summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:50:17 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:50:17 +0000
commit86ed03f8adee56c050c73018537371c230a664a6 (patch)
treeeae3d04cdf1c49848e5a671327ab38297f4acb0d
parentInitial commit. (diff)
downloadfence-agents-upstream.tar.xz
fence-agents-upstream.zip
Adding upstream version 4.12.1.upstream/4.12.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--.gitignore75
-rw-r--r--Makefile.am142
-rw-r--r--README.md18
-rw-r--r--agents/Makefile.am123
-rw-r--r--agents/aliyun/fence_aliyun.py192
-rw-r--r--agents/alom/fence_alom.py53
-rw-r--r--agents/amt/fence_amt.py128
-rwxr-xr-xagents/amt_ws/fence_amt_ws.py240
-rw-r--r--agents/apc/fence_apc.py263
-rw-r--r--agents/apc_snmp/README45
-rw-r--r--agents/apc_snmp/fence_apc_snmp.py232
-rw-r--r--agents/apc_snmp/powernet369.mib31109
-rw-r--r--agents/autodetect/a.py8
-rwxr-xr-xagents/autodetect/autodetect.py255
-rwxr-xr-xagents/autodetect/autodetect_test.py33
-rw-r--r--agents/autodetect/b.py2
-rw-r--r--agents/autodetect/fence_apc.py259
-rw-r--r--agents/autodetect/fence_bladecenter.py111
-rw-r--r--agents/autodetect/fence_brocade.py78
-rw-r--r--agents/autodetect/fence_ilo_moonshot.py69
-rw-r--r--agents/autodetect/fence_lpar.py159
-rw-r--r--agents/autodetect/fencing.py1393
-rw-r--r--agents/aws/fence_aws.py223
-rwxr-xr-xagents/azure_arm/fence_azure_arm.py260
-rw-r--r--agents/bladecenter/fence_bladecenter.py105
-rw-r--r--agents/brocade/fence_brocade.py72
-rw-r--r--agents/cdu/fence_cdu.py176
-rw-r--r--agents/cisco_mds/fence_cisco_mds.py94
-rw-r--r--agents/cisco_ucs/fence_cisco_ucs.py198
-rw-r--r--agents/compute/fence_compute.py516
-rw-r--r--agents/crosslink/README.md44
-rwxr-xr-xagents/crosslink/fence_crosslink.py113
-rwxr-xr-xagents/cyberpower_ssh/fence_cyberpower_ssh.py70
-rw-r--r--agents/docker/fence_docker.py161
-rw-r--r--agents/drac/fence_drac.py62
-rw-r--r--agents/drac5/fence_drac5.py147
-rw-r--r--agents/dummy/fence_dummy.py133
-rw-r--r--agents/eaton_snmp/README20
-rw-r--r--agents/eaton_snmp/fence_eaton_snmp.py229
-rw-r--r--agents/ecloud/fence_ecloud.py169
-rw-r--r--agents/emerson/fence_emerson.py62
-rw-r--r--agents/eps/fence_eps.py129
-rw-r--r--agents/evacuate/fence_evacuate.py428
-rw-r--r--agents/gce/fence_gce.py632
-rwxr-xr-xagents/hds_cb/fence_hds_cb.py132
-rw-r--r--agents/heuristics_ping/fence_heuristics_ping.py198
-rw-r--r--agents/hpblade/fence_hpblade.py134
-rwxr-xr-xagents/ibm_powervs/fence_ibm_powervs.py267
-rwxr-xr-xagents/ibm_vpc/fence_ibm_vpc.py316
-rw-r--r--agents/ibmblade/fence_ibmblade.py72
-rw-r--r--agents/ibmz/fence_ibmz.py566
-rw-r--r--agents/ifmib/README45
-rw-r--r--agents/ifmib/fence_ifmib.py116
-rw-r--r--agents/ilo/fence_ilo.py143
-rw-r--r--agents/ilo_moonshot/fence_ilo_moonshot.py65
-rw-r--r--agents/ilo_mp/fence_ilo_mp.py58
-rw-r--r--agents/ilo_ssh/fence_ilo_ssh.py77
-rw-r--r--agents/intelmodular/fence_intelmodular.py86
-rw-r--r--agents/ipdu/fence_ipdu.py153
-rw-r--r--agents/ipmilan/fence_ipmilan.py233
-rw-r--r--agents/ironic/fence_ironic.py130
-rw-r--r--agents/kdump/fence_kdump.c592
-rw-r--r--agents/kdump/fence_kdump_send.850
-rw-r--r--agents/kdump/fence_kdump_send.c255
-rw-r--r--agents/kdump/list.h573
-rw-r--r--agents/kdump/message.h41
-rw-r--r--agents/kdump/options.h260
-rw-r--r--agents/kdump/version.h33
-rwxr-xr-xagents/kubevirt/fence_kubevirt.py154
-rw-r--r--agents/ldom/fence_ldom.py102
-rw-r--r--agents/lindy_pdu/fence_lindypdu.py206
-rw-r--r--agents/lpar/fence_lpar.py197
-rw-r--r--agents/manual/fence_ack_manual.839
-rw-r--r--agents/manual/fence_ack_manual.in37
-rw-r--r--agents/mpath/fence_mpath.py341
-rwxr-xr-xagents/netio/fence_netio.py94
-rw-r--r--agents/openstack/fence_openstack.py381
-rw-r--r--agents/ovh/fence_ovh.py164
-rwxr-xr-xagents/powerman/fence_powerman.py257
-rwxr-xr-xagents/pve/fence_pve.py240
-rw-r--r--agents/raritan/fence_raritan.py87
-rw-r--r--agents/raritan_px3/fence_raritan_px3.py195
-rw-r--r--agents/rcd_serial/fence_rcd_serial.py100
-rw-r--r--agents/rcd_serial/rcd_serial_cable_diagram.svg276
-rw-r--r--agents/redfish/fence_redfish.py177
-rw-r--r--agents/rhevm/fence_rhevm.py249
-rw-r--r--agents/rsa/fence_rsa.py63
-rwxr-xr-xagents/rsb/fence_rsb.py70
-rw-r--r--agents/sanbox2/fence_sanbox2.py155
-rw-r--r--agents/sbd/fence_sbd.py435
-rw-r--r--agents/scsi/fence_scsi.py598
-rw-r--r--agents/skalar/fence_skalar.py226
-rw-r--r--agents/vbox/fence_vbox.py135
-rw-r--r--agents/virsh/fence_virsh.py96
-rw-r--r--agents/virt/Makefile.am31
-rw-r--r--agents/virt/client/Makefile.am40
-rw-r--r--agents/virt/client/main.c198
-rw-r--r--agents/virt/client/mcast.c393
-rw-r--r--agents/virt/client/options.c1000
-rw-r--r--agents/virt/client/serial.c311
-rw-r--r--agents/virt/client/tcp.c171
-rw-r--r--agents/virt/client/vsock.c176
-rw-r--r--agents/virt/common/Makefile.am24
-rw-r--r--agents/virt/common/bcast.c347
-rw-r--r--agents/virt/common/debug.c38
-rw-r--r--agents/virt/common/fdops.c202
-rw-r--r--agents/virt/common/ip_lookup.c326
-rw-r--r--agents/virt/common/log.c204
-rw-r--r--agents/virt/common/mcast.c388
-rw-r--r--agents/virt/common/simple_auth.c466
-rw-r--r--agents/virt/common/tcp.c386
-rw-r--r--agents/virt/config/Makefile.am44
-rw-r--r--agents/virt/config/config-stack.h38
-rw-r--r--agents/virt/config/config.l106
-rw-r--r--agents/virt/config/config.y140
-rw-r--r--agents/virt/config/fence_virt.conf20
-rw-r--r--agents/virt/config/simpleconfig.c494
-rw-r--r--agents/virt/docs/README125
-rw-r--r--agents/virt/docs/TODO7
-rw-r--r--agents/virt/docs/architecture.txt16
-rw-r--r--agents/virt/docs/fence_virt.txt127
-rw-r--r--agents/virt/fence_virtd.service.in23
-rw-r--r--agents/virt/include/bcast.h16
-rw-r--r--agents/virt/include/client.h9
-rw-r--r--agents/virt/include/debug.h31
-rw-r--r--agents/virt/include/fdops.h14
-rw-r--r--agents/virt/include/history.h25
-rw-r--r--agents/virt/include/ip_lookup.h40
-rw-r--r--agents/virt/include/list.h84
-rw-r--r--agents/virt/include/mcast.h32
-rw-r--r--agents/virt/include/options.h99
-rw-r--r--agents/virt/include/server_plugin.h130
-rw-r--r--agents/virt/include/simple_auth.h35
-rw-r--r--agents/virt/include/simpleconfig.h56
-rw-r--r--agents/virt/include/static_map.h34
-rw-r--r--agents/virt/include/tcp.h27
-rw-r--r--agents/virt/include/tcp_listener.h7
-rw-r--r--agents/virt/include/xvm.h158
-rw-r--r--agents/virt/man/.gitignore2
-rw-r--r--agents/virt/man/Makefile.am28
-rw-r--r--agents/virt/man/fence_virt.conf.5335
-rw-r--r--agents/virt/man/fence_virtd.853
-rw-r--r--agents/virt/man/fence_xvm.81
-rw-r--r--agents/virt/server/Makefile.am79
-rw-r--r--agents/virt/server/config.c698
-rw-r--r--agents/virt/server/cpg-virt.c643
-rw-r--r--agents/virt/server/cpg.c411
-rw-r--r--agents/virt/server/cpg.h29
-rw-r--r--agents/virt/server/daemon_init.c215
-rw-r--r--agents/virt/server/history.c124
-rw-r--r--agents/virt/server/libvirt.c359
-rw-r--r--agents/virt/server/main.c281
-rw-r--r--agents/virt/server/mcast.c622
-rw-r--r--agents/virt/server/plugin.c417
-rw-r--r--agents/virt/server/serial.c459
-rw-r--r--agents/virt/server/serial.h20
-rw-r--r--agents/virt/server/static_map.c237
-rw-r--r--agents/virt/server/tcp.c575
-rw-r--r--agents/virt/server/uuid-test.c66
-rw-r--r--agents/virt/server/uuid-test.h14
-rw-r--r--agents/virt/server/virt-serial.c444
-rw-r--r--agents/virt/server/virt-sockets.c242
-rw-r--r--agents/virt/server/virt.c630
-rw-r--r--agents/virt/server/virt.h62
-rw-r--r--agents/virt/server/vsock.c565
-rw-r--r--agents/vmware/fence_vmware.py336
-rw-r--r--agents/vmware/fence_vmware_helper.pl276
-rw-r--r--agents/vmware_rest/fence_vmware_rest.py229
-rw-r--r--agents/vmware_soap/fence_vmware_soap.py265
-rw-r--r--agents/vmware_vcloud/fence_vmware_vcloud.py214
-rw-r--r--agents/wti/fence_wti.py240
-rw-r--r--agents/xenapi/fence_xenapi.py221
-rw-r--r--agents/zvm/fence_zvm.c1056
-rw-r--r--agents/zvm/fence_zvm.h583
-rw-r--r--agents/zvm/fence_zvm_man_page88
-rw-r--r--agents/zvm/fence_zvmip.c1001
-rw-r--r--agents/zvm/fence_zvmip.py226
-rwxr-xr-xautogen.sh4
-rw-r--r--configure.ac593
-rw-r--r--doc/COPYING.applications339
-rw-r--r--doc/COPYING.libraries510
-rw-r--r--doc/COPYRIGHT86
-rw-r--r--doc/FenceAgentAPI.md196
-rw-r--r--doc/Makefile.am6
-rw-r--r--doc/README.licence33
-rw-r--r--fence-agents.pc.in7
-rw-r--r--fence-agents.spec.in1445
-rw-r--r--lib/Makefile.am34
-rw-r--r--lib/XenAPI.py.py212
-rw-r--r--lib/azure_fence.py.py393
-rw-r--r--lib/check_used_options.py68
-rw-r--r--lib/fence.rng.head7
-rw-r--r--lib/fence.rng.tail13
-rw-r--r--lib/fence2man.xsl78
-rw-r--r--lib/fence2rng.xsl184
-rw-r--r--lib/fence2wiki.xsl14
-rw-r--r--lib/fencing.py.py1748
-rw-r--r--lib/fencing_snmp.py.py128
-rw-r--r--lib/metadata.rng80
-rw-r--r--lib/tests/test_fencing.py123
-rw-r--r--m4/PKG_CHECK_VAR.m424
-rw-r--r--m4/ac_python_module.m430
-rw-r--r--m4/ax_check_link_flag.m474
-rw-r--r--m4/ax_prog_date.m4137
-rw-r--r--m4/ax_pthread.m4485
-rw-r--r--make/agentccheck.mk32
-rw-r--r--make/agentpycheck.mk44
-rw-r--r--make/fencebuild.mk84
-rw-r--r--make/fenceman.mk11
-rwxr-xr-xmake/git-version-gen161
-rwxr-xr-xmake/gitlog-to-changelog191
-rw-r--r--make/release.mk82
-rw-r--r--systemd/Makefile.am24
-rw-r--r--systemd/fence-agents.conf.in1
-rw-r--r--tests/actions.d/list.cfg2
-rw-r--r--tests/actions.d/power-on-off.cfg2
-rw-r--r--tests/actions.d/sleep.cfg2
-rw-r--r--tests/actions.d/status.cfg2
-rw-r--r--tests/data/metadata/fence_aliyun.xml138
-rw-r--r--tests/data/metadata/fence_alom.xml204
-rw-r--r--tests/data/metadata/fence_amt.xml188
-rw-r--r--tests/data/metadata/fence_amt_ws.xml170
-rw-r--r--tests/data/metadata/fence_apc.xml215
-rw-r--r--tests/data/metadata/fence_apc_snmp.xml225
-rw-r--r--tests/data/metadata/fence_aws.xml146
-rw-r--r--tests/data/metadata/fence_azure_arm.xml198
-rw-r--r--tests/data/metadata/fence_bladecenter.xml215
-rw-r--r--tests/data/metadata/fence_brocade.xml209
-rw-r--r--tests/data/metadata/fence_cdu.xml172
-rw-r--r--tests/data/metadata/fence_cisco_mds.xml223
-rw-r--r--tests/data/metadata/fence_cisco_ucs.xml197
-rw-r--r--tests/data/metadata/fence_compute.xml222
-rw-r--r--tests/data/metadata/fence_crosslink.xml128
-rw-r--r--tests/data/metadata/fence_cyberpower_ssh.xml206
-rw-r--r--tests/data/metadata/fence_docker.xml180
-rw-r--r--tests/data/metadata/fence_drac.xml175
-rw-r--r--tests/data/metadata/fence_drac5.xml219
-rw-r--r--tests/data/metadata/fence_dummy.xml115
-rw-r--r--tests/data/metadata/fence_eaton_snmp.xml224
-rw-r--r--tests/data/metadata/fence_ecloud.xml123
-rw-r--r--tests/data/metadata/fence_emerson.xml224
-rw-r--r--tests/data/metadata/fence_eps.xml175
-rw-r--r--tests/data/metadata/fence_evacuate.xml218
-rw-r--r--tests/data/metadata/fence_gce.xml213
-rw-r--r--tests/data/metadata/fence_hds_cb.xml215
-rw-r--r--tests/data/metadata/fence_heuristics_ping.xml140
-rw-r--r--tests/data/metadata/fence_hpblade.xml215
-rw-r--r--tests/data/metadata/fence_ibm_powervs.xml153
-rw-r--r--tests/data/metadata/fence_ibm_vpc.xml142
-rw-r--r--tests/data/metadata/fence_ibmblade.xml224
-rw-r--r--tests/data/metadata/fence_ibmz.xml198
-rw-r--r--tests/data/metadata/fence_idrac.xml238
-rw-r--r--tests/data/metadata/fence_ifmib.xml225
-rw-r--r--tests/data/metadata/fence_ilo.xml201
-rw-r--r--tests/data/metadata/fence_ilo2.xml201
-rw-r--r--tests/data/metadata/fence_ilo3.xml238
-rw-r--r--tests/data/metadata/fence_ilo3_ssh.xml221
-rw-r--r--tests/data/metadata/fence_ilo4.xml238
-rw-r--r--tests/data/metadata/fence_ilo4_ssh.xml221
-rw-r--r--tests/data/metadata/fence_ilo5.xml238
-rw-r--r--tests/data/metadata/fence_ilo5_ssh.xml221
-rw-r--r--tests/data/metadata/fence_ilo_moonshot.xml206
-rw-r--r--tests/data/metadata/fence_ilo_mp.xml208
-rw-r--r--tests/data/metadata/fence_ilo_ssh.xml221
-rw-r--r--tests/data/metadata/fence_imm.xml238
-rw-r--r--tests/data/metadata/fence_intelmodular.xml226
-rw-r--r--tests/data/metadata/fence_ipdu.xml224
-rw-r--r--tests/data/metadata/fence_ipmilan.xml238
-rw-r--r--tests/data/metadata/fence_ipmilanplus.xml238
-rw-r--r--tests/data/metadata/fence_ironic.xml177
-rw-r--r--tests/data/metadata/fence_kdump.xml79
-rw-r--r--tests/data/metadata/fence_kubevirt.xml138
-rw-r--r--tests/data/metadata/fence_ldom.xml208
-rw-r--r--tests/data/metadata/fence_lindypdu.xml229
-rw-r--r--tests/data/metadata/fence_lpar.xml220
-rw-r--r--tests/data/metadata/fence_mpath.xml155
-rw-r--r--tests/data/metadata/fence_netio.xml167
-rw-r--r--tests/data/metadata/fence_openstack.xml218
-rw-r--r--tests/data/metadata/fence_ovh.xml152
-rw-r--r--tests/data/metadata/fence_powerman.xml135
-rw-r--r--tests/data/metadata/fence_pve.xml215
-rw-r--r--tests/data/metadata/fence_raritan.xml167
-rw-r--r--tests/data/metadata/fence_raritan_px3.xml210
-rw-r--r--tests/data/metadata/fence_rcd_serial.xml111
-rw-r--r--tests/data/metadata/fence_redfish.xml201
-rw-r--r--tests/data/metadata/fence_rhevm.xml210
-rw-r--r--tests/data/metadata/fence_rsa.xml208
-rw-r--r--tests/data/metadata/fence_rsb.xml208
-rw-r--r--tests/data/metadata/fence_sanbox2.xml176
-rw-r--r--tests/data/metadata/fence_sbd.xml135
-rw-r--r--tests/data/metadata/fence_scsi.xml169
-rw-r--r--tests/data/metadata/fence_skalar.xml192
-rw-r--r--tests/data/metadata/fence_tripplite_snmp.xml225
-rw-r--r--tests/data/metadata/fence_vbox.xml240
-rw-r--r--tests/data/metadata/fence_virsh.xml227
-rw-r--r--tests/data/metadata/fence_virt.xml101
-rw-r--r--tests/data/metadata/fence_vmware.xml217
-rw-r--r--tests/data/metadata/fence_vmware_rest.xml198
-rw-r--r--tests/data/metadata/fence_vmware_soap.xml189
-rw-r--r--tests/data/metadata/fence_vmware_vcloud.xml191
-rw-r--r--tests/data/metadata/fence_wti.xml210
-rw-r--r--tests/data/metadata/fence_xenapi.xml153
-rw-r--r--tests/data/metadata/fence_zvmip.xml225
-rw-r--r--tests/devices.d/dummy-with_action.cfg9
-rw-r--r--tests/devices.d/dummy.cfg3
-rw-r--r--tests/devices.d/invalid-missing_option.cfg4
-rw-r--r--tests/devices.d/true-with_action.cfg8
-rw-r--r--tests/devices.d/true.cfg8
-rwxr-xr-xtests/fence_testing.py126
-rwxr-xr-xtests/fence_testing_test.py70
-rwxr-xr-xtests/test-apc2.py17
-rwxr-xr-xtests/test-apc5.py17
-rwxr-xr-xtests/test-drac4.py15
-rwxr-xr-xtests/test-multi-apc2.py17
-rwxr-xr-xtests/test.py21
315 files changed, 92193 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0ac1c6a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,75 @@
+*.orig
+*.rej
+*.swp
+Makefile.in
+aclocal.m4
+autoconf
+autoheader
+autom4te.cache
+automake
+autoscan.log
+compile
+configure
+configure.scan
+config.guess
+config.log
+config.sub
+config.status
+Makefile
+depcomp
+install-sh
+libtoolize
+ltmain.sh
+libtool
+make/stamp-h1
+
+# ignore "libtoolized" m4 files, but keep our (enumerated) ones
+/m4/*
+!/m4/ac_python_module.m4
+!/m4/ax*.m4
+
+# make/release.mk related litter
+/.tarball-version
+/tag-*
+
+make/config.h*
+missing
+*.pc
+.deps
+.libs
+*.o
+*.la
+*.lo
+lib/*.py*
+lib/__pycache__
+!lib/*.py.py
+!lib/check_used_options.py
+agents/*/fence_*
+agents/*/.dirstamp
+!agents/*/fence_*.py
+!agents/*/fence_*.c
+!agents/*/fence_*.h
+!agents/kdump/fence_kdump_send.8
+!agents/manual/fence_ack_manual.8
+!agents/zvm/fence_zvm_man_page
+.fence*.tmp
+fence-agents*
+.version
+tests/devices.d/*
+
+y.tab.*
+*.o
+*.lo
+*.la
+.deps
+.libs
+.*version
+*.swp
+agents/virt/client/fence_virt
+agents/virt/client/fence_xvm
+agents/virt/common/libfence_virt.a
+agents/virt/config/config.c
+agents/virt/config/libsimpleconfig.a
+agents/virt/fence_virtd.service
+agents/virt/server/fence_virtd
+fence-virt-*
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..a4cd64c
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,142 @@
+pkgconfigdir = $(datadir)/pkgconfig
+pkgconfig_DATA = $(PACKAGE_NAME).pc
+
+SPEC = $(PACKAGE_NAME).spec
+
+EXTRA_DIST = autogen.sh make/fencebuild.mk \
+ .version make/release.mk \
+ make/git-version-gen make/gitlog-to-changelog tests \
+ $(pkgconfig_DATA).in $(SPEC).in
+
+AUTOMAKE_OPTIONS = foreign
+
+MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure depcomp \
+ config.guess config.sub missing install-sh \
+ autoheader automake autoconf libtool libtoolize \
+ ltmain.sh compile make/config.h.in \
+ make/config.h.in~ autoscan.log \
+ configure.scan
+
+TARFILES = $(PACKAGE_NAME)-$(VERSION).tar.bz2 \
+ $(PACKAGE_NAME)-$(VERSION).tar.gz \
+ $(PACKAGE_NAME)-$(VERSION).tar.xz
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = lib agents doc systemd
+
+.PHONY: $(SUBDIRS)
+
+agents: lib
+
+doc: agents
+
+install-exec-local:
+ $(INSTALL) -d $(DESTDIR)/$(LOGDIR)
+ $(INSTALL) -d $(DESTDIR)/$(CLUSTERVARRUN)
+ $(INSTALL) -d -m 1755 $(DESTDIR)$(FENCETMPDIR)
+
+uninstall-local:
+ rmdir $(DESTDIR)/$(LOGDIR) || :;
+ rmdir $(DESTDIR)/$(CLUSTERVARRUN) || :;
+
+BUILT_SOURCES = .version
+.version:
+ echo $(VERSION) > $@-t && mv $@-t $@
+
+dist-hook: gen-ChangeLog
+ echo $(VERSION) > $(distdir)/.tarball-version
+
+gen_start_date = 2000-01-01
+.PHONY: gen-ChangeLog
+gen-ChangeLog:
+ if test -d .git; then \
+ $(top_srcdir)/make/gitlog-to-changelog \
+ --since=$(gen_start_date) > $(distdir)/cl-t; \
+ rm -f $(distdir)/ChangeLog; \
+ mv $(distdir)/cl-t $(distdir)/ChangeLog; \
+ fi
+
+# this will get rid of "libtoolized" m4 files
+maintainer-clean-local:
+ rm -rf $(filter-out \
+ $(top_srcdir)/m4/ax_check_link_flag.m4 \
+ $(top_srcdir)/m4/ax_prog_date.m4 \
+ $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/ac_python_module.m4 \
+ $(top_srcdir)/m4/PKG_CHECK_VAR.m4, \
+ $(wildcard $(top_srcdir)/m4/*.m4))
+
+## make rpm/srpm section.
+$(SPEC): $(SPEC).in
+ rm -f $@-t $@
+ date="$(shell LC_ALL=C date "+%a %b %d %Y")" && \
+ specver="1" && \
+ rcver="" && \
+ dirty="" && \
+ alphatag="" && \
+ numcomm="" && \
+ ver="$(VERSION)" && \
+ if echo $$ver | grep -q -- "-dirty$$"; then \
+ dirty="dirty" && \
+ echo VERSION IS DIRTY && \
+ ver=`echo $$ver | sed -e "s/-dirty$$//"`; \
+ fi && \
+ echo $$ver && \
+ if echo $$ver | grep -q -- "-"; then \
+ alphatag=`echo $$ver | sed -e "s/.*-//"` && \
+ echo VERSION HAS ALPHATAG && \
+ ver=`echo $$ver | sed -e "s/-.*//"`; \
+ fi && \
+ echo $$ver && \
+ if [ -n "$$alphatag" ]; then \
+ echo VERSION HAS NUMCOMMITS && \
+ numcomm=`echo $$ver | sed -e 's/.*\.//'` && \
+ ver=`echo $$ver | sed -e 's/.'$$numcomm'$$//'`; \
+ fi && \
+ if echo $$ver | grep -q "\.[[:digit:]]rc[[:digit:]]"; then \
+ rpmver=`echo $$ver | sed -e "s/rc[[:digit:]].*//g"` && \
+ rcver=`echo $$ver | sed -e "s/.*\(rc[[:digit:]]\).*/\1/g"` && \
+ specver="0"; \
+ else \
+ rpmver=$$ver; \
+ fi && \
+ echo $$rpmver $$rcver && \
+ sed \
+ -e "s#@version@#$$rpmver#g" \
+ -e "s#@alphatag@#$$alphatag#g" \
+ -e "s#@numcomm@#$$numcomm#g" \
+ -e "s#@dirty@#$$dirty#g" \
+ -e "s#@date@#$$date#g" \
+ -e "s#@specver@#$$specver#g" \
+ -e "s#@rcver@#$$rcver#g" \
+ -e "s#@rgmanager@#$(RGMANAGER)#g" \
+ -e "s#@linux-ha@#$(LINUX_HA)#g" \
+ -e "s#@compat-habindir@#$(COMPAT_HABINDIR)#g" \
+ $< > $@-t; \
+ if [ -z "$$dirty" ]; then sed -i -e "s#%glo.*dirty.*##g" $@-t; fi; \
+ if [ -z "$$alphatag" ]; then sed -i -e "s#%glo.*alphatag.*##g" $@-t; fi; \
+ if [ -z "$$numcomm" ]; then sed -i -e "s#%glo.*numcomm.*##g" $@-t; fi; \
+ if [ -z "$$rcver" ]; then sed -i -e "s#%glo.*rcver.*##g" $@-t; fi
+ chmod a-w $@-t
+ mv $@-t $@
+
+$(TARFILES):
+ $(MAKE) dist
+
+RPMBUILDOPTS = --define "_sourcedir $(abs_builddir)" \
+ --define "_specdir $(abs_builddir)" \
+ --define "_builddir $(abs_builddir)" \
+ --define "_srcrpmdir $(abs_builddir)" \
+ --define "_rpmdir $(abs_builddir)"
+
+srpm: clean
+ $(MAKE) $(SPEC) $(TARFILES)
+ rpmbuild $(RPMBUILDOPTS) --nodeps -bs $(SPEC)
+
+rpm: clean
+ $(MAKE) $(SPEC) $(TARFILES)
+ PYTHON="$(PYTHON)" rpmbuild $(RPMBUILDOPTS) -ba $(SPEC)
+
+clean-generic:
+ rm -rf $(SPEC) $(TARFILES) $(PACKAGE_NAME)-$(VERSION) *.rpm
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d9fcb94
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# Fence agents
+
+Fence agents were developed as device "drivers" which are able to prevent computers from destroying data on shared storage. Their aim is to isolate a corrupted computer, using one of three methods:
+
+ * Power - A computer that is switched off cannot corrupt data, but it is important to not do a "soft-reboot" as we won't know if this is possible. This also works for virtual machines when the fence device is a hypervisor.
+ * Network - Switches can prevent routing to a given computer, so even if a computer is powered on it won't be able to harm the data.
+ * Configuration - Fibre-channel switches or SCSI devices allow us to limit who can write to managed disks.
+
+Fence agents do not use configuration files, as configuration management is outside of their scope. All of the configuration has to be specified either as command-line arguments or lines of standard input (see the complete list for more info).
+
+Because many fence agents are quite similar to each other, a fencing library (in Python) was developed. Please use it for further development. Creating or modifying a new fence agent should be quite simple using this library.
+
+## Where can I find more information?
+
+* [ClusterLabs website](http://www.clusterlabs.org/)
+* [User and developer documentation](https://github.com/ClusterLabs/fence-agents/tree/master/doc/FenceAgentAPI.md)
+* Mailing lists for [users](http://oss.clusterlabs.org/mailman/listinfo/users) and [developers](http://oss.clusterlabs.org/mailman/listinfo/developers)
+* #clusterlabs IRC channel on [freenode](http://freenode.net/)
diff --git a/agents/Makefile.am b/agents/Makefile.am
new file mode 100644
index 0000000..88e0c60
--- /dev/null
+++ b/agents/Makefile.am
@@ -0,0 +1,123 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+TARGET = $(AGENTS_LIST:%.py=%)
+
+SRC = $(TARGET:=.py)
+
+CLEAN_TARGET_ADDITIONAL = kdump/fence_kdump_send manual/fence_ack_manual */*.o
+
+EXTRA_DIST = $(SRC)
+
+sbin_PROGRAMS =
+sbin_SCRIPTS = $(TARGET)
+libexec_PROGRAMS =
+
+noinst_HEADERS = kdump/list.h kdump/message.h kdump/options.h kdump/version.h zvm/fence_zvm.h
+
+man_MANS = $(sbin_SCRIPTS:=.8)
+dist_man_MANS =
+
+EXTRA_SCRIPTS =
+
+if BUILD_FENCE_VIRT
+SUBDIRS = virt
+endif
+
+if BUILD_FENCE_KDUMP
+sbin_PROGRAMS += kdump/fence_kdump
+libexec_PROGRAMS += kdump/fence_kdump_send
+
+man_MANS += kdump/fence_kdump.8
+dist_man_MANS += kdump/fence_kdump_send.8
+
+kdump_fence_kdump_SOURCES = kdump/fence_kdump.c
+kdump_fence_kdump_CFLAGS = -D_GNU_SOURCE -Ikdump $(AM_CFLAGS) -Wno-cast-align
+
+kdump_fence_kdump_send_SOURCES = kdump/fence_kdump_send.c
+kdump_fence_kdump_send_CFLAGS = -D_GNU_SOURCE -Ikdump $(AM_CFLAGS) -Wno-cast-align
+endif
+
+if BUILD_FENCE_MANUAL
+EXTRA_DIST += manual/fence_ack_manual.in manual/fence_ack_manual.8
+
+sbin_SCRIPTS += manual/fence_ack_manual
+endif
+
+if BUILD_FENCE_ZVM
+EXTRA_DIST += zvm/fence_zvm_man_page
+
+sbin_PROGRAMS += zvm/fence_zvm
+
+man_MANS += zvm/fence_zvm.8
+
+zvm_fence_zvm_SOURCES = zvm/fence_zvm.c
+zvm_fence_zvm_CFLAGS = -D_GNU_SOURCE -Izvm $(AM_CFLAGS)
+endif
+
+if BUILD_FENCE_MPATH
+mpathdatadir = $(CLUSTERDATA)
+mpathdata_SCRIPTS = mpath/fence_mpath_check mpath/fence_mpath_check_hardreboot
+endif
+
+if BUILD_FENCE_SCSI
+scsidatadir = $(CLUSTERDATA)
+scsidata_SCRIPTS = scsi/fence_scsi_check scsi/fence_scsi_check_hardreboot
+endif
+
+FENCE_TEST_ARGS = \
+login=test\n\
+passwd=test\n\
+ipaddr=test\n\
+port=1\n\
+managed=1\n\
+devices=test\n\
+session_url=http://test\n\
+email=test@test.te\n\
+ping_targets=localhost
+
+manual/fence_ack_manual: manual/fence_ack_manual.in
+ mkdir -p $(@D)
+ cat $^ | sed \
+ -e 's#@clustervarrun@#${CLUSTERVARRUN}#g' \
+ > $@
+
+mpath/fence_mpath_check: mpath/fence_mpath
+ cp $^ $@
+
+mpath/fence_mpath_check_hardreboot: mpath/fence_mpath
+ cp $^ $@
+
+scsi/fence_scsi_check: scsi/fence_scsi
+ cp $^ $@
+
+scsi/fence_scsi_check_hardreboot: scsi/fence_scsi
+ cp $^ $@
+
+kdump/fence_kdump.8: kdump/fence_kdump $(top_srcdir)/lib/fence2man.xsl
+ set -e && \
+ ./$(@:%.8=%) -o metadata > $(@D)/.$(@F).tmp && \
+ xmllint --noout --relaxng $(top_srcdir)/lib/metadata.rng $(@D)/.$(@F).tmp && \
+ xsltproc $(top_srcdir)/lib/fence2man.xsl $(@D)/.$(@F).tmp > $@
+ xsltproc $(top_srcdir)/lib/fence2wiki.xsl $(@D)/.$(@F).tmp | grep -v '<?xml' > $(@D)/$(@F:%.8=%.wiki)
+
+kdump/fence_kdump_send.8:
+ true
+
+manual/fence_ack_manual.8:
+ true
+
+zvm/fence_zvm.8: zvm/fence_zvm
+ cp $(top_srcdir)/agents/zvm/fence_zvm_man_page $(@D)/fence_zvm.8
+
+cisco_mds/fence_cisco_mds.delay-check: cisco_mds/fence_cisco_mds
+ $(eval INPUT=$(subst .delay-check,,$@))
+ FENCE_TEST_ARGS_CISCO_MDS=$$(printf '$(FENCE_TEST_ARGS)' | sed 's#port=1#port=fc1/1#'); \
+ test `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \
+ sh -c "printf 'delay=10\n $$FENCE_TEST_ARGS_CISCO_MDS' | $(PYTHON) ./$(INPUT)" 2>&1 |\
+ awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}'` -ge 1000 || ( \
+ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \
+ sh -c "printf "delay=0\n $$FENCE_TEST_ARGS_CISCO_MDS" | $(PYTHON) ./$(INPUT)"; false )
+
+include $(top_srcdir)/make/fencebuild.mk
+include $(top_srcdir)/make/fenceman.mk
+include $(top_srcdir)/make/agentpycheck.mk
diff --git a/agents/aliyun/fence_aliyun.py b/agents/aliyun/fence_aliyun.py
new file mode 100644
index 0000000..1e9c790
--- /dev/null
+++ b/agents/aliyun/fence_aliyun.py
@@ -0,0 +1,192 @@
+#!@PYTHON@ -tt
+
+import sys
+import logging
+import atexit
+import json
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, run_delay
+
+
+try:
+ from aliyunsdkcore import client
+ from aliyunsdkcore.auth.credentials import EcsRamRoleCredential
+ from aliyunsdkcore.profile import region_provider
+except ImportError as e:
+ logging.warn("The 'aliyunsdkcore' module has been not installed or is unavailable, try to execute the command 'pip install aliyun-python-sdk-core --upgrade' to solve. error: %s" % e)
+
+
+try:
+ from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
+ from aliyunsdkecs.request.v20140526.StartInstanceRequest import StartInstanceRequest
+ from aliyunsdkecs.request.v20140526.StopInstanceRequest import StopInstanceRequest
+ from aliyunsdkecs.request.v20140526.RebootInstanceRequest import RebootInstanceRequest
+except ImportError as e:
+ logging.warn("The 'aliyunsdkecs' module has been not installed or is unavailable, try to execute the command 'pip install aliyun-python-sdk-ecs --upgrade' to solve. error: %s" % e)
+
+
+def _send_request(conn, request):
+ logging.debug("send request action: %s" % request.get_action_name())
+ request.set_accept_format('json')
+ try:
+ response_str = conn.do_action_with_exception(request)
+ except Exception as e:
+ fail_usage("Failed: send request failed: Error: %s" % e)
+
+ response_detail = json.loads(response_str)
+ logging.debug("reponse: %s" % response_detail)
+ return response_detail
+
+def start_instance(conn, instance_id):
+ logging.debug("start instance %s" % instance_id)
+ request = StartInstanceRequest()
+ request.set_InstanceId(instance_id)
+ _send_request(conn, request)
+
+def stop_instance(conn, instance_id):
+ logging.debug("stop instance %s" % instance_id)
+ request = StopInstanceRequest()
+ request.set_InstanceId(instance_id)
+ request.set_ForceStop('true')
+ _send_request(conn, request)
+
+def reboot_instance(conn, instance_id):
+ logging.debug("reboot instance %s" % instance_id)
+ request = RebootInstanceRequest()
+ request.set_InstanceId(instance_id)
+ request.set_ForceStop('true')
+ _send_request(conn, request)
+
+def get_status(conn, instance_id):
+ logging.debug("get instance %s status" % instance_id)
+ request = DescribeInstancesRequest()
+ request.set_InstanceIds(json.dumps([instance_id]))
+ response = _send_request(conn, request)
+ instance_status = None
+ if response is not None:
+ instance_list = response.get('Instances').get('Instance')
+ for item in instance_list:
+ instance_status = item.get('Status')
+ return instance_status
+
+def get_nodes_list(conn, options):
+ logging.debug("start to get nodes list")
+ result = {}
+ request = DescribeInstancesRequest()
+ request.set_PageSize(100)
+ response = _send_request(conn, request)
+ if response is not None:
+ instance_list = response.get('Instances').get('Instance')
+ for item in instance_list:
+ instance_id = item.get('InstanceId')
+ instance_name = item.get('InstanceName')
+ result[instance_id] = (instance_name, None)
+ logging.debug("get nodes list: %s" % result)
+ return result
+
+def get_power_status(conn, options):
+ logging.debug("start to get power(%s) status" % options["--plug"])
+ state = get_status(conn, options["--plug"])
+
+ if state == "Running":
+ status = "on"
+ elif state == "Stopped":
+ status = "off"
+ else:
+ status = "unknown"
+ logging.debug("the power(%s) status is %s" % (options["--plug"], status))
+ return status
+
+def set_power_status(conn, options):
+ logging.info("start to set power(%s) status to %s" % (options["--plug"], options["--action"]))
+
+ if (options["--action"]=="off"):
+ stop_instance(conn, options["--plug"])
+ elif (options["--action"]=="on"):
+ start_instance(conn, options["--plug"])
+ elif (options["--action"]=="reboot"):
+ reboot_instance(conn, options["--plug"])
+
+def define_new_opts():
+ all_opt["region"] = {
+ "getopt" : "r:",
+ "longopt" : "region",
+ "help" : "-r, --region=[name] Region, e.g. cn-hangzhou",
+ "shortdesc" : "Region.",
+ "required" : "0",
+ "order" : 2
+ }
+ all_opt["access_key"] = {
+ "getopt" : "a:",
+ "longopt" : "access-key",
+ "help" : "-a, --access-key=[name] Access Key",
+ "shortdesc" : "Access Key.",
+ "required" : "0",
+ "order" : 3
+ }
+ all_opt["secret_key"] = {
+ "getopt" : "s:",
+ "longopt" : "secret-key",
+ "help" : "-s, --secret-key=[name] Secret Key",
+ "shortdesc" : "Secret Key.",
+ "required" : "0",
+ "order" : 4
+ }
+ all_opt["ram_role"] = {
+ "getopt": ":",
+ "longopt": "ram-role",
+ "help": "--ram-role=[name] Ram Role",
+ "shortdesc": "Ram Role.",
+ "required": "0",
+ "order": 5
+ }
+
+# Main agent method
+def main():
+ conn = None
+
+ device_opt = ["port", "no_password", "region", "access_key", "secret_key", "ram_role"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["power_timeout"]["default"] = "60"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Aliyun (Aliyun Web Services)"
+ docs["longdesc"] = "fence_aliyun is an I/O Fencing agent for Aliyun"
+ docs["vendorurl"] = "http://www.aliyun.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if "--region" in options:
+ region = options["--region"]
+ if "--access-key" in options and "--secret-key" in options:
+ access_key = options["--access-key"]
+ secret_key = options["--secret-key"]
+ conn = client.AcsClient(access_key, secret_key, region)
+ elif "--ram-role" in options:
+ ram_role = options["--ram-role"]
+ role = EcsRamRoleCredential(ram_role)
+ conn = client.AcsClient(region_id=region, credential=role)
+ else:
+ fail_usage("Failed: User credentials are not set. Please set the Access Key and the Secret Key, or configure the RAM role.")
+
+ # Use intranet endpoint to access ECS service
+ try:
+ region_provider.modify_point('Ecs', region, 'ecs.%s.aliyuncs.com' % region)
+ except Exception as e:
+ logging.warn("Failed: failed to modify endpoint to 'ecs.%s.aliyuncs.com': %s" % (region, e))
+
+ # Operate the fencing device
+ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/alom/fence_alom.py b/agents/alom/fence_alom.py
new file mode 100644
index 0000000..7b03dc2
--- /dev/null
+++ b/agents/alom/fence_alom.py
@@ -0,0 +1,53 @@
+#!@PYTHON@ -tt
+
+# The Following Agent Has Been Tested On:
+#
+# Sun(tm) Advanced Lights Out Manager CMT v1.6.1
+# as found on SUN T2000 Niagara
+
+import sys, re, time
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+def get_power_status(conn, options):
+ conn.send_eol("showplatform")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ status = re.search("standby", conn.before.lower())
+ result = (status != None and "off" or "on")
+
+ return result
+
+def set_power_status(conn, options):
+ cmd_line = (options["--action"] == "on" and "poweron" or "poweroff -f -y")
+ conn.send_eol(cmd_line)
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ # Get the machine some time between poweron and poweroff
+ time.sleep(int(options["--power-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["secure"]["default"] = "1"
+ all_opt["cmd_prompt"]["default"] = [r"sc\>\ "]
+
+ options = check_input(device_opt, process_input(device_opt))
+ options["telnet_over_ssh"] = 1
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Sun ALOM"
+ docs["longdesc"] = "fence_alom is an I/O Fencing \
+agent which can be used with ALOM connected machines."
+ docs["vendorurl"] = "http://www.sun.com"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, None)
+ fence_logout(conn, "logout")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/amt/fence_amt.py b/agents/amt/fence_amt.py
new file mode 100644
index 0000000..feec6e3
--- /dev/null
+++ b/agents/amt/fence_amt.py
@@ -0,0 +1,128 @@
+#!@PYTHON@ -tt
+
+import sys, re, os
+import atexit
+from pipes import quote
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, is_executable, run_command, run_delay
+
+def get_power_status(_, options):
+ output = amt_run_command(options, create_command(options, "status"))
+ match = re.search('Powerstate:[\\s]*(..)', str(output))
+ status = match.group(1) if match else None
+
+ if status == None:
+ return "fail"
+ elif status == "S0": # SO = on; S3 = sleep; S5 = off
+ return "on"
+ else:
+ return "off"
+
+def set_power_status(_, options):
+ amt_run_command(options, create_command(options, options["--action"]))
+ return
+
+def reboot_cycle(_, options):
+ (status, _, _) = run_command(options, create_command(options, "cycle"))
+ return not bool(status)
+
+def amt_run_command(options, command, timeout=None):
+ env = os.environ.copy()
+
+ x = quote(options["--password"])
+ x = x[:-1] if x.endswith("'") else x
+ x = x[1:] if x.startswith("'") else x
+ env["AMT_PASSWORD"] = x
+
+ # This is needed because setting the AMT_PASSWORD env
+ # variable only works when no pipe is involved. E.g.:
+ # - Broken:
+ # $ AMT_PASSWORD='foobar' echo 'y' | /usr/bin/amttool nuc2 powerdown
+ # 401 Unauthorized at /usr/bin/amttool line 129.
+ # - Working:
+ # $ AMT_PASSWORD='foobar' sh -c "(echo 'y' | /usr/bin/amttool nuc2 powerdown)"
+ # execute: powerdown
+ # result: pt_status: success
+ newcommand = "sh -c \"(%s)\"" % command
+ return run_command(options, newcommand, timeout, env)
+
+def create_command(options, action):
+ cmd = options["--amttool-path"]
+
+ # --ip / -a
+ cmd += " " + options["--ip"]
+
+ # --action / -o
+ if action == "status":
+ cmd += " info"
+ elif action == "on":
+ cmd = "echo \"y\"|" + cmd
+ cmd += " powerup"
+ elif action == "off":
+ cmd = "echo \"y\"|" + cmd
+ cmd += " powerdown"
+ elif action == "cycle":
+ cmd = "echo \"y\"|" + cmd
+ cmd += " powercycle"
+ if action in ["on", "off", "cycle"] and "--boot-option" in options:
+ cmd += options["--boot-option"]
+
+ # --use-sudo / -d
+ if "--use-sudo" in options:
+ cmd = options["--sudo-path"] + " " + cmd
+
+ return cmd
+
+def define_new_opts():
+ all_opt["boot_option"] = {
+ "getopt" : "b:",
+ "longopt" : "boot-option",
+ "help" : "-b, --boot-option=[option] "
+ "Change the default boot behavior of the machine. (pxe|hd|hdsafe|cd|diag)",
+ "required" : "0",
+ "shortdesc" : "Change the default boot behavior of the machine.",
+ "choices" : ["pxe", "hd", "hdsafe", "cd", "diag"],
+ "order" : 1
+ }
+ all_opt["amttool_path"] = {
+ "getopt" : ":",
+ "longopt" : "amttool-path",
+ "help" : "--amttool-path=[path] Path to amttool binary",
+ "required" : "0",
+ "shortdesc" : "Path to amttool binary",
+ "default" : "@AMTTOOL_PATH@",
+ "order": 200
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["ipaddr", "no_login", "passwd", "boot_option", "no_port",
+ "sudo", "amttool_path", "method"]
+
+ define_new_opts()
+
+ all_opt["ipport"]["default"] = "16994"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for AMT"
+ docs["longdesc"] = "fence_amt is an I/O Fencing agent \
+which can be used with Intel AMT. This agent calls support software amttool\
+(http://www.kraxel.org/cgit/amtterm/)."
+ docs["vendorurl"] = "http://www.intel.com/"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if not is_executable(options["--amttool-path"]):
+ fail_usage("Amttool not found or not accessible")
+
+ result = fence_action(None, options, set_power_status, get_power_status, None, reboot_cycle)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/amt_ws/fence_amt_ws.py b/agents/amt_ws/fence_amt_ws.py
new file mode 100755
index 0000000..5e7452a
--- /dev/null
+++ b/agents/amt_ws/fence_amt_ws.py
@@ -0,0 +1,240 @@
+#!@PYTHON@ -tt
+
+#
+# Fence agent for Intel AMT (WS) based on code from the openstack/ironic project:
+# https://github.com/openstack/ironic/blob/master/ironic/drivers/modules/amt/power.py
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+import sys
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import run_delay, fail_usage, fail, EC_STATUS
+
+from xml.etree import ElementTree
+
+try:
+ import pywsman
+except ImportError:
+ pass
+
+POWER_ON='2'
+POWER_OFF='8'
+POWER_CYCLE='10'
+
+RET_SUCCESS = '0'
+
+CIM_PowerManagementService = ('http://schemas.dmtf.org/wbem/wscim/1/'
+ 'cim-schema/2/CIM_PowerManagementService')
+CIM_ComputerSystem = ('http://schemas.dmtf.org/wbem/wscim/'
+ '1/cim-schema/2/CIM_ComputerSystem')
+CIM_AssociatedPowerManagementService = ('http://schemas.dmtf.org/wbem/wscim/'
+ '1/cim-schema/2/'
+ 'CIM_AssociatedPowerManagementService')
+
+CIM_BootConfigSetting = ('http://schemas.dmtf.org/wbem/wscim/'
+ '1/cim-schema/2/CIM_BootConfigSetting')
+CIM_BootSourceSetting = ('http://schemas.dmtf.org/wbem/wscim/'
+ '1/cim-schema/2/CIM_BootSourceSetting')
+
+
+def xml_find(doc, namespace, item):
+ if doc is None:
+ return
+ tree = ElementTree.fromstring(doc.root().string())
+ query = ('.//{%(namespace)s}%(item)s' % {'namespace': namespace,
+ 'item': item})
+ return tree.find(query)
+
+def _generate_power_action_input(action):
+ method_input = "RequestPowerStateChange_INPUT"
+ address = 'http://schemas.xmlsoap.org/ws/2004/08/addressing'
+ anonymous = ('http://schemas.xmlsoap.org/ws/2004/08/addressing/'
+ 'role/anonymous')
+ wsman = 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd'
+ namespace = CIM_PowerManagementService
+
+ doc = pywsman.XmlDoc(method_input)
+ root = doc.root()
+ root.set_ns(namespace)
+ root.add(namespace, 'PowerState', action)
+
+ child = root.add(namespace, 'ManagedElement', None)
+ child.add(address, 'Address', anonymous)
+
+ grand_child = child.add(address, 'ReferenceParameters', None)
+ grand_child.add(wsman, 'ResourceURI', CIM_ComputerSystem)
+
+ g_grand_child = grand_child.add(wsman, 'SelectorSet', None)
+ g_g_grand_child = g_grand_child.add(wsman, 'Selector', 'ManagedSystem')
+ g_g_grand_child.attr_add(wsman, 'Name', 'Name')
+ return doc
+
+def get_power_status(_, options):
+ client = pywsman.Client(options["--ip"], int(options["--ipport"]), \
+ '/wsman', 'http', 'admin', options["--password"])
+ namespace = CIM_AssociatedPowerManagementService
+ client_options = pywsman.ClientOptions()
+ doc = client.get(client_options, namespace)
+ _SOAP_ENVELOPE = 'http://www.w3.org/2003/05/soap-envelope'
+ item = 'Fault'
+ fault = xml_find(doc, _SOAP_ENVELOPE, item)
+ if fault is not None:
+ logging.error("Failed to get power state for: %s port:%s", \
+ options["--ip"], options["--ipport"])
+ fail(EC_STATUS)
+
+ item = "PowerState"
+ try: power_state = xml_find(doc, namespace, item).text
+ except AttributeError:
+ logging.error("Failed to get power state for: %s port:%s", \
+ options["--ip"], options["--ipport"])
+ fail(EC_STATUS)
+ if power_state == POWER_ON:
+ return "on"
+ elif power_state == POWER_OFF:
+ return "off"
+ else:
+ fail(EC_STATUS)
+
+def set_power_status(_, options):
+ client = pywsman.Client(options["--ip"], int(options["--ipport"]), \
+ '/wsman', 'http', 'admin', options["--password"])
+
+ method = 'RequestPowerStateChange'
+ client_options = pywsman.ClientOptions()
+ client_options.add_selector('Name', 'Intel(r) AMT Power Management Service')
+
+ if options["--action"] == "on":
+ target_state = POWER_ON
+ elif options["--action"] == "off":
+ target_state = POWER_OFF
+ elif options["--action"] == "reboot":
+ target_state = POWER_CYCLE
+ if options["--action"] in ["on", "off", "reboot"] \
+ and "--boot-option" in options:
+ set_boot_order(_, client, options)
+
+ doc = _generate_power_action_input(target_state)
+ client_doc = client.invoke(client_options, CIM_PowerManagementService, \
+ method, doc)
+ item = "ReturnValue"
+ return_value = xml_find(client_doc, CIM_PowerManagementService, item).text
+ if return_value != RET_SUCCESS:
+ logging.error("Failed to set power state: %s for: %s", \
+ options["--action"], options["--ip"])
+ fail(EC_STATUS)
+
+def set_boot_order(_, client, options):
+ method_input = "ChangeBootOrder_INPUT"
+ address = 'http://schemas.xmlsoap.org/ws/2004/08/addressing'
+ anonymous = ('http://schemas.xmlsoap.org/ws/2004/08/addressing/'
+ 'role/anonymous')
+ wsman = 'http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd'
+ namespace = CIM_BootConfigSetting
+
+ if options["--boot-option"] == "PXE":
+ device = "Intel(r) AMT: Force PXE Boot"
+ elif options["--boot-option"] in ["HD", "HDSAFE"]:
+ device = "Intel(r) AMT: Force Hard-drive Boot"
+ elif options["--boot-option"] == "CD":
+ device = "Intel(r) AMT: Force CD/DVD Boot"
+ elif options["--boot-option"] == "DIAG":
+ device = "Intel(r) AMT: Force Diagnostic Boot"
+ else:
+ logging.error('Boot device: %s not supported.', \
+ options["--boot-option"])
+ return
+
+ method = 'ChangeBootOrder'
+ client_options = pywsman.ClientOptions()
+ client_options.add_selector('InstanceID', \
+ 'Intel(r) AMT: Boot Configuration 0')
+
+ doc = pywsman.XmlDoc(method_input)
+ root = doc.root()
+ root.set_ns(namespace)
+
+ child = root.add(namespace, 'Source', None)
+ child.add(address, 'Address', anonymous)
+
+ grand_child = child.add(address, 'ReferenceParameters', None)
+ grand_child.add(wsman, 'ResourceURI', CIM_BootSourceSetting)
+
+ g_grand_child = grand_child.add(wsman, 'SelectorSet', None)
+ g_g_grand_child = g_grand_child.add(wsman, 'Selector', device)
+ g_g_grand_child.attr_add(wsman, 'Name', 'InstanceID')
+ if options["--boot-option"] == "hdsafe":
+ g_g_grand_child = g_grand_child.add(wsman, 'Selector', 'True')
+ g_g_grand_child.attr_add(wsman, 'Name', 'UseSafeMode')
+
+ client_doc = client.invoke(client_options, CIM_BootConfigSetting, \
+ method, doc)
+ item = "ReturnValue"
+ return_value = xml_find(client_doc, CIM_BootConfigSetting, item).text
+ if return_value != RET_SUCCESS:
+ logging.error("Failed to set boot device to: %s for: %s", \
+ options["--boot-option"], options["--ip"])
+ fail(EC_STATUS)
+
+def reboot_cycle(_, options):
+ status = set_power_status(_, options)
+ return not bool(status)
+
+def define_new_opts():
+ all_opt["boot_option"] = {
+ "getopt" : "b:",
+ "longopt" : "boot-option",
+ "help" : "-b, --boot-option=[option] "
+ "Change the default boot behavior of the\n"
+ " machine."
+ " (pxe|hd|hdsafe|cd|diag)",
+ "required" : "0",
+ "shortdesc" : "Change the default boot behavior of the machine.",
+ "choices" : ["pxe", "hd", "hdsafe", "cd", "diag"],
+ "order" : 1
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["ipaddr", "no_login", "passwd", "boot_option", "no_port",
+ "method"]
+
+ define_new_opts()
+
+ all_opt["ipport"]["default"] = "16992"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for AMT (WS)"
+ docs["longdesc"] = "fence_amt_ws is an I/O Fencing agent \
+which can be used with Intel AMT (WS). This agent requires \
+the pywsman Python library which is included in OpenWSMAN. \
+(http://openwsman.github.io/)."
+ docs["vendorurl"] = "http://www.intel.com/"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ result = fence_action(None, options, set_power_status, get_power_status, \
+ None, reboot_cycle)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/apc/fence_apc.py b/agents/apc/fence_apc.py
new file mode 100644
index 0000000..3ea0f37
--- /dev/null
+++ b/agents/apc/fence_apc.py
@@ -0,0 +1,263 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Model Firmware
+## +---------------------------------------------+
+## AP7951 AOS v2.7.0, PDU APP v2.7.3
+## AP7941 AOS v3.5.7, PDU APP v3.5.6
+## AP9606 AOS v2.5.4, PDU APP v2.7.3
+##
+## @note: ssh is very slow on AP79XX devices protocol (1) and
+## cipher (des/blowfish) have to be defined
+#####
+
+import sys, re, time
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, EC_STATUS
+
+# Fix for connection timed out issue in:
+# https://bugzilla.redhat.com/show_bug.cgi?id=1342584
+TIMEDOUT_DELAY = 0.5
+
+def get_power_status(conn, options):
+ exp_result = 0
+ outlets = {}
+
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ version = 0
+ admin = 0
+ switch = 0
+
+ if None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before):
+ switch = 1
+ if None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before):
+ if "--switch" not in options:
+ fail_usage("Failed: You have to enter physical switch number")
+ else:
+ if "--switch" not in options:
+ options["--switch"] = "1"
+
+ if None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before):
+ version = 2
+ else:
+ version = 3
+
+ if None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before):
+ admin = 0
+ else:
+ admin = 1
+
+ if switch == 0:
+ if version == 2:
+ if admin == 0:
+ conn.send_eol("2")
+ else:
+ conn.send_eol("3")
+ else:
+ conn.send_eol("2")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.send_eol("1")
+ else:
+ conn.send_eol(options["--switch"])
+
+ while True:
+ exp_result = conn.log_expect(
+ ["Press <ENTER>"] + options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+ show_re = re.compile(r'(^|\x0D)\s*(\d+)- (.*?)\s+(ON|OFF)\s*')
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ outlets[res.group(2)] = (res.group(3), res.group(4))
+ time.sleep(TIMEDOUT_DELAY)
+ conn.send_eol("")
+ if exp_result != 0:
+ break
+ conn.send(chr(0o3))
+ conn.log_expect("- Logout", int(options["--shell-timeout"]))
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ try:
+ (_, status) = outlets[options["--plug"]]
+ return status.lower().strip()
+ except KeyError as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_STATUS)
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "1",
+ 'off': "2"
+ }[options["--action"]]
+
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ version = 0
+ admin2 = 0
+ admin3 = 0
+ switch = 0
+
+ if None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before):
+ switch = 1
+ ## MasterSwitch has different schema for on/off actions
+ action = {
+ 'on' : "1",
+ 'off': "3"
+ }[options["--action"]]
+ if None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before):
+ if "--switch" not in options:
+ fail_usage("Failed: You have to enter physical switch number")
+ else:
+ if "--switch" not in options:
+ options["--switch"] = 1
+
+ if None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before):
+ version = 2
+ else:
+ version = 3
+
+ if None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before):
+ admin2 = 0
+ else:
+ admin2 = 1
+
+ if switch == 0:
+ if version == 2:
+ if admin2 == 0:
+ conn.send_eol("2")
+ else:
+ conn.send_eol("3")
+ else:
+ conn.send_eol("2")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ if None == re.compile('.*2- Outlet Restriction.*', re.IGNORECASE | re.S).match(conn.before):
+ admin3 = 0
+ else:
+ admin3 = 1
+ conn.send_eol("1")
+ else:
+ conn.send_eol(options["--switch"])
+
+ while 0 == conn.log_expect(
+ ["Press <ENTER>"] + options["--command-prompt"], int(options["--shell-timeout"])):
+ time.sleep(TIMEDOUT_DELAY)
+ conn.send_eol("")
+
+ conn.send_eol(options["--plug"]+"")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ if switch == 0:
+ if admin2 == 1:
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ if admin3 == 1:
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ else:
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ conn.send_eol(action)
+ conn.log_expect("Enter 'YES' to continue or <ENTER> to cancel :", int(options["--shell-timeout"]))
+ conn.send_eol("YES")
+ conn.log_expect("Press <ENTER> to continue...", int(options["--power-timeout"]))
+ time.sleep(TIMEDOUT_DELAY)
+ conn.send_eol("")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ conn.send(chr(0o3))
+ conn.log_expect("- Logout", int(options["--shell-timeout"]))
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_power_status5(conn, options):
+ outlets = {}
+
+ conn.send_eol("olStatus all")
+
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+
+ show_re = re.compile(r'^\s*(\d+): (.*): (On|Off)\s*$', re.IGNORECASE)
+
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ outlets[res.group(1)] = (res.group(2), res.group(3))
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ try:
+ (_, status) = outlets[options["--plug"]]
+ return status.lower().strip()
+ except KeyError as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_STATUS)
+
+def set_power_status5(conn, options):
+ action = {
+ 'on' : "olOn",
+ 'off': "olOff"
+ }[options["--action"]]
+
+ conn.send_eol(action + " " + options["--plug"])
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "switch", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["\n>", "\napc>"]
+ all_opt["ssh_options"]["default"] = "-1 -c blowfish"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for APC over telnet/ssh"
+ docs["longdesc"] = "fence_apc is an I/O Fencing agent \
+which can be used with the APC network power switch. It logs into device \
+via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections \
+should be avoided while a GFS cluster is running because the connection \
+will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.apc.com"
+ show_docs(options, docs)
+
+ ## Support for --plug [switch]:[plug] notation that was used before
+ if (("--plug" in options) == 1) and (-1 != options["--plug"].find(":")):
+ (switch, plug) = options["--plug"].split(":", 1)
+ options["--switch"] = switch
+ options["--plug"] = plug
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+
+ ## Detect firmware version (ASCII menu vs command-line interface)
+ ## and continue with proper action
+ ####
+ result = -1
+ firmware_version = re.compile(r'\s*v(\d)*\.').search(conn.before)
+ if (firmware_version != None) and (firmware_version.group(1) in [ "5", "6", "7" ]):
+ result = fence_action(conn, options, set_power_status5, get_power_status5, get_power_status5)
+ else:
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+
+ fence_logout(conn, "4")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/apc_snmp/README b/agents/apc_snmp/README
new file mode 100644
index 0000000..75aa37a
--- /dev/null
+++ b/agents/apc_snmp/README
@@ -0,0 +1,45 @@
+This is an snmp based fence agent for APC power switches to be used
+with RHEL4 Red Hat Cluster Suite.
+
+The reasons to use this agent rather than the current fence_apc agent are:
+1) This script has been tested with EVERY powerswitch that APC currently
+makes.
+2) It will work on many older models that are no longer supported by APC.
+I have been told that it even works with the AP9200 switch. Older switches
+usually don't do well with the fence_apc script.
+3) This agent works with large power switches that have more than 8 outlets.
+The fence_apc script will also, in the next update -- this script will work for you now.
+
+If feedback on this beta version of the agent is good, and if ganged switches
+can be supported, then this agent may replace fence_apc.
+
+In order to use this agent, you will need to have net-snmp-utils installed
+on every node in your cluster. net-snmp-utils is scheduled for inclusion
+in the base RHEL distribution for Update 4, and is yummable in FC5.
+
+After net-snmp-utils is installed, there will be a directory named:
+/usr/share/snmp/mibs/
+
+Place the accompanying powernet369.mib file in this directory.
+
+To use the agent, cp the agent to the /sbin directory on every
+cluster node. The interface for the fence_apc_snmp agent is identical to
+the existing fence_apc agent, so if you are using APC for fencing in
+your cluster, you *could* backup your current fence_apc agent, and
+rename this agent from fence_apc_snmp to fence_apc, and it should just work.
+
+NOTE: The fence_apc_snmp agent does not yet support ganged or 'daisy-chained'
+APC switches.
+
+If you would rather not copy over your fence_apc agent, you can still use
+the fence_apc_snmp agent by dropping it into /sbin on every node, and then
+defining a <fencedevice> in the cluster.conf file with agent="fence_apc_snmp"
+as an attribute, and use it that way. Note, please, that the GUI does
+not support this agent yet, and you will have to edit your cluster.conf
+by hand and then propagate it yourself. If you need help with this, email
+me on linux-cluster or at the address below.
+
+Big thanks to Nate Straz who laid the foundation for this agent.
+
+Please let me know how this agent works.
+--Jim Parsons - jparsons@redhat.com
diff --git a/agents/apc_snmp/fence_apc_snmp.py b/agents/apc_snmp/fence_apc_snmp.py
new file mode 100644
index 0000000..cd60166
--- /dev/null
+++ b/agents/apc_snmp/fence_apc_snmp.py
@@ -0,0 +1,232 @@
+#!@PYTHON@ -tt
+
+# The Following agent has been tested on:
+# - APC Switched Rack PDU - SNMP v1
+# (MB:v3.7.0 PF:v2.7.0 PN:apc_hw02_aos_270.bin AF1:v2.7.3
+# AN1:apc_hw02_aos_270.bin AF1:v2.7.3 AN1:apc_hw02_rpdu_273.bin MN:AP7930 HR:B2)
+# - APC Web/SNMP Management Card - SNMP v1 and v3 (noAuthNoPrivacy,authNoPrivacy, authPrivacy)
+# (MB:v3.8.6 PF:v3.5.8 PN:apc_hw02_aos_358.bin AF1:v3.5.7
+# AN1:apc_hw02_aos_358.bin AF1:v3.5.7 AN1:apc_hw02_rpdu_357.bin MN:AP7900 HR:B2)
+# - APC Switched Rack PDU - SNMP v1
+# (MB:v3.7.0 PF:v2.7.0 PN:apc_hw02_aos_270.bin AF1:v2.7.3
+# AN1:apc_hw02_rpdu_273.bin MN:AP7951 HR:B2)
+# - Tripplite PDUMH20HVNET 12.04.0055 - SNMP v1, v2c, v3
+# - Tripplite PDU15NETLX 15.5.4 - SNMP v1, v2c, v3
+
+import sys
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# oid defining fence device
+OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0'
+
+### GLOBAL VARIABLES ###
+# Device - see ApcRPDU, ApcMSP, ApcMS, TripplitePDU, TrippliteLXPDU
+device = None
+
+# Port ID
+port_id = None
+# Switch ID
+switch_id = None
+
+# Classes describing Device params
+class TripplitePDU(object):
+ # Rack PDU
+ status_oid = '.1.3.6.1.4.1.850.10.2.3.5.1.2.1.%d'
+ control_oid = '.1.3.6.1.4.1.850.10.2.3.5.1.4.1.%d'
+ outlet_table_oid = '.1.3.6.1.4.1.850.10.2.3.5.1.5'
+ ident_str = "Tripplite"
+ state_on = 2
+ state_off = 1
+ turn_on = 2
+ turn_off = 1
+ has_switches = False
+
+class TrippliteLXPDU(object):
+ # WEBCARDLX-based PDU
+ status_oid = '.1.3.6.1.4.1.850.1.1.3.2.3.3.1.1.4.1.%d'
+ control_oid = '.1.3.6.1.4.1.850.1.1.3.2.3.3.1.1.6.1.%d'
+ outlet_table_oid = '.1.3.6.1.4.1.850.1.1.3.2.3.3.1.1.2.1'
+ ident_str = "Tripplite LX"
+ state_on = 2
+ state_off = 1
+ turn_on = 2
+ turn_off = 1
+ has_switches = False
+
+class ApcRPDU(object):
+ # Rack PDU
+ status_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.%d'
+ control_oid = '.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%d'
+ outlet_table_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.2'
+ ident_str = "APC rPDU"
+ state_on = 1
+ state_off = 2
+ turn_on = 1
+ turn_off = 2
+ has_switches = False
+
+class ApcMSP(object):
+ # Master Switch+
+ status_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.5.%d.1.%d'
+ control_oid = '.1.3.6.1.4.1.318.1.1.6.5.1.1.5.%d.1.%d'
+ outlet_table_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.4'
+ ident_str = "APC Master Switch+"
+ state_on = 1
+ state_off = 2
+ turn_on = 1
+ turn_off = 3
+ has_switches = True
+
+class ApcMS(object):
+ # Master Switch - seems oldest, but supported on every APC PDU
+ status_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.3.%d'
+ control_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.3.%d'
+ outlet_table_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.4'
+ ident_str = "APC Master Switch (fallback)"
+ state_on = 1
+ state_off = 2
+ turn_on = 1
+ turn_off = 2
+ has_switches = False
+
+class ApcMS6(object):
+ # Master Switch with 6.x firmware
+ status_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.3.%d'
+ control_oid = '.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%d'
+ outlet_table_oid = '1.3.6.1.4.1.318.1.1.4.4.2.1.4'
+ ident_str = "APC Master Switch with firmware v6.x"
+ state_on = 1
+ state_off = 2
+ turn_on = 1
+ turn_off = 2
+ has_switches = False
+
+### FUNCTIONS ###
+def apc_set_device(conn):
+ global device
+
+ agents_dir = {'.1.3.6.1.4.1.318.1.3.4.5':ApcRPDU,
+ '.1.3.6.1.4.1.318.1.3.4.4':ApcMSP,
+ '.1.3.6.1.4.1.850.1':TripplitePDU,
+ '.1.3.6.1.4.1.850.1.1.1':TrippliteLXPDU,
+ '.1.3.6.1.4.1.318.1.3.4.6':ApcMS6,
+ None:ApcMS}
+
+ # First resolve type of APC
+ apc_type = conn.walk(OID_SYS_OBJECT_ID)
+
+ if not ((len(apc_type) == 1) and (apc_type[0][1] in agents_dir)):
+ apc_type = [[None, None]]
+
+ device = agents_dir[apc_type[0][1]]
+
+ logging.debug("Trying %s"%(device.ident_str))
+
+def apc_resolv_port_id(conn, options):
+ global port_id, switch_id
+
+ if device == None:
+ apc_set_device(conn)
+
+ # Now we resolv port_id/switch_id
+ if (options["--plug"].isdigit()) and ((not device.has_switches) or (options["--switch"].isdigit())):
+ port_id = int(options["--plug"])
+
+ if device.has_switches:
+ switch_id = int(options["--switch"])
+ else:
+ table = conn.walk(device.outlet_table_oid, 30)
+
+ for x in table:
+ if x[1].strip('"') == options["--plug"]:
+ t = x[0].split('.')
+ if device.has_switches:
+ port_id = int(t[len(t)-1])
+ switch_id = int(t[len(t)-3])
+ else:
+ port_id = int(t[len(t)-1])
+
+ if port_id == None:
+ fail_usage("Can't find port with name %s!"%(options["--plug"]))
+
+def get_power_status(conn, options):
+ if port_id == None:
+ apc_resolv_port_id(conn, options)
+
+ oid = ((device.has_switches) and device.status_oid%(switch_id, port_id) or device.status_oid%(port_id))
+
+ (oid, status) = conn.get(oid)
+ return status == str(device.state_on) and "on" or "off"
+
+def set_power_status(conn, options):
+ if port_id == None:
+ apc_resolv_port_id(conn, options)
+
+ oid = ((device.has_switches) and device.control_oid%(switch_id, port_id) or device.control_oid%(port_id))
+
+ conn.set(oid, (options["--action"] == "on" and device.turn_on or device.turn_off))
+
+
+def get_outlets_status(conn, options):
+ result = {}
+
+ if device == None:
+ apc_set_device(conn)
+
+ res_ports = conn.walk(device.outlet_table_oid, 30)
+
+ for x in res_ports:
+ t = x[0].split('.')
+
+ port_num = ((device.has_switches) and "%s:%s"%(t[len(t)-3], t[len(t)-1]) or "%s"%(t[len(t)-1]))
+
+ port_name = x[1].strip('"')
+ port_status = ""
+ result[port_num] = (port_name, port_status)
+
+ return result
+
+# Main agent method
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["snmp_version"]["default"] = "1"
+ all_opt["community"]["default"] = "private"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ ## Support for -n [switch]:[plug] notation that was used before
+ if ("--plug" in options) and (-1 != options["--plug"].find(":")):
+ (switch, plug) = options["--plug"].split(":", 1)
+ if switch.isdigit() and plug.isdigit():
+ options["--switch"] = switch
+ options["--plug"] = plug
+
+ if "--switch" not in options:
+ options["--switch"] = "1"
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for APC, Tripplite PDU over SNMP"
+ docs["longdesc"] = "fence_apc_snmp is an I/O Fencing agent \
+which can be used with the APC network power switch or Tripplite PDU devices.\
+It logs into a device via SNMP and reboots a specified outlet. It supports \
+SNMP v1, v2c, v3 with all combinations of authenticity/privacy settings."
+ docs["vendorurl"] = "http://www.apc.com"
+ docs["symlink"] = [("fence_tripplite_snmp", "Fence agent for Tripplife over SNMP")]
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+if __name__ == "__main__":
+ main()
diff --git a/agents/apc_snmp/powernet369.mib b/agents/apc_snmp/powernet369.mib
new file mode 100644
index 0000000..ab948f8
--- /dev/null
+++ b/agents/apc_snmp/powernet369.mib
@@ -0,0 +1,31109 @@
+-- *************************************************************************
+-- AMERICAN POWER CONVERSION PowerNet-MIB
+-- *************************************************************************
+-- Copyright (c) 2005 American Power Conversion, Inc.
+-- PowerNet is a Trademark of American Power Conversion Corp.
+--
+-- Title: APC TOP LEVEL PowerNet MIB
+--
+-- Version : 3.6.9
+--
+-- Generated by script: tomib.awk
+--
+-- Input File: powernetPS.mib
+--
+-- Created: Wednesday, January, 26, 2005
+--
+-- Revision History:
+-- *************************************************************************
+
+-- - v3.2.0 Added functionality for MasterSwitch Plus
+-- - v3.3.0 Added functionality for MX28B (dcDM3) and 3-phase UPS
+-- - v3.3.2 New traps for Symmetra PX UPS
+-- 07/15/01 - v3.4.0 Added transfer switch
+-- - v3.4.3 Added functionality for External and Integrated Environmental Monitor
+-- 06/14/02 - v3.4.4 Added dcmim2(Siemens) branch, Battery Manager(Reading) traps, and
+-- Psx Traps for PDU and RM-PDU and Netlock branch/traps
+-- 06/18/02 - v3.5.0a Sync Control Group support
+-- 08/06/02 - v3.5.0a Environmental Management System branch/traps
+-- 09/16/02 - v3.5.0b Fixed some odds/ends ... going to RM-PDU for MS additions
+-- 09/25/02 - v3.5.0c MS3 additions
+-- 11/05/02 - v3.5.0e More Environmental Management System/A-Link devices(ARU)
+-- 11/22/02 - v3.5.0g Added General APC device status OID
+-- 11/27/02 - v3.5.0h Wrapped up MS3 ((Controlled or Metered) Rack PDU) changes
+-- 12/26/02 - v3.5.1a Changed MS3 name again, Controlled to Switched Rack PDU
+-- 01/07/03 - v3.6.0a Added OIDs/Traps for UPS Switchable Outlet Groups.
+-- 01/09/03 - Adding the General APC device discovery OIDs (hidden)
+-- 01/28/03 - v3.6.0c Made some small trap pair fixes for Switched Rack PDU (MS3)
+-- 02/13/03 - v3.6.0d Mods from the review and some EMS fixes.
+-- Added OID for the new 20kVA Symmetra 3 Phase type.
+-- Added OIDs to upsAdvConfig for Symmetra type UPSs.
+-- Added upsDiagnostics branch OID for Symmetra module information.
+-- 04/05/03 - v3.6.2 Added OID for the new Smart-UPS 7500 and 10000 types.
+-- 06/04/03 - v3.6.3 Added OIDs/Traps for AirFM.
+-- 06/24/03 - v3.6.4 Moved some AirFM temps and humidities from system level to module level.
+-- 10/24/03 - v3.6.4a Added OIDs/Traps for xPDU.
+-- 10/27/03 - v3.6.4f Added AirPA OIDs.
+-- 11/03/03 - v3.6.4g Merge of 3.6.4e and 3.6.4f
+-- 11/07/03 - v3.6.4h Additional review corrections
+-- 12/01/03 - v3.6.5a Added group OIDs for Air FM. Added C & F OIDs for Air PA setpoint.
+-- 12/19/03 - v3.6.5b Review corrections.
+-- 02/23/04 - v3.6.5c Added Modbus to experimental and multiple CB(bank) rPDU support
+-- 05/05/04 - v3.6.6 Adding EMS status OID and trap for H/W issues, redefined duplicate
+-- trap #228 (to ARU Device config change) and minor clean-up
+-- 05/12/04 - v3.6.7a Added Air FM alarm status OIDs.
+-- 06/03/04 - v3.6.7b Added UPS Config for Simple Signal Shutdowns and Number of External
+-- batteries. Added Mute option to the UPS Config Audible Alarm.
+-- 07/12/04 - v3.6.7d Removed Air FM alarm status OIDs due to delay in release.
+-- 07/14/04 - v3.6.7d Added a detailed description to the UPSAdvConfigAlarm OID
+-- 07/14/04 - v3.6.7e Added Custom Event traps
+-- 08/04/04 - v3.6.7 Tag for final builds, see v3.6.7 beta build notes for changes
+-- 08/26/04 - v3.6.8a Added new traps for UPS internal over temperature fault and cleared.
+-- 09/01/04 - v3.6.8b Adding new thresholds for EMS probe config & status
+-- 09/08/04 - v3.6.8c Corrections from MIB review.
+-- 09/30/04 - v3.6.8d Added new traps for AIS ^F Message events.
+-- 10/21/04 - v3.6.8e EMS. Added missing traps and new Rate functionality.
+-- 10/22/04 - v3.6.8f Added resetNetworkLeaveModeAndRestart option to the mcontrolRestartAgent OID.
+-- 10/28/04 - v3.6.8g Updated EMS sections from mib committee review.
+-- 11/22/04 - v3.6.8 Tag for final build.
+-- 12/02/04 - v3.6.9a Added OIDs and traps for BMS-HVA.
+-- 12/20/04 - v3.6.9c corrections to xPDU.
+-- 12/20/04 - v3.6.9c added OIDs and traps for xATS.
+-- 01/03/05 - v3.6.9d removed traps for xATS.
+-- 01/03/05 - v3.6.9e correction to xATS entries, that removed underscores (mib browser incompatibility)
+-- 01/07/05 - v3.6.9f
+-- 01/14/05 - v3.6.9g add xPDU OIDs and traps and some corrections.
+-- 01/14/05 - v3.6.9g modifications to xATS OIDs and traps.
+
+-- *************************************************************************
+-- *************************************************************************
+-- PowerNet-MIB { iso org(3) dod(6) internet(1) private(4)
+-- enterprises(1) apc(318) }
+
+PowerNet-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ enterprises, IpAddress, Gauge, TimeTicks FROM RFC1155-SMI
+ DisplayString FROM RFC1213-MIB
+ OBJECT-TYPE FROM RFC-1212
+ TRAP-TYPE FROM RFC-1215;
+
+apc OBJECT IDENTIFIER ::= { enterprises 318 }
+
+products OBJECT IDENTIFIER ::= { apc 1 }
+apcmgmt OBJECT IDENTIFIER ::= { apc 2 }
+
+hardware OBJECT IDENTIFIER ::= { products 1 }
+software OBJECT IDENTIFIER ::= { products 2 }
+system OBJECT IDENTIFIER ::= { products 3 }
+experimental OBJECT IDENTIFIER ::= { products 4 }
+
+mconfig OBJECT IDENTIFIER ::= { apcmgmt 1 }
+mcontrol OBJECT IDENTIFIER ::= { apcmgmt 2 }
+mtrapargs OBJECT IDENTIFIER ::= { apcmgmt 3 }
+mfiletransfer OBJECT IDENTIFIER ::= { apcmgmt 4 }
+
+mconfigClock OBJECT IDENTIFIER ::= { mconfig 6 }
+
+mfiletransferStatus OBJECT IDENTIFIER ::= { mfiletransfer 1 }
+mfiletransferConfig OBJECT IDENTIFIER ::= { mfiletransfer 2 }
+mfiletransferControl OBJECT IDENTIFIER ::= { mfiletransfer 3 }
+
+mfiletransferConfigSettings OBJECT IDENTIFIER ::= { mfiletransferConfig 1 }
+mfiletransferConfigTFTP OBJECT IDENTIFIER ::= { mfiletransferConfig 2 }
+mfiletransferConfigFTP OBJECT IDENTIFIER ::= { mfiletransferConfig 3 }
+
+ups OBJECT IDENTIFIER ::= { hardware 1 }
+measureUps OBJECT IDENTIFIER ::= { hardware 2 }
+miniSNMPadapter OBJECT IDENTIFIER ::= { hardware 3 }
+masterswitch OBJECT IDENTIFIER ::= { hardware 4 }
+masterswitchVM OBJECT IDENTIFIER ::= { hardware 5 }
+masterswitchMSP OBJECT IDENTIFIER ::= { hardware 6 }
+dcDM3 OBJECT IDENTIFIER ::= { hardware 7 }
+automaticTransferSwitch OBJECT IDENTIFIER ::= { hardware 8 }
+dc2 OBJECT IDENTIFIER ::= { hardware 9 }
+environmentalMonitor OBJECT IDENTIFIER ::= { hardware 10 }
+netlock OBJECT IDENTIFIER ::= { hardware 11 }
+rPDU OBJECT IDENTIFIER ::= { hardware 12 }
+airConditioners OBJECT IDENTIFIER ::= { hardware 13 }
+rARU OBJECT IDENTIFIER ::= { hardware 14 }
+xPDU OBJECT IDENTIFIER ::= { hardware 15 }
+battMan OBJECT IDENTIFIER ::= { hardware 16 }
+xATS OBJECT IDENTIFIER ::= { hardware 17 }
+generator OBJECT IDENTIFIER ::= { hardware 18 }
+
+powerNetSubAgent OBJECT IDENTIFIER ::= { software 1 }
+
+powerNetSoftwareSystem OBJECT IDENTIFIER ::= { powerNetSubAgent 1 }
+powerNetSoftwareConfig OBJECT IDENTIFIER ::= { powerNetSubAgent 2 }
+
+backUPS OBJECT IDENTIFIER ::= { system 1 }
+smartUPS OBJECT IDENTIFIER ::= { system 2 }
+matrixUPS OBJECT IDENTIFIER ::= { system 3 }
+masterSwitch OBJECT IDENTIFIER ::= { system 4 }
+symmetraUPS OBJECT IDENTIFIER ::= { system 5 }
+dp100E OBJECT IDENTIFIER ::= { system 6 }
+dp300E OBJECT IDENTIFIER ::= { system 7 }
+monitors OBJECT IDENTIFIER ::= { system 8 }
+redundantSwitch OBJECT IDENTIFIER ::= { system 9 }
+dcPower OBJECT IDENTIFIER ::= { system 10 }
+automaticXferSwitch OBJECT IDENTIFIER ::= { system 11 }
+netLock OBJECT IDENTIFIER ::= { system 12 }
+symmetra3PhaseUPS OBJECT IDENTIFIER ::= { system 13 }
+networkAir OBJECT IDENTIFIER ::= { system 14 }
+infraXurePDU OBJECT IDENTIFIER ::= { system 15 }
+ais5000UPS OBJECT IDENTIFIER ::= { system 16 }
+smartUPS3Phase OBJECT IDENTIFIER ::= { system 17 }
+battManager OBJECT IDENTIFIER ::= { system 18 }
+infraXureATS OBJECT IDENTIFIER ::= { system 19 }
+
+battManIdent OBJECT IDENTIFIER ::= { battMan 1 }
+battManSystemCalib OBJECT IDENTIFIER ::= { battMan 2 }
+battManUnitCalib OBJECT IDENTIFIER ::= { battMan 3 }
+battManStringCalib OBJECT IDENTIFIER ::= { battMan 4 }
+battManBatteryCalib OBJECT IDENTIFIER ::= { battMan 5 }
+battManConfig OBJECT IDENTIFIER ::= { battMan 6 }
+battManAlarm OBJECT IDENTIFIER ::= { battMan 7 }
+battManSystemStatus OBJECT IDENTIFIER ::= { battMan 8 }
+battManStringStatus OBJECT IDENTIFIER ::= { battMan 9 }
+battManBatteryStatus OBJECT IDENTIFIER ::= { battMan 10 }
+battManInputContactStatus OBJECT IDENTIFIER ::= { battMan 11 }
+battManControl OBJECT IDENTIFIER ::= { battMan 12 }
+battManTestResults OBJECT IDENTIFIER ::= { battMan 13 }
+
+xPDUIdent OBJECT IDENTIFIER ::= { xPDU 1 }
+xPDUDevice OBJECT IDENTIFIER ::= { xPDU 2 }
+xPDUACMonitoringPoint OBJECT IDENTIFIER ::= { xPDU 3 }
+xPDUCircuitBreakers OBJECT IDENTIFIER ::= { xPDU 4 }
+xPDUInputContacts OBJECT IDENTIFIER ::= { xPDU 5 }
+xPDUOutputRelays OBJECT IDENTIFIER ::= { xPDU 6 }
+xPDUMiscGroup OBJECT IDENTIFIER ::= { xPDU 7 }
+
+xPDUMainInput OBJECT IDENTIFIER ::= { xPDUACMonitoringPoint 1 }
+xPDUBypassInput OBJECT IDENTIFIER ::= { xPDUACMonitoringPoint 2 }
+xPDUUPSInput OBJECT IDENTIFIER ::= { xPDUACMonitoringPoint 3 }
+xPDUSystemOutput OBJECT IDENTIFIER ::= { xPDUACMonitoringPoint 4 }
+xPDUGroundMonitorPoint OBJECT IDENTIFIER ::= { xPDUACMonitoringPoint 5 }
+
+xPDUSystemBreakers OBJECT IDENTIFIER ::= { xPDUCircuitBreakers 1 }
+xPDUBranchBreakers OBJECT IDENTIFIER ::= { xPDUCircuitBreakers 2 }
+
+xATSIdent OBJECT IDENTIFIER ::= { xATS 1 }
+xATSDevice OBJECT IDENTIFIER ::= { xATS 2 }
+xATSSwitch OBJECT IDENTIFIER ::= { xATS 3 }
+xATSACMonitoringPoint OBJECT IDENTIFIER ::= { xATS 4 }
+xATSTesting OBJECT IDENTIFIER ::= { xATS 5 }
+xATSInputContacts OBJECT IDENTIFIER ::= { xATS 6 }
+xATSOutputRelays OBJECT IDENTIFIER ::= { xATS 7 }
+xATSMisc OBJECT IDENTIFIER ::= { xATS 8 }
+
+xATSSwitchStatus OBJECT IDENTIFIER ::= { xATSSwitch 1 }
+xATSSwitchSettings OBJECT IDENTIFIER ::= { xATSSwitch 2 }
+xATSSwitchTimers OBJECT IDENTIFIER ::= { xATSSwitch 3 }
+xATSSwitchBlockMap OBJECT IDENTIFIER ::= { xATSSwitch 4 }
+xATSSwitchStatistics OBJECT IDENTIFIER ::= { xATSSwitch 5 }
+
+xATSSource1 OBJECT IDENTIFIER ::= { xATSACMonitoringPoint 1 }
+xATSSource2 OBJECT IDENTIFIER ::= { xATSACMonitoringPoint 2 }
+xATSSystemOutput OBJECT IDENTIFIER ::= { xATSACMonitoringPoint 3 }
+
+xATSTestingStatus OBJECT IDENTIFIER ::= { xATSTesting 1 }
+xATSTestingResults OBJECT IDENTIFIER ::= { xATSTesting 2 }
+xATSTestingSchedule OBJECT IDENTIFIER ::= { xATSTesting 3 }
+xATSTestingSimulatePowerFail OBJECT IDENTIFIER ::= { xATSTesting 4 }
+
+xATSGenerator OBJECT IDENTIFIER ::= { generator 1 }
+
+xATSGeneratorIdent OBJECT IDENTIFIER ::= { xATSGenerator 1 }
+xATSGeneratorStatus OBJECT IDENTIFIER ::= { xATSGenerator 2 }
+xATSGeneratorAdvStatus OBJECT IDENTIFIER ::= { xATSGenerator 3 }
+xATSGeneratorOutput OBJECT IDENTIFIER ::= { xATSGenerator 4 }
+xATSGeneratorSettings OBJECT IDENTIFIER ::= { xATSGenerator 5 }
+xATSGeneratorService OBJECT IDENTIFIER ::= { xATSGenerator 6 }
+xATSGeneratorFuelSystem OBJECT IDENTIFIER ::= { xATSGenerator 7 }
+
+
+smartUPS250 OBJECT IDENTIFIER ::= { smartUPS 1 }
+smartUPS400 OBJECT IDENTIFIER ::= { smartUPS 2 }
+smartUPS600 OBJECT IDENTIFIER ::= { smartUPS 3 }
+smartUPS900 OBJECT IDENTIFIER ::= { smartUPS 4 }
+smartUPS1250 OBJECT IDENTIFIER ::= { smartUPS 5 }
+smartUPS2000 OBJECT IDENTIFIER ::= { smartUPS 6 }
+
+smartUPS450 OBJECT IDENTIFIER ::= { smartUPS 7 }
+smartUPS700 OBJECT IDENTIFIER ::= { smartUPS 8 }
+smartUPS1000 OBJECT IDENTIFIER ::= { smartUPS 9 }
+smartUPS1400 OBJECT IDENTIFIER ::= { smartUPS 10 }
+smartUPS2200 OBJECT IDENTIFIER ::= { smartUPS 11 }
+smartUPS3000 OBJECT IDENTIFIER ::= { smartUPS 12 }
+smartUPS5000 OBJECT IDENTIFIER ::= { smartUPS 13 }
+smartUPS7500 OBJECT IDENTIFIER ::= { smartUPS 14 }
+smartUPS10000 OBJECT IDENTIFIER ::= { smartUPS 15 }
+smartUPS1500 OBJECT IDENTIFIER ::= { smartUPS 16 }
+
+matrixUPS3000 OBJECT IDENTIFIER ::= { matrixUPS 1 }
+matrixUPS5000 OBJECT IDENTIFIER ::= { matrixUPS 2 }
+
+masterSwitchV1 OBJECT IDENTIFIER ::= { masterSwitch 1}
+masterSwitchV2 OBJECT IDENTIFIER ::= { masterSwitch 2}
+masterSwitchVM OBJECT IDENTIFIER ::= { masterSwitch 3}
+masterSwitchMSP OBJECT IDENTIFIER ::= { masterSwitch 4}
+masterSwitchrPDU OBJECT IDENTIFIER ::= { masterSwitch 5}
+
+symmetraUPS4kVA OBJECT IDENTIFIER ::= { symmetraUPS 1 }
+symmetraUPS8kVA OBJECT IDENTIFIER ::= { symmetraUPS 2 }
+symmetraUPS12kVA OBJECT IDENTIFIER ::= { symmetraUPS 3 }
+symmetraUPS16kVA OBJECT IDENTIFIER ::= { symmetraUPS 4 }
+
+environmental OBJECT IDENTIFIER ::= { monitors 1 }
+environmentalMgtSystem OBJECT IDENTIFIER ::= { monitors 2 }
+emu2 OBJECT IDENTIFIER ::= { monitors 3 }
+
+dm3 OBJECT IDENTIFIER ::= { dcPower 1 }
+dcmim2 OBJECT IDENTIFIER ::= { dcPower 2 }
+
+symmetra3PhaseUPS40kVA OBJECT IDENTIFIER ::= { symmetra3PhaseUPS 1 }
+symmetra3PhaseUPS60kVA OBJECT IDENTIFIER ::= { symmetra3PhaseUPS 2 }
+symmetra3PhaseUPS80kVA OBJECT IDENTIFIER ::= { symmetra3PhaseUPS 3 }
+symmetra3PhaseUPS20kVA OBJECT IDENTIFIER ::= { symmetra3PhaseUPS 4 }
+
+airFMSeries OBJECT IDENTIFIER ::= { networkAir 1 }
+rackAirRemovalUnit OBJECT IDENTIFIER ::= { networkAir 2 }
+airPASeries OBJECT IDENTIFIER ::= { networkAir 3 }
+
+ais5000UPS10kVA OBJECT IDENTIFIER ::= { ais5000UPS 1 }
+ais5000UPS20kVA OBJECT IDENTIFIER ::= { ais5000UPS 2 }
+ais5000UPS30kVA OBJECT IDENTIFIER ::= { ais5000UPS 3 }
+ais5000UPS40kVA OBJECT IDENTIFIER ::= { ais5000UPS 4 }
+ais5000UPS60kVA OBJECT IDENTIFIER ::= { ais5000UPS 5 }
+ais5000UPS80kVA OBJECT IDENTIFIER ::= { ais5000UPS 6 }
+ais5000UPS100kVA OBJECT IDENTIFIER ::= { ais5000UPS 7 }
+
+smartUPS3Phase10kVA OBJECT IDENTIFIER ::= { smartUPS3Phase 1 }
+smartUPS3Phase15kVA OBJECT IDENTIFIER ::= { smartUPS3Phase 2 }
+smartUPS3Phase20kVA OBJECT IDENTIFIER ::= { smartUPS3Phase 3 }
+smartUPS3Phase30kVA OBJECT IDENTIFIER ::= { smartUPS3Phase 4 }
+smartUPS3Phase40kVA OBJECT IDENTIFIER ::= { smartUPS3Phase 5 }
+
+upsIdent OBJECT IDENTIFIER ::= { ups 1 }
+upsBattery OBJECT IDENTIFIER ::= { ups 2 }
+upsInput OBJECT IDENTIFIER ::= { ups 3 }
+upsOutput OBJECT IDENTIFIER ::= { ups 4 }
+upsConfig OBJECT IDENTIFIER ::= { ups 5 }
+upsControl OBJECT IDENTIFIER ::= { ups 6 }
+upsTest OBJECT IDENTIFIER ::= { ups 7 }
+upsComm OBJECT IDENTIFIER ::= { ups 8 }
+upsPhase OBJECT IDENTIFIER ::= { ups 9 }
+upsSyncCtrlGroup OBJECT IDENTIFIER ::= { ups 10 }
+upsState OBJECT IDENTIFIER ::= { ups 11 }
+upsOutletGroups OBJECT IDENTIFIER ::= { ups 12 }
+upsDiagnostics OBJECT IDENTIFIER ::= { ups 13 }
+
+upsBasicIdent OBJECT IDENTIFIER ::= { upsIdent 1 }
+upsAdvIdent OBJECT IDENTIFIER ::= { upsIdent 2 }
+
+upsBasicBattery OBJECT IDENTIFIER ::= { upsBattery 1 }
+upsAdvBattery OBJECT IDENTIFIER ::= { upsBattery 2 }
+
+upsBasicInput OBJECT IDENTIFIER ::= { upsInput 1 }
+upsAdvInput OBJECT IDENTIFIER ::= { upsInput 2 }
+
+upsBasicOutput OBJECT IDENTIFIER ::= { upsOutput 1 }
+upsAdvOutput OBJECT IDENTIFIER ::= { upsOutput 2 }
+
+upsBasicConfig OBJECT IDENTIFIER ::= { upsConfig 1 }
+upsAdvConfig OBJECT IDENTIFIER ::= { upsConfig 2 }
+
+upsBasicControl OBJECT IDENTIFIER ::= { upsControl 1 }
+upsAdvControl OBJECT IDENTIFIER ::= { upsControl 2 }
+
+upsBasicTest OBJECT IDENTIFIER ::= { upsTest 1 }
+upsAdvTest OBJECT IDENTIFIER ::= { upsTest 2 }
+
+upsPhaseResetValues OBJECT IDENTIFIER ::= { upsPhase 1 }
+upsPhaseInput OBJECT IDENTIFIER ::= { upsPhase 2 }
+upsPhaseOutput OBJECT IDENTIFIER ::= { upsPhase 3 }
+
+upsSyncCtrlGroupConfig OBJECT IDENTIFIER ::= { upsSyncCtrlGroup 1 }
+upsSyncCtrlGroupStatus OBJECT IDENTIFIER ::= { upsSyncCtrlGroup 2 }
+
+upsBasicState OBJECT IDENTIFIER ::= { upsState 1 }
+upsAdvState OBJECT IDENTIFIER ::= { upsState 2 }
+
+upsOutletGroupStatus OBJECT IDENTIFIER ::= { upsOutletGroups 1 }
+upsOutletGroupConfig OBJECT IDENTIFIER ::= { upsOutletGroups 2 }
+upsOutletGroupControl OBJECT IDENTIFIER ::= { upsOutletGroups 3 }
+
+upsDiagnosticIM OBJECT IDENTIFIER ::= { upsDiagnostics 1 }
+upsDiagnosticPowerModules OBJECT IDENTIFIER ::= { upsDiagnostics 2 }
+upsDiagnosticBatteries OBJECT IDENTIFIER ::= { upsDiagnostics 3 }
+upsDiagnosticSubsystem OBJECT IDENTIFIER ::= { upsDiagnostics 4 }
+upsDiagnosticExternalDevices OBJECT IDENTIFIER ::= { upsDiagnostics 5 }
+upsDiagnosticComBus OBJECT IDENTIFIER ::= { upsDiagnostics 6 }
+
+upsDiagSwitchGear OBJECT IDENTIFIER ::= { upsDiagnosticExternalDevices 1 }
+upsDiagMCCBBox OBJECT IDENTIFIER ::= { upsDiagnosticExternalDevices 2 }
+upsDiagTransformer OBJECT IDENTIFIER ::= { upsDiagnosticExternalDevices 3 }
+
+mUpsEnviron OBJECT IDENTIFIER ::= { measureUps 1 }
+mUpsContact OBJECT IDENTIFIER ::= { measureUps 2 }
+
+serialPort OBJECT IDENTIFIER ::= { miniSNMPadapter 1}
+
+serialPort1 OBJECT IDENTIFIER ::= { serialPort 1}
+serialPort2 OBJECT IDENTIFIER ::= { serialPort 2}
+
+serialPort2Config OBJECT IDENTIFIER ::= { serialPort2 1}
+serialPort2Control OBJECT IDENTIFIER ::= { serialPort2 2}
+
+sPDUIdent OBJECT IDENTIFIER ::= { masterswitch 1 }
+sPDUMasterControl OBJECT IDENTIFIER ::= { masterswitch 2 }
+sPDUMasterConfig OBJECT IDENTIFIER ::= { masterswitch 3 }
+sPDUOutletControl OBJECT IDENTIFIER ::= { masterswitch 4 }
+sPDUOutletConfig OBJECT IDENTIFIER ::= { masterswitch 5 }
+
+sPDUIdentVM OBJECT IDENTIFIER ::= { masterswitchVM 1 }
+sPDUMasterControlVM OBJECT IDENTIFIER ::= { masterswitchVM 2 }
+sPDUMasterConfigVM OBJECT IDENTIFIER ::= { masterswitchVM 3 }
+sPDUMasterStatusVM OBJECT IDENTIFIER ::= { masterswitchVM 4 }
+sPDUOutletControlVM OBJECT IDENTIFIER ::= { masterswitchVM 5 }
+sPDUOutletConfigVM OBJECT IDENTIFIER ::= { masterswitchVM 6 }
+sPDUOutletStatusVM OBJECT IDENTIFIER ::= { masterswitchVM 7 }
+
+sPDUIdentMSP OBJECT IDENTIFIER ::= { masterswitchMSP 1 }
+sPDUMasterControlMSP OBJECT IDENTIFIER ::= { masterswitchMSP 2 }
+sPDUMasterConfigMSP OBJECT IDENTIFIER ::= { masterswitchMSP 3 }
+sPDUMasterStatusMSP OBJECT IDENTIFIER ::= { masterswitchMSP 4 }
+sPDUOutletControlMSP OBJECT IDENTIFIER ::= { masterswitchMSP 5 }
+sPDUOutletConfigMSP OBJECT IDENTIFIER ::= { masterswitchMSP 6 }
+sPDUOutletStatusMSP OBJECT IDENTIFIER ::= { masterswitchMSP 7 }
+
+sPDUOutletConfigMSPall OBJECT IDENTIFIER ::= { sPDUOutletConfigMSP 1 }
+sPDUOutletConfigMSPgs OBJECT IDENTIFIER ::= { sPDUOutletConfigMSP 2 }
+sPDUOutletConfigMSPannun OBJECT IDENTIFIER ::= { sPDUOutletConfigMSP 3 }
+sPDUOutletConfigMSPmups OBJECT IDENTIFIER ::= { sPDUOutletConfigMSP 4 }
+
+rPDUIdent OBJECT IDENTIFIER ::= { rPDU 1 }
+rPDULoad OBJECT IDENTIFIER ::= { rPDU 2 }
+rPDUOutlet OBJECT IDENTIFIER ::= { rPDU 3 }
+rPDUPowerSupply OBJECT IDENTIFIER ::= { rPDU 4 }
+
+rPDULoadDevice OBJECT IDENTIFIER ::= { rPDULoad 1 }
+rPDULoadPhaseConfig OBJECT IDENTIFIER ::= { rPDULoad 2 }
+rPDULoadStatus OBJECT IDENTIFIER ::= { rPDULoad 3 }
+rPDULoadBankConfig OBJECT IDENTIFIER ::= { rPDULoad 4 }
+
+rPDUOutletDevice OBJECT IDENTIFIER ::= { rPDUOutlet 1 }
+rPDUOutletPhase OBJECT IDENTIFIER ::= { rPDUOutlet 2 }
+rPDUOutletControl OBJECT IDENTIFIER ::= { rPDUOutlet 3 }
+rPDUOutletConfig OBJECT IDENTIFIER ::= { rPDUOutlet 4 }
+rPDUOutletStatus OBJECT IDENTIFIER ::= { rPDUOutlet 5 }
+rPDUOutletBank OBJECT IDENTIFIER ::= { rPDUOutlet 6 }
+
+rPDUPowerSupplyDevice OBJECT IDENTIFIER ::= { rPDUPowerSupply 1 }
+
+dm3Ident OBJECT IDENTIFIER ::= { dcDM3 1 }
+dm3Config OBJECT IDENTIFIER ::= { dcDM3 2 }
+dm3Status OBJECT IDENTIFIER ::= { dcDM3 3 }
+
+dm3IdentSystem OBJECT IDENTIFIER ::= { dm3Ident 1}
+
+dm3ConfigSystem OBJECT IDENTIFIER ::= { dm3Config 1 }
+dm3ConfigLVD OBJECT IDENTIFIER ::= { dm3Config 2 }
+dm3ConfigBattery OBJECT IDENTIFIER ::= { dm3Config 3 }
+dm3ConfigPowerModules OBJECT IDENTIFIER ::= { dm3Config 4 }
+dm3ConfigRelays OBJECT IDENTIFIER ::= { dm3Config 5 }
+dm3ConfigDistribution OBJECT IDENTIFIER ::= { dm3Config 6 }
+
+dm3ConfigRectifier OBJECT IDENTIFIER ::= { dm3ConfigPowerModules 1 }
+dm3ConfigConverter OBJECT IDENTIFIER ::= { dm3ConfigPowerModules 2 }
+
+dm3ConfigRectThresh OBJECT IDENTIFIER ::= { dm3ConfigRectifier 1 }
+dm3ConfigRectAlarms OBJECT IDENTIFIER ::= { dm3ConfigRectifier 2 }
+
+dm3ConfigConvThresh OBJECT IDENTIFIER ::= { dm3ConfigConverter 1 }
+dm3ConfigConvAlarms OBJECT IDENTIFIER ::= { dm3ConfigConverter 2 }
+
+dm3ConfigOutputRelays OBJECT IDENTIFIER ::= { dm3ConfigRelays 1 }
+dm3ConfigInputRelays OBJECT IDENTIFIER ::= { dm3ConfigRelays 2 }
+
+dm3ConfigBreakers OBJECT IDENTIFIER ::= { dm3ConfigDistribution 1 }
+dm3ConfigFuses OBJECT IDENTIFIER ::= { dm3ConfigDistribution 2 }
+
+dm3StatusSystem OBJECT IDENTIFIER ::= { dm3Status 1 }
+dm3StatusAlarms OBJECT IDENTIFIER ::= { dm3Status 2 }
+dm3StatusBattery OBJECT IDENTIFIER ::= { dm3Status 3 }
+dm3StatusOEM OBJECT IDENTIFIER ::= { dm3Status 4 }
+dm3StatusLVD OBJECT IDENTIFIER ::= { dm3Status 5 }
+dm3StatusPowerModules OBJECT IDENTIFIER ::= { dm3Status 6 }
+dm3StatusRelays OBJECT IDENTIFIER ::= { dm3Status 7 }
+dm3StatusDistribution OBJECT IDENTIFIER ::= { dm3Status 8 }
+
+dm3StatusRectifier OBJECT IDENTIFIER ::= { dm3StatusPowerModules 1 }
+dm3StatusConverter OBJECT IDENTIFIER ::= { dm3StatusPowerModules 2 }
+
+dm3StatusOutputRelays OBJECT IDENTIFIER ::= { dm3StatusRelays 1 }
+dm3StatusInputRelays OBJECT IDENTIFIER ::= { dm3StatusRelays 2 }
+
+dm3StatusBreakers OBJECT IDENTIFIER ::= { dm3StatusDistribution 1 }
+dm3StatusFuses OBJECT IDENTIFIER ::= { dm3StatusDistribution 2 }
+
+atsIdent OBJECT IDENTIFIER ::= { automaticTransferSwitch 1 }
+atsCalibration OBJECT IDENTIFIER ::= { automaticTransferSwitch 2 }
+atsControl OBJECT IDENTIFIER ::= { automaticTransferSwitch 3 }
+atsConfig OBJECT IDENTIFIER ::= { automaticTransferSwitch 4 }
+atsStatus OBJECT IDENTIFIER ::= { automaticTransferSwitch 5 }
+
+atsCalibrationInput OBJECT IDENTIFIER ::= { atsCalibration 1 }
+atsCalibrationPowerSupply OBJECT IDENTIFIER ::= { atsCalibration 2 }
+atsCalibrationOutput OBJECT IDENTIFIER ::= { atsCalibration 3 }
+
+atsStatusDeviceStatus OBJECT IDENTIFIER ::= { atsStatus 1 }
+atsStatusResetValues OBJECT IDENTIFIER ::= { atsStatus 2 }
+atsStatusInput OBJECT IDENTIFIER ::= { atsStatus 3 }
+atsStatusOutput OBJECT IDENTIFIER ::= { atsStatus 4 }
+
+dcmim2Ident OBJECT IDENTIFIER ::= { dc2 1 }
+dcmim2Control OBJECT IDENTIFIER ::= { dc2 2 }
+dcmim2Config OBJECT IDENTIFIER ::= { dc2 3 }
+dcmim2Status OBJECT IDENTIFIER ::= { dc2 4 }
+
+dcmim2IdentSystem OBJECT IDENTIFIER ::= { dcmim2Ident 1 }
+
+dcmim2ControlSystem OBJECT IDENTIFIER ::= { dcmim2Control 1 }
+
+dcmim2ConfigSystem OBJECT IDENTIFIER ::= { dcmim2Config 1 }
+dcmim2ConfigBattery OBJECT IDENTIFIER ::= { dcmim2Config 2 }
+dcmim2ConfigLVD OBJECT IDENTIFIER ::= { dcmim2Config 3 }
+
+dcmim2StatusSystem OBJECT IDENTIFIER ::= { dcmim2Status 1 }
+dcmim2StatusRectifier OBJECT IDENTIFIER ::= { dcmim2Status 2 }
+dcmim2StatusBattery OBJECT IDENTIFIER ::= { dcmim2Status 3 }
+dcmim2StatusLVD OBJECT IDENTIFIER ::= { dcmim2Status 4 }
+dcmim2StatusAlarms OBJECT IDENTIFIER ::= { dcmim2Status 5 }
+
+external OBJECT IDENTIFIER ::= { environmentalMonitor 1 }
+integrated OBJECT IDENTIFIER ::= { environmentalMonitor 2 }
+envMgtSystem OBJECT IDENTIFIER ::= { environmentalMonitor 3 }
+
+emIdent OBJECT IDENTIFIER ::= { external 1 }
+emConfig OBJECT IDENTIFIER ::= { external 2 }
+emStatus OBJECT IDENTIFIER ::= { external 3 }
+
+iemIdent OBJECT IDENTIFIER ::= { integrated 1 }
+iemConfig OBJECT IDENTIFIER ::= { integrated 2 }
+iemStatus OBJECT IDENTIFIER ::= { integrated 3 }
+
+emsIdent OBJECT IDENTIFIER ::= { envMgtSystem 1 }
+
+emsOutputRelayControl OBJECT IDENTIFIER ::= { envMgtSystem 2 }
+emsOutletControl OBJECT IDENTIFIER ::= { envMgtSystem 3 }
+emsSensorControl OBJECT IDENTIFIER ::= { envMgtSystem 4 }
+emsAlarmDeviceControl OBJECT IDENTIFIER ::= { envMgtSystem 5 }
+
+emsConfig OBJECT IDENTIFIER ::= { envMgtSystem 6 }
+emsProbeConfig OBJECT IDENTIFIER ::= { envMgtSystem 7 }
+emsInputContactConfig OBJECT IDENTIFIER ::= { envMgtSystem 8 }
+emsOutputRelayConfig OBJECT IDENTIFIER ::= { envMgtSystem 9 }
+emsOutletConfig OBJECT IDENTIFIER ::= { envMgtSystem 10 }
+emsSensorConfig OBJECT IDENTIFIER ::= { envMgtSystem 11 }
+
+emsStatus OBJECT IDENTIFIER ::= { envMgtSystem 12 }
+emsProbeStatus OBJECT IDENTIFIER ::= { envMgtSystem 13 }
+emsInputContactStatus OBJECT IDENTIFIER ::= { envMgtSystem 14 }
+emsOutputRelayStatus OBJECT IDENTIFIER ::= { envMgtSystem 15 }
+emsOutletStatus OBJECT IDENTIFIER ::= { envMgtSystem 16 }
+emsAlarmDeviceStatus OBJECT IDENTIFIER ::= { envMgtSystem 17 }
+emsSensorStatus OBJECT IDENTIFIER ::= { envMgtSystem 18 }
+
+nlIdent OBJECT IDENTIFIER ::= { netlock 1 }
+nlStatus OBJECT IDENTIFIER ::= { netlock 2 }
+
+airFM OBJECT IDENTIFIER ::= { airConditioners 1 }
+airFMIdent OBJECT IDENTIFIER ::= { airFM 1 }
+airFMStatus OBJECT IDENTIFIER ::= { airFM 2 }
+airFMGroup OBJECT IDENTIFIER ::= { airFM 3 }
+
+airPA OBJECT IDENTIFIER ::= { airConditioners 2 }
+airPAIdent OBJECT IDENTIFIER ::= { airPA 1 }
+airPAStatus OBJECT IDENTIFIER ::= { airPA 2 }
+
+rARUIdent OBJECT IDENTIFIER ::= { rARU 1 }
+rARUConfig OBJECT IDENTIFIER ::= { rARU 2 }
+rARUStatus OBJECT IDENTIFIER ::= { rARU 3 }
+
+
+-- object types
+
+-- the products group
+-- the experimental group
+
+
+
+-- the apcmgmt group
+-- the mconfig group
+
+mconfigNumTrapReceivers OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of managers to send traps to."
+ ::= { mconfig 1 }
+
+mconfigTrapReceiverTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MconfigTrapReceiverEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of managers to send traps to. The number of
+ entries is given by the value of mconfigNumTrapReceivers.
+ Maximum number of Trap Receivers is four."
+ ::= { mconfig 2 }
+
+mconfigTrapReceiverEntry OBJECT-TYPE
+ SYNTAX MconfigTrapReceiverEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The managers to send traps to."
+ INDEX { trapIndex}
+ ::= { mconfigTrapReceiverTable 1 }
+
+MconfigTrapReceiverEntry ::=
+ SEQUENCE {
+ trapIndex
+ INTEGER,
+ receiverAddr
+ IpAddress,
+ communityString
+ DisplayString,
+ severity
+ INTEGER,
+ acceptThisReceiver
+ INTEGER,
+ receiveTrapType
+ INTEGER
+ }
+
+trapIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to a trap receiver entry."
+ ::= { mconfigTrapReceiverEntry 1 }
+
+receiverAddr OBJECT-TYPE
+ SYNTAX IpAddress
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The IP address of the manager to send a trap to."
+ ::= { mconfigTrapReceiverEntry 2 }
+
+communityString OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The community name to use in the trap when
+ sent to the manager."
+ ::= { mconfigTrapReceiverEntry 3 }
+
+severity OBJECT-TYPE
+ SYNTAX INTEGER {
+ information(1),
+ warning(2),
+ severe(3)
+ }
+ ACCESS read-only
+ STATUS obsolete
+ DESCRIPTION
+ "The severity threshold of traps to send to the manager.
+ traps are labeled in severity as informational(1), warning(2),
+ severe(3). Only traps of equal or greater severity than
+ this value are sent to the manager."
+ ::= { mconfigTrapReceiverEntry 4 }
+
+acceptThisReceiver OBJECT-TYPE
+ SYNTAX INTEGER {
+ yes (1),
+ no (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "An entry will become active if yes, and will
+ be deleted if no."
+ ::= { mconfigTrapReceiverEntry 5 }
+
+
+receiveTrapType OBJECT-TYPE
+ SYNTAX INTEGER {
+ powernet (1),
+ ietf (2),
+ both (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The node in this entry will receive traps defined in APC
+ PowerNet MIB, if this OID is set to yes."
+ ::= { mconfigTrapReceiverEntry 6 }
+
+mconfigBOOTPEnabled OBJECT-TYPE
+ SYNTAX INTEGER {
+ yes (1),
+ no (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The value of yes(1) indicates the PowerNet Adapter is configured to
+ obtain its IP configuration parameters from a BOOTP server.
+
+ The value of no(2) indicates adapter will assume IP configuration parameters
+ values saved in adapter's eeprom, which was originally configured at local
+ console."
+ ::= { mconfig 3 }
+
+mconfigTFTPServerIP OBJECT-TYPE
+ SYNTAX IpAddress
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The IP address of TFTP server. If mconfigBOOTPEnabled is yes(1), then this IP address
+ is provided by BOOTP server and not allowed to be modified; otherwise, this IP address
+ can be modified.
+
+ Before using TFTP to load new code image, the image file should be placed in proper
+ directory of the specified TFTP server. This OID is only supported by AP9605, AP9205,
+ and AP9603 PowerNet SNMP Adapters."
+ ::= { mconfig 4 }
+
+newCodeAuthentViaTFTP OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ validNewAgentCodeImage (2),
+ sameAgentCodeImage (3),
+ invalidAgentCodeImage (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Once mcontrolRestartAgent is set to loadAndExecuteNewAgent (3), PowerNet adapter will
+ start to load the remote image file, for authentication only, instead of saving the code
+ into flash memory. Only if a validNewAgentCodeImage (1) is found will the agent reboot
+ the PowerNet adapter and invoke the loader to load and save new code into the flash memory.
+ Otherwise, the current agent code will continue to run.
+
+ This OID shows the result of the above authentication process.
+ validNewAgentCodeImage (1) means the code image on TFTP server
+ is a valid APC agent code and is different version from the current agent.
+ Once agent identifies this, loader will start to update flash memory with
+ the new agent code.
+
+ sameAgentCodeImage (2) means the code image on TFTP server is exactly the
+ same as the currently running agent. Currently running agent will not invoke
+ loader to load the same again.
+
+ invalidAgentCodeImage (3) means the code image on TFTP server is NOT a valid
+ APC agent code. Thus, current agent will not load it into the flash memory.
+
+ The value of this OID will be associated with TRAP codeImageAuthentDone.
+ This OID is only supported by AP9605, AP9205, and AP9603 PowerNet SNMP Adapters."
+
+ ::= { mconfig 5 }
+
+mconfigClockDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The current date in the mm/dd/yyyy format. Example: 01/01/2000."
+ ::= { mconfigClock 1 }
+
+mconfigClockTime OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The current time in the hh:mm:ss am/pm format. Example: 12:00:00 am."
+ ::= { mconfigClock 2 }
+
+mcontrolRestartAgent OBJECT-TYPE
+ SYNTAX INTEGER {
+ restartCurrentAgent (1),
+ continueCurrentAgent (2),
+ loadAndExecuteNewAgent (3),
+ restartWithoutAgent (4),
+ resetNetworkAndRestart (5),
+ resetNetworkLeaveModeAndRestart (6)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to restartCurrentAgent (1) will restart the same SNMP
+ agent code currently saved in flash memory. Setting this OID to
+ loadAndExecuteNewAgent (3) will enable adapter to load a new agent code
+ into the flash memory and start to execute this new agent code.
+ Bootp/tftp is the default protocol. loadAndExecuteNewAgent is only
+ supported by AP9605, AP9205, and AP9603 PowerNet SNMP Adapters. Setting
+ this OID to restartWithoutAgent (4) will restart the system and not
+ start the agent. The subsequent time the system restarts the agent will
+ also automatically restart. Setting this OID to
+ resetNetworkAndRestart (5) will set the Boot Mode, IP Address, Subnet
+ Mask, and Default Gateway to defaults, expire any existing DHCP lease
+ and then restart the system. Setting this OID to
+ resetNetworkLeaveModeAndRestart (6) will leave the Boot Mode at the
+ current setting, set the IP Address, Subnet Mask, and Default Gateway to
+ defaults, expire any existing DHCP lease and then restart the system."
+
+ ::= { mcontrol 1 }
+
+-- The mtrapargs group
+-- These OIDs allows APC traps to be sent with additional arguments
+-- which may not be defined in the APC MIB.
+
+mtrapargsInteger OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an integer argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 1 }
+
+mtrapargsIpAddress OBJECT-TYPE
+ SYNTAX IpAddress
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an IP address argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0.0.0.0."
+ ::= { mtrapargs 2 }
+
+mtrapargsString OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an octet string argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return a NULL string."
+ ::= { mtrapargs 3 }
+
+mtrapargsGauge OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with a Gauge argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 4 }
+
+mtrapargsTimeTicks OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with a TimeTicks argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 5 }
+
+mtrapargsInteger02 OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an integer argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 6 }
+
+mtrapargsInteger03 OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an integer argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 7 }
+
+mtrapargsIpAddress02 OBJECT-TYPE
+ SYNTAX IpAddress
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an IP address argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0.0.0.0."
+ ::= { mtrapargs 8 }
+
+mtrapargsIpAddress03 OBJECT-TYPE
+ SYNTAX IpAddress
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an IP address argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0.0.0.0."
+ ::= { mtrapargs 9 }
+
+mtrapargsString02 OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an octet string argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return a NULL string."
+ ::= { mtrapargs 10 }
+
+mtrapargsString03 OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with an octet string argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return a NULL string."
+ ::= { mtrapargs 11 }
+
+mtrapargsGauge02 OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with a Gauge argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 12 }
+
+mtrapargsGauge03 OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with a Gauge argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 13 }
+
+mtrapargsTimeTicks02 OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with a TimeTicks argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 14 }
+
+mtrapargsTimeTicks03 OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID allows APC traps to be sent with a TimeTicks argument
+ that my not be defined in the APC MIB.
+
+ A get of this OID will return 0."
+ ::= { mtrapargs 15 }
+
+-- the mfiletransfer group
+-- the mfiletransferStatus group
+mfiletransferStatusLastTransferResult OBJECT-TYPE
+ SYNTAX INTEGER {
+ lastFileTransferResultSuccessful (1),
+ lastFileTransferResultNotAvailable (2),
+ lastFileTransferResultFailureUnknown (3),
+ lastFileTransferResultFailureServerInaccessible (4),
+ lastFileTransferResultFailureServerAccessDenied (5),
+ lastFileTransferResultFailureFileNotFound (6),
+ lastFileTransferResultFailureFileTypeUnknown (7),
+ lastFileTransferResultFailureFileCorrupted (8)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Once mfiletransferControlInitiateFileTransfer is set to a value other than doNotInitiateFileTransfer
+ a file transfer of mfiletransferConfigSettingsFilename will be attempted from either a TFTP or FTP
+ server.
+
+ This OID shows the last attempted file transfer result.
+ lastFileTransferResultSuccessful (1) means the file transfer was successful.
+ lastFileTransferResultNotAvailable (2) means that there have been no previous file transfers.
+ lastFileTransferResultFailureUnknown (3) means that the last file transfer failed for an unknown reason.
+ lastFileTransferResultFailureServerInaccessible (4) means that the TFTP or FTP server could not be found on the network.
+ lastFileTransferResultFailureServerAccessDenied (5) means that the TFTP or FTP server denied access.
+ lastFileTransferResultFailureFileNotFound (6) means that the file could not be located.
+ lastFileTransferResultFailureFileTypeUnknown (7) means the file was examined, but the contents were unknown.
+ lastFileTransferResultFailureFileCorrupt (8) means the transferred file was corrupt."
+
+ ::= { mfiletransferStatus 1 }
+
+-- the mfiletransferConfig group
+-- the mfiletransferConfigSettings group
+
+mfiletransferConfigSettingsFilename OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The path and name of the file to transfer using the mfiletransferControlInitiateFileTransfer OID.
+ If the file to transfer exists in the default server directory then the path may be omitted."
+
+ ::= { mfiletransferConfigSettings 1 }
+
+-- the mfiletransferConfigTFTP group
+
+mfiletransferConfigTFTPServerAddress OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The IP Address in dotted decimal notation of the TFTP server involved in the file transfer."
+
+ ::= { mfiletransferConfigTFTP 1 }
+
+-- the mfiletransferConfigFTP group
+
+mfiletransferConfigFTPServerAddress OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The IP Address in dotted decimal notation of the FTP server involved in the file transfer."
+
+ ::= { mfiletransferConfigFTP 1 }
+
+mfiletransferConfigFTPServerUser OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The user identification for logging into the FTP server specified with mfiletransferConfigFTPServerAddress."
+
+ ::= { mfiletransferConfigFTP 2 }
+
+mfiletransferConfigFTPServerPassword OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The password for logging into the FTP server specified with mfiletransferConfigFTPServerAddress."
+
+ ::= { mfiletransferConfigFTP 3 }
+
+-- the mfiletransferControl group
+
+mfiletransferControlInitiateFileTransfer OBJECT-TYPE
+ SYNTAX INTEGER {
+ doNotInitiateFileTransfer (1),
+ initiateFileTransferDownloadViaTFTP (2),
+ initiateFileTransferDownloadViaFTP (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to doNotInitiateFileTransfer (1) will do nothing.
+
+ Setting this OID to initiateFileTransferDownloadViaTFTP (2) will attempt to transfer the file named in
+ mfiletransferConfigSettingsFilename from the TFTP Server identified in mfiletransferConfigTFTPAddress.
+
+ Setting this OID to initiateFileTransferDownloadViaFTP (3) will attempt to transfer the file named in
+ mfiletransferConfigSettingsFilename from the FTP Server identified in mfiletransferConfigFTPAddress
+ using mfiletransferConfigFTPUser and mfiletransferConfigFTPPassword for the FTP Server login process."
+
+ ::= { mfiletransferControl 1 }
+
+-- the battManIdent group
+
+battManIdentProductName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the battery manager."
+ ::= { battManIdent 1 }
+
+battManIdentHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery manager network interface hardware revision.
+ This value is set at the factory."
+ ::= { battManIdent 2 }
+
+battManIdentFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery manager network interface firmware revision.
+ This value is set at the factory and can change with firmware update."
+ ::= { battManIdent 3 }
+
+battManIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date the battery manager was manufactured in mm/dd/yyyy format.
+ This value is set at the factory."
+ ::= { battManIdent 4 }
+
+battManIdentModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery manager model number character string.
+ This value is set at the factory."
+ ::= { battManIdent 5 }
+
+battManIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery manager serial number character string.
+ This value is set at the factory."
+ ::= { battManIdent 6 }
+
+-- the battManCalib group
+-- system calibration
+
+battManOhmicValueCorrectionFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The system ohmic value correction factor in percent."
+ ::= { battManSystemCalib 1 }
+
+-- unit calibration
+
+battManUnitCalibTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManUnitCalibTable."
+ ::= { battManUnitCalib 1 }
+
+battManUnitCalibTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManUnitCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting calibration information from each unit in the system."
+ ::= { battManUnitCalib 2 }
+
+battManUnitCalibTableEntry OBJECT-TYPE
+ SYNTAX BattManUnitCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The unit to get data from."
+ INDEX { battManUnitCalibIndex }
+ ::= { battManUnitCalibTable 1 }
+
+BattManUnitCalibTableEntry ::=
+ SEQUENCE {
+ battManUnitCalibIndex INTEGER,
+ battManUnitSerialNumber DisplayString,
+ battManBatteryVoltageZeroCalib INTEGER,
+ battManBatteryVoltageSpanCalib INTEGER
+ }
+
+battManUnitCalibIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of unit calibration entries in the table."
+ ::= { battManUnitCalibTableEntry 1 }
+
+battManUnitSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the unit."
+ ::= { battManUnitCalibTableEntry 2 }
+
+battManBatteryVoltageZeroCalib OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The unit battery voltage zero calibration in millivolts."
+ ::= { battManUnitCalibTableEntry 3 }
+
+battManBatteryVoltageSpanCalib OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The unit battery voltage span calibration in percent."
+ ::= { battManUnitCalibTableEntry 4 }
+
+-- string calibration table
+
+battManStringCalibTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManStringCalibTable."
+ ::= { battManStringCalib 1 }
+
+battManStringCalibTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManStringCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting calibration information from each string in the system."
+ ::= { battManStringCalib 2 }
+
+battManStringCalibTableEntry OBJECT-TYPE
+ SYNTAX BattManStringCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManStringCalibIndex }
+ ::= { battManStringCalibTable 1 }
+
+BattManStringCalibTableEntry ::=
+ SEQUENCE {
+ battManStringCalibIndex INTEGER,
+ battManDCCurrentZeroCalib INTEGER,
+ battManACCurrentZeroCalib INTEGER,
+ battManProbeRange INTEGER
+ }
+
+battManStringCalibIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of string calibration entries in the table."
+ ::= { battManStringCalibTableEntry 1 }
+
+battManDCCurrentZeroCalib OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The string DC current zero calibration in tenths of amps."
+ ::= { battManStringCalibTableEntry 2 }
+
+battManACCurrentZeroCalib OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The string AC current zero calibration in tenths of amps."
+ ::= { battManStringCalibTableEntry 3 }
+
+battManProbeRange OBJECT-TYPE
+ SYNTAX INTEGER {
+ amps1000 (1),
+ amps500 (2),
+ amps100 (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The string probe range in amps."
+ ::= { battManStringCalibTableEntry 4 }
+
+--string 1 battery calibration table
+
+battManString1BatteryCalibTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString1BatteryCalibTable."
+ ::= { battManBatteryCalib 1 }
+
+battManString1BatteryCalibTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString1BatteryCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting calibration information from each battery in String 1."
+ ::= { battManBatteryCalib 2 }
+
+battManString1BatteryCalibTableEntry OBJECT-TYPE
+ SYNTAX BattManString1BatteryCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString1BatteryCalibIndex }
+ ::= { battManString1BatteryCalibTable 1 }
+
+BattManString1BatteryCalibTableEntry ::=
+ SEQUENCE {
+ battManString1BatteryCalibIndex INTEGER,
+ battManString1BatteryInterTierOhmicValue INTEGER
+ }
+
+battManString1BatteryCalibIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of battery calibration entries in the table."
+ ::= { battManString1BatteryCalibTableEntry 1 }
+
+battManString1BatteryInterTierOhmicValue OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The battery inter-tier ohmic value in ohms. This corresponds to the ohmic
+ value for the positive terminal of the battery."
+ ::= { battManString1BatteryCalibTableEntry 2 }
+
+--string 2 battery calibration table
+
+battManString2BatteryCalibTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString2BatteryCalibTable."
+ ::= { battManBatteryCalib 3 }
+
+battManString2BatteryCalibTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString2BatteryCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting calibration information from each battery in String 2."
+ ::= { battManBatteryCalib 4 }
+
+battManString2BatteryCalibTableEntry OBJECT-TYPE
+ SYNTAX BattManString2BatteryCalibTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString2BatteryCalibIndex }
+ ::= { battManString2BatteryCalibTable 1 }
+
+BattManString2BatteryCalibTableEntry ::=
+ SEQUENCE {
+ battManString2BatteryCalibIndex INTEGER,
+ battManString2BatteryInterTierOhmicValue INTEGER
+ }
+
+battManString2BatteryCalibIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of battery calibration entries in the table."
+ ::= { battManString2BatteryCalibTableEntry 1 }
+
+battManString2BatteryInterTierOhmicValue OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The battery inter-tier ohmic value in ohms."
+ ::= { battManString2BatteryCalibTableEntry 2 }
+
+-- the battManConfig group
+
+battManConfigApplication OBJECT-TYPE
+ SYNTAX INTEGER {
+ silcon (1),
+ other (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The type of application the battery manager is installed on:
+ Silcon(1) Silcon UPS or
+ Other(2) Other UPS/Charger."
+ ::= { battManConfig 1 }
+
+battManConfigBatteryChemistry OBJECT-TYPE
+ SYNTAX INTEGER {
+ leadAcid (1),
+ nickel-Cadmium (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The battery chemistry of the monitored batteries:
+ LeadAcid(1) Lead Acid or
+ Nickel-Cadmium(2) Nickel-Cadmium."
+ ::= { battManConfig 2 }
+
+battManConfigBatteryAHCapacity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amp hour capacity of the monitored batteries 5-2000 AH."
+ ::= { battManConfig 3 }
+
+battManConfigNumberofStrings OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The number of strings in the battery manager system (1 - 2 Silcon)/(1 Other)."
+ ::= { battManConfig 4 }
+
+battManConfigBatteriesperString OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The number of batteries per string."
+ ::= { battManConfig 5 }
+
+battManConfigCellsperBattery OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The number of cells per battery (1 - 6 for lead-acid, 1 - 2 for NiCd."
+ ::= { battManConfig 6 }
+
+battManConfigMinCellVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum battery cell voltage alarm limit in millivolts DC."
+ ::= { battManConfig 7 }
+
+battManConfigMaxCellVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum battery cell voltage alarm limit in millivolts DC."
+ ::= { battManConfig 8 }
+
+battManConfigMaxPilotTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum pilot battery temperature alarm limit in tenths of degrees Fahrenheit."
+ ::= { battManConfig 9 }
+
+battManConfigMaxPilotTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum pilot battery temperature alarm limit in tenths of degrees Celcius."
+ ::= { battManConfig 10 }
+
+battManConfigMaxAmbientTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum ambient temperature alarm limit in tenths of degrees Fahrenheit."
+ ::= { battManConfig 11 }
+
+battManConfigMaxAmbientTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum ambient temperature alarm limit in tenths of degrees Celcius."
+ ::= { battManConfig 12 }
+
+battManConfigMinAmbientTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The Minimum Ambient Temperature alarm limit in tenths of degrees Fahrenheit."
+ ::= { battManConfig 13 }
+
+battManConfigMinAmbientTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The Minimum Ambient Temperature alarm limit in tenths of degrees Celcius."
+ ::= { battManConfig 14 }
+
+battManConfigMaxRippleCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum ripple current alarm limit for the monitored battery
+ strings in percent of AH capacity."
+ ::= { battManConfig 15 }
+
+battManConfigMaxCurrentAcceptanceDeviation OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum current acceptance deviation alarm limit in percentage."
+ ::= { battManConfig 16 }
+
+battManConfigMonitorWireLength OBJECT-TYPE
+ SYNTAX INTEGER {
+ fiftyFeetOrLess (1),
+ moreThanFiftyFeet (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The monitor wire length:
+ fiftyFeetOrLess (1) indicates that the wire length is less than or equal to 50 feet.
+ moreThanFiftyFeet (2) indicates that the wire length is greater than 50 feet."
+ ::= { battManConfig 17 }
+
+battManConfigDischargeVoltageAlarmLevel OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The discharge voltage alarm level in percent."
+ ::= { battManConfig 18 }
+
+battManConfigAutoAnnunciatorReset OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled (1),
+ enabled (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The annunciator output signal reset method:
+ disabled(1) means the annunciator signal output will be reset when the reset button is pressed.
+ enabled(2) means the annunciator will stop signalling when all alarm conditions clear."
+ ::= { battManConfig 19 }
+
+-- the battManAlarm group
+
+battManAlarmManagementController OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Management Controller Alarm is :
+ normal(1) no alarm condtions identified
+ alarm(2) an alarm condition exits."
+ ::= { battManAlarm 1 }
+
+battManAlarmBatteries OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Batteries Alarm is :
+ normal(1) no alarm condtions identified
+ alarm(2) an alarm condition exits."
+ ::= { battManAlarm 2 }
+
+battManAlarmCharger OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Charger Alarm is :
+ normal(1) no alarm condtions identified
+ alarm(2) an alarm condition exits."
+ ::= { battManAlarm 3 }
+
+battManAlarmEnvironment OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Environment Alarm is :
+ normal(1) no alarm condtions identified
+ alarm(2) an alarm condition exits."
+ ::= { battManAlarm 4 }
+
+-- the battManSystemStatus group
+
+-- These are system wide parameters
+
+battManSystemAmbientTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system ambient temperture in tenths of degrees Celcius."
+ ::= { battManSystemStatus 1 }
+
+battManSystemAmbientTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system ambient temperture in tenths of degrees Fahrenheit."
+ ::= { battManSystemStatus 2 }
+
+battManSystemPilotTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system pilot temperature in tenths of degrees Celcius."
+ ::= { battManSystemStatus 3 }
+
+battManSystemPilotTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system pilot temperature in tenths of degrees Fahrenheit."
+ ::= { battManSystemStatus 4 }
+
+battManSystemAmbientHighTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the system has a high temperature alarm."
+ ::= { battManSystemStatus 5 }
+
+battManSystemAmbientLowTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the system has a low temperature alarm."
+ ::= { battManSystemStatus 6 }
+
+battManSystemPilotBatteryHighTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the system has a pilot battery high temperature alarm."
+ ::= { battManSystemStatus 7 }
+
+battManSystemPilotProbeDisconnected OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the system pilot probe is disconnected."
+ ::= { battManSystemStatus 8 }
+
+battManSystemAmbientProbeDisconnected OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the system ambient probe is disconnected."
+ ::= { battManSystemStatus 9 }
+
+-- This is a table of input contact parameters
+
+battManInputContactTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManContactTable."
+ ::= { battManInputContactStatus 1 }
+
+battManInputContactTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManInputContactTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting information from each contact
+ in the system. "
+ ::= { battManInputContactStatus 2 }
+
+battManInputContactTableEntry OBJECT-TYPE
+ SYNTAX BattManInputContactTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The contact to get data from."
+ INDEX { battManInputContactIndex }
+ ::= { battManInputContactTable 1 }
+
+BattManInputContactTableEntry ::=
+ SEQUENCE {
+ battManInputContactIndex INTEGER,
+ battManInputContactName DisplayString,
+ battManInputContactAlarmState INTEGER,
+ battManInputContactState INTEGER,
+ battManInputContactNormalState INTEGER,
+ battManInputContactAlarmDelay INTEGER
+ }
+
+battManInputContactIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of contact entries in the table."
+ ::= { battManInputContactTableEntry 1 }
+
+battManInputContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the input contact."
+ ::= { battManInputContactTableEntry 2 }
+
+battManInputContactAlarmState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the alarm condition is active for this contact."
+ ::= { battManInputContactTableEntry 3 }
+
+battManInputContactState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to open(1), the input contact is in the open state.
+ When set to closed(2), the input contact is in the closed state."
+ ::= { battManInputContactTableEntry 4 }
+
+battManInputContactNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to open(1), the input contact is normally open.
+ When set to closed(2), the input contact is normally closed."
+ ::= { battManInputContactTableEntry 5 }
+
+battManInputContactAlarmDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The alarm delay time in seconds."
+ ::= { battManInputContactTableEntry 6 }
+
+-- This is a table of battery string parameters
+
+battManStringTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManStringTable."
+ ::= { battManStringStatus 1 }
+
+battManStringTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManStringTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting information from each string
+ in the system. "
+ ::= { battManStringStatus 2 }
+
+battManStringTableEntry OBJECT-TYPE
+ SYNTAX BattManStringTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManStringIndex }
+ ::= { battManStringTable 1 }
+
+BattManStringTableEntry ::=
+ SEQUENCE {
+ battManStringIndex INTEGER,
+ battManStringCurrent INTEGER,
+ battManStringRippleCurrent INTEGER,
+ battManStringChargerHighVoltageAlarm INTEGER,
+ battManStringChargerLowVoltageAlarm INTEGER,
+ battManStringCurrentProbeDisconnected INTEGER,
+ battManStringOnBattery INTEGER
+ }
+
+battManStringIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of string entries in the table."
+ ::= { battManStringTableEntry 1 }
+
+battManStringCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The string current in tenths of Amps."
+ ::= { battManStringTableEntry 2 }
+
+battManStringRippleCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The string ripple current in tenths of Amps."
+ ::= { battManStringTableEntry 3 }
+
+battManStringChargerHighVoltageAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the string charger has a high voltage alarm."
+ ::= { battManStringTableEntry 4 }
+
+battManStringChargerLowVoltageAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the string charger has a low voltage alarm."
+ ::= { battManStringTableEntry 5 }
+
+battManStringCurrentProbeDisconnected OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the string charger probe is disconnected."
+ ::= { battManStringTableEntry 6 }
+
+battManStringOnBattery OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that the string is in the on-battery state."
+ ::= { battManStringTableEntry 7 }
+
+-- the battManString1BatteryStatus group
+
+battManString1BatteryTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString1BatteryStatusTable."
+ ::= { battManBatteryStatus 1 }
+
+battManString1BatteryTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString1BatteryTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting information from each string
+ in the system. "
+ ::= { battManBatteryStatus 2 }
+
+battManString1BatteryTableEntry OBJECT-TYPE
+ SYNTAX BattManString1BatteryTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString1BatteryIndex }
+ ::= { battManString1BatteryTable 1 }
+
+BattManString1BatteryTableEntry ::=
+ SEQUENCE {
+ battManString1BatteryIndex INTEGER,
+ battManString1BatteryVoltage INTEGER,
+ battManString1BatteryLowestVoltage INTEGER,
+ battManString1BatteryCellShorted INTEGER,
+ battManString1BatteryOpenFuseOrConnection INTEGER,
+ battManString1BatteryLowCapacity INTEGER,
+ battManString1BatteryHighOhmicValue INTEGER,
+ battManString1BatteryThermalRunaway INTEGER,
+ battManString1BatteryDryout INTEGER
+ }
+
+battManString1BatteryIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of string entries in the table."
+ ::= { battManString1BatteryTableEntry 1 }
+
+battManString1BatteryVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery voltage in milli VDC."
+ ::= { battManString1BatteryTableEntry 2 }
+
+battManString1BatteryLowestVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The lowest battery discharge voltage during the last power event in milli VDC."
+ ::= { battManString1BatteryTableEntry 3 }
+
+battManString1BatteryCellShorted OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that a battery cell is shorted."
+ ::= { battManString1BatteryTableEntry 4 }
+
+battManString1BatteryOpenFuseOrConnection OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that a fuse or connection is open."
+ ::= { battManString1BatteryTableEntry 5 }
+
+battManString1BatteryLowCapacity OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has low capacity."
+ ::= { battManString1BatteryTableEntry 6 }
+
+battManString1BatteryHighOhmicValue OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has a high ohmic value."
+ ::= { battManString1BatteryTableEntry 7 }
+
+battManString1BatteryThermalRunaway OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has a thermal runaway condition."
+ ::= { battManString1BatteryTableEntry 8 }
+
+battManString1BatteryDryout OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has a dryout condition."
+ ::= { battManString1BatteryTableEntry 9 }
+
+-- the battManString2BatteryStatus group
+
+battManString2BatteryTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString2BatteryStatusTable."
+ ::= { battManBatteryStatus 3 }
+
+battManString2BatteryTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString2BatteryTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting information from each string
+ in the system. "
+ ::= { battManBatteryStatus 4 }
+
+battManString2BatteryTableEntry OBJECT-TYPE
+ SYNTAX BattManString2BatteryTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString2BatteryIndex }
+ ::= { battManString2BatteryTable 1 }
+
+BattManString2BatteryTableEntry ::=
+ SEQUENCE {
+ battManString2BatteryIndex INTEGER,
+ battManString2BatteryVoltage INTEGER,
+ battManString2BatteryLowestVoltage INTEGER,
+ battManString2BatteryCellShorted INTEGER,
+ battManString2BatteryOpenFuseOrConnection INTEGER,
+ battManString2BatteryLowCapacity INTEGER,
+ battManString2BatteryHighOhmicValue INTEGER,
+ battManString2BatteryThermalRunaway INTEGER,
+ battManString2BatteryDryout INTEGER
+ }
+
+battManString2BatteryIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of string entries in the table."
+ ::= { battManString2BatteryTableEntry 1 }
+
+battManString2BatteryVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery voltage in milli VDC."
+ ::= { battManString2BatteryTableEntry 2 }
+
+battManString2BatteryLowestVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The lowest battery discharge voltage during the last power event in milli VDC."
+ ::= { battManString2BatteryTableEntry 3 }
+
+battManString2BatteryCellShorted OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that a battery cell is shorted."
+ ::= { battManString2BatteryTableEntry 4 }
+
+battManString2BatteryOpenFuseOrConnection OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates that a fuse or connection is open."
+ ::= { battManString2BatteryTableEntry 5 }
+
+battManString2BatteryLowCapacity OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has low capacity."
+ ::= { battManString2BatteryTableEntry 6 }
+
+battManString2BatteryHighOhmicValue OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has a high ohmic value."
+ ::= { battManString2BatteryTableEntry 7 }
+
+battManString2BatteryThermalRunaway OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has a thermal runaway condition."
+ ::= { battManString2BatteryTableEntry 8 }
+
+battManString2BatteryDryout OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ alarm (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When set to alarm(2), indicates a battery has a dryout condition."
+ ::= { battManString2BatteryTableEntry 9 }
+
+-- battery manager control group
+battManRemoteAnnunciatorReset OBJECT-TYPE
+ SYNTAX INTEGER {
+ noOperation (1),
+ reset (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to reset(2) will reset the user interface annunciator.
+ Getting this OID will do nothing and return the noOperation(1) value."
+ ::= { battManControl 1 }
+
+battManResetChargeCurrentDeviationBenchmark OBJECT-TYPE
+ SYNTAX INTEGER {
+ noOperation (1),
+ reset (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to reset(2) will reset the charge current deviation benchmark.
+ Getting this OID will do nothing and return the noOperation(1) value."
+ ::= { battManControl 2 }
+
+battManResetLowestDischargeVoltages OBJECT-TYPE
+ SYNTAX INTEGER {
+ noOperation (1),
+ reset (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to reset(2) will reset the lowest discharge voltages.
+ Getting this OID will do nothing and return the noOperation(1) value."
+ ::= { battManControl 3 }
+
+-- the battManTestResults group
+
+--string 1 test results table
+
+battManString1OhmicValueLastDischargeInfo OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Informational text showing the date/time, load, and pilot temperature for the string
+ during the last discharge when ohmic values were recorded."
+ ::= { battManTestResults 1 }
+
+battManString1OhmicValueTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString1OhmicValueTable."
+ ::= { battManTestResults 2 }
+
+battManString1OhmicValueTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString1OhmicValueTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting ohmic value information from each battery in String 1."
+ ::= { battManTestResults 3 }
+
+battManString1OhmicValueTableEntry OBJECT-TYPE
+ SYNTAX BattManString1OhmicValueTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString1OhmicValueIndex }
+ ::= { battManString1OhmicValueTable 1 }
+
+BattManString1OhmicValueTableEntry ::=
+ SEQUENCE {
+ battManString1OhmicValueIndex INTEGER,
+ battManString1OhmicValueData INTEGER
+ }
+
+battManString1OhmicValueIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery number."
+ ::= { battManString1OhmicValueTableEntry 1 }
+
+battManString1OhmicValueData OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery inter-tier ohmic value in ohms.
+ Note: Negative values are invalid and may indicate faulty calibration
+ of ohmic value correction factors."
+ ::= { battManString1OhmicValueTableEntry 2 }
+
+battManString1ResponseTestChangeTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString1ResponseTestChangeTable."
+ ::= { battManTestResults 4 }
+
+battManString1ResponseTestChangeTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString1ResponseTestChangeTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting response test change information from each battery in String 1."
+ ::= { battManTestResults 5 }
+
+battManString1ResponseTestChangeTableEntry OBJECT-TYPE
+ SYNTAX BattManString1ResponseTestChangeTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString1ResponseTestChangeIndex }
+ ::= { battManString1ResponseTestChangeTable 1 }
+
+BattManString1ResponseTestChangeTableEntry ::=
+ SEQUENCE {
+ battManString1ResponseTestChangeIndex INTEGER,
+ battManString1ResponseTestChangeData INTEGER
+ }
+
+battManString1ResponseTestChangeIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of the entries in the table."
+ ::= { battManString1ResponseTestChangeTableEntry 1 }
+
+battManString1ResponseTestChangeData OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery response test change in percent."
+ ::= { battManString1ResponseTestChangeTableEntry 2 }
+
+battManString2OhmicValueLastDischargeInfo OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Informational text showing the date/time, load, and pilot temperature for the string
+ during the last discharge when ohmic values were recorded."
+ ::= { battManTestResults 6 }
+
+battManString2OhmicValueTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString2OhmicValueTable."
+ ::= { battManTestResults 7 }
+
+battManString2OhmicValueTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString2OhmicValueTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting ohmic value information from each battery in String 1."
+ ::= { battManTestResults 8 }
+
+battManString2OhmicValueTableEntry OBJECT-TYPE
+ SYNTAX BattManString2OhmicValueTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString2OhmicValueIndex }
+ ::= { battManString2OhmicValueTable 1 }
+
+BattManString2OhmicValueTableEntry ::=
+ SEQUENCE {
+ battManString2OhmicValueIndex INTEGER,
+ battManString2OhmicValueData INTEGER
+ }
+
+battManString2OhmicValueIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of battery calibration entries in the table."
+ ::= { battManString2OhmicValueTableEntry 1 }
+
+battManString2OhmicValueData OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery inter-tier ohmic value in ohms.
+ Note: Negative values are invalid and may indicate faulty calibration
+ of ohmic value correction factors."
+ ::= { battManString2OhmicValueTableEntry 2 }
+
+battManString2ResponseTestChangeTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the battManString2ResponseTestChangeTable."
+ ::= { battManTestResults 9 }
+
+battManString2ResponseTestChangeTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF BattManString2ResponseTestChangeTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting response test change information from each battery in String 1."
+ ::= { battManTestResults 10 }
+
+battManString2ResponseTestChangeTableEntry OBJECT-TYPE
+ SYNTAX BattManString2ResponseTestChangeTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The string to get data from."
+ INDEX { battManString2ResponseTestChangeIndex }
+ ::= { battManString2ResponseTestChangeTable 1 }
+
+BattManString2ResponseTestChangeTableEntry ::=
+ SEQUENCE {
+ battManString2ResponseTestChangeIndex INTEGER,
+ battManString2ResponseTestChangeData INTEGER
+ }
+
+battManString2ResponseTestChangeIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of the entries in the table."
+ ::= { battManString2ResponseTestChangeTableEntry 1 }
+
+battManString2ResponseTestChangeData OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery response test change in percent."
+ ::= { battManString2ResponseTestChangeTableEntry 2 }
+
+-- the xPDUIdent group
+
+xPDUIdentProductName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the PDU."
+ ::= { xPDUIdent 1 }
+
+xPDUIdentHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the PDU.
+ This value is set at the factory."
+ ::= { xPDUIdent 2 }
+
+xPDUIdentFirmwareAppRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ID string identifying the application firmware revision of the PDU."
+ ::= { xPDUIdent 3 }
+
+xPDUIdentFirmwareAppOSRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ID string identifying the application operating system firmware revision of the PDU."
+ ::= { xPDUIdent 4 }
+
+xPDUIdentFirmwareControllerRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ID string identifying the PDU controller firmware revision."
+ ::= { xPDUIdent 5 }
+
+xPDUIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the PDU was manufactured in mm/dd/yyyy format.
+ This value is set at the factory."
+ ::= { xPDUIdent 6 }
+
+xPDUIdentModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the model number of
+ the PDU. This value is set at the factory."
+ ::= { xPDUIdent 7 }
+
+xPDUIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the serial number of
+ the PDU. This value is set at the factory."
+ ::= { xPDUIdent 8 }
+
+-- the xPDUDevice group
+
+xPDUDeviceNominalMainInputVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The nominal main input voltage to the PDU.
+ Measured in Volts, line-to-line for a delta service or
+ line-to-neutral for a wye service."
+ ::= { xPDUDevice 1 }
+
+xPDUDeviceServiceType OBJECT-TYPE
+ SYNTAX INTEGER {
+ delta (1),
+ wye (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The type of utility input to the PDU. Either 3 wires (delta), or 4 wires (wye)."
+ ::= { xPDUDevice 2 }
+
+xPDUDeviceNominalOutputVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The nominal line-to-neutral output voltage to the load measured in Volts."
+ ::= { xPDUDevice 3 }
+
+xPDUDeviceMainInputBreakerRating OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The rating of the main input breaker measured in Amps."
+ ::= { xPDUDevice 4 }
+
+xPDUDevicePanelBreakerRating OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The rating of the panel breaker measured in Amps."
+ ::= { xPDUDevice 5 }
+
+xPDUDeviceTransformerPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not a transformer is installed in the PDU."
+ ::= { xPDUDevice 6 }
+
+xPDUDeviceLoadTieBreakerPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not a load tie breaker is installed in the PDU."
+ ::= { xPDUDevice 7 }
+
+xPDUDeviceLoadTestPortPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not a load test port is installed in the PDU."
+ ::= { xPDUDevice 8 }
+
+xPDUDeviceFusesPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not the UPS feed from the PDU includes fuses."
+ ::= { xPDUDevice 9 }
+
+xPDUDeviceFansPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not cooling fans are installed in the PDU."
+ ::= { xPDUDevice 10 }
+
+xPDUDeviceBypassInputPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not the PDU is equipped with a second feed for
+ the UPS's bypass input."
+ ::= { xPDUDevice 11 }
+
+xPDUDeviceCrossTieOutputPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not the PDU is equipped with a cross-tie output."
+ ::= { xPDUDevice 12 }
+
+xPDUDeviceEarthGroundMonitorPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not the PDU can provide ground current measurements."
+ ::= { xPDUDevice 13 }
+
+xPDUDeviceInfraXureType OBJECT-TYPE
+ SYNTAX INTEGER {
+ typeB (1),
+ typeC (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the configuration of this PDU system.
+ Type-B PDU is in a distributed UPS system and has bypass capabilities.
+ Type-C PDU receives power from a larger central UPS."
+ ::= { xPDUDevice 14 }
+
+-- Main Input
+
+xPDUMainInputOverVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..30)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which an input over voltage condition will be generated.
+ Specified as percent deviation from nominal."
+ ::= { xPDUMainInput 1 }
+
+xPDUMainInputUnderVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..30)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which an input under voltage condition will be generated.
+ Specified as percent deviation from nominal."
+ ::= { xPDUMainInput 2 }
+
+-- Main Input Voltage Table
+
+xPDUMainInputVoltageTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of Main input voltage entries."
+ ::= { xPDUMainInput 3 }
+
+xPDUMainInputVoltageTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUMainInputVoltagePhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of input voltage table entries. The number of
+ entries are the phase entries.
+ The number of entries is contained in the
+ xPDUMainInputVoltageTableSize OID."
+ ::= { xPDUMainInput 4 }
+
+ xPDUMainInputVoltagePhaseEntry OBJECT-TYPE
+ SYNTAX XPDUMainInputVoltagePhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular main input voltage phase."
+ INDEX { xPDUMainInputVoltagePhaseIndex }
+ ::= { xPDUMainInputVoltageTable 1 }
+
+ XPDUMainInputVoltagePhaseEntry ::= SEQUENCE {
+ xPDUMainInputVoltagePhaseIndex INTEGER,
+ xPDUMainInputVoltageLtoL INTEGER,
+ xPDUMainInputVoltageLtoN INTEGER
+ }
+
+ xPDUMainInputVoltagePhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each input phase entry in the table."
+ ::= { xPDUMainInputVoltagePhaseEntry 1 }
+
+ xPDUMainInputVoltageLtoL OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-line PDU input voltage when an isolation transformer is present,
+ or -1 if no transformer present in this PDU. Measured in tenths of Volts."
+ ::= { xPDUMainInputVoltagePhaseEntry 2 }
+
+ xPDUMainInputVoltageLtoN OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-neutral PDU input voltage when an isolation transformer is not present,
+ or -1 if a transformer is present in this PDU. Measured in tenths of Volts."
+ ::= { xPDUMainInputVoltagePhaseEntry 3 }
+
+
+xPDUBypassInputOverVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..30)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which a bypass input over voltage condition will be generated.
+ Specified as percent deviation from nominal."
+ ::= { xPDUBypassInput 1 }
+
+xPDUBypassInputUnderVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..30)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which an bypass input under voltage condition will be generated.
+ Specified as percent deviation from nominal."
+ ::= { xPDUBypassInput 2 }
+
+-- Bypass Input Voltage Table
+
+xPDUBypassInputVoltageTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of bypass input voltage entries."
+ ::= { xPDUBypassInput 3 }
+
+xPDUBypassInputVoltageTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUBypassInputVoltagePhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output table entries. The number of
+ entries are the phase entries.
+ The number of entries is contained in the
+ xPDUBypassInputVoltageTableSize OID."
+ ::= { xPDUBypassInput 4 }
+
+ xPDUBypassInputVoltagePhaseEntry OBJECT-TYPE
+ SYNTAX XPDUBypassInputVoltagePhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular bypass input voltage phase."
+ INDEX { xPDUBypassInputVoltagePhaseIndex }
+ ::= { xPDUBypassInputVoltageTable 1 }
+
+ XPDUBypassInputVoltagePhaseEntry ::= SEQUENCE {
+ xPDUBypassInputVoltagePhaseIndex INTEGER,
+ xPDUBypassInputVoltageLtoL INTEGER,
+ xPDUBypassInputVoltageLtoN INTEGER
+ }
+
+ xPDUBypassInputVoltagePhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of each bypass input phase entry in the table."
+ ::= { xPDUBypassInputVoltagePhaseEntry 1 }
+
+ xPDUBypassInputVoltageLtoL OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-line bypass input voltage, or -1 if no bypass
+ feed is present in this PDU. Measured in tenths of Volts"
+ ::= { xPDUBypassInputVoltagePhaseEntry 2 }
+
+ xPDUBypassInputVoltageLtoN OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-neutral bypass input voltage, or -1 if no bypass
+ feed is present in this PDU. Measured in tenths of Volts"
+ ::= { xPDUBypassInputVoltagePhaseEntry 3 }
+
+-- UPS Input Table
+
+xPDUUPSInputVoltageTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of UPS input voltage entries."
+ ::= { xPDUUPSInput 1 }
+
+xPDUUPSInputVoltageTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUUPSInputVoltagePhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of UPS input table entries. The number of
+ entries are the phase entries.
+ The number of entries is contained in the
+ xPDUUPSInputVoltageTableSize OID."
+ ::= { xPDUUPSInput 2 }
+
+ xPDUUPSInputVoltagePhaseEntry OBJECT-TYPE
+ SYNTAX XPDUUPSInputVoltagePhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular UPS input voltage phase."
+ INDEX { xPDUUPSInputVoltagePhaseIndex }
+ ::= { xPDUUPSInputVoltageTable 1 }
+
+ XPDUUPSInputVoltagePhaseEntry ::= SEQUENCE {
+ xPDUUPSInputVoltagePhaseIndex INTEGER,
+ xPDUUPSInputVoltageLtoNPresent INTEGER
+ }
+
+ xPDUUPSInputVoltagePhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each UPS input phase entry in the table."
+ ::= { xPDUUPSInputVoltagePhaseEntry 1 }
+
+ xPDUUPSInputVoltageLtoNPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ notPresent (1),
+ present (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not voltage is present at the UPS feed."
+ ::= { xPDUUPSInputVoltagePhaseEntry 2 }
+
+-- System Output
+
+xPDUSystemOutputFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system output frequency in tenths of Hertz."
+ ::= { xPDUSystemOutput 1 }
+
+xPDUSystemOutputNeutralCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the neutral current measured at the system output in tenths of Amps."
+ ::= { xPDUSystemOutput 2 }
+
+xPDUSystemOutputTotalPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the total system output power in tenths of kW."
+ ::= { xPDUSystemOutput 3 }
+
+xPDUSystemOutputTotalApparentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the total system output power in tenths of kVA."
+ ::= { xPDUSystemOutput 4 }
+
+xPDUSystemOutputTotalPowerFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the total power factor of the system output.
+ A value of 100 representing a unity power factor (1.00).
+ Measured in hundredths."
+ ::= { xPDUSystemOutput 5 }
+
+xPDUSystemOutputFrequencyTolerance OBJECT-TYPE
+ SYNTAX INTEGER{
+ freqToleranceOff (1),
+ freqTolerancePointTwo (2),
+ freqTolerancePointFive (3),
+ freqToleranceOne (4),
+ freqToleranceOnePointFive (5),
+ freqToleranceTwo (6),
+ freqToleranceThree (7),
+ freqToleranceFour (8),
+ freqToleranceFive (9),
+ freqToleranceNine (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the circuit panel output frequency tolerance in Hertz."
+ ::= { xPDUSystemOutput 6 }
+
+xPDUSystemOutputMaxKWPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Defines 100% load in kW.
+ Purpose is to set to match UPS capabilities."
+ ::= { xPDUSystemOutput 7 }
+
+xPDUSystemOutputOverVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..30)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which an output over voltage condition will be generated.
+ Specified as percent deviation from nominal."
+ ::= { xPDUSystemOutput 8 }
+
+xPDUSystemOutputUnderVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..30)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which an output under voltage condition will be generated.
+ Specified as percent deviation from nominal."
+ ::= { xPDUSystemOutput 9 }
+
+
+xPDUSystemOutputOverCurrentThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which an over current condition will be generated.
+ Specified as a percent of the panel breaker rating."
+ ::= { xPDUSystemOutput 10 }
+
+xPDUSystemOutputOverCurrentNeutralThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which an Over current neutral condition will be generated.
+ Specified as a percent of the panel breaker rating."
+ ::= { xPDUSystemOutput 11 }
+
+xPDUSystemOutputUnderCurrentThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which an under current condition will be generated.
+ Specified as a percent of the panel breaker rating."
+ ::= { xPDUSystemOutput 12 }
+
+xPDUSystemOutputTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of System Output phase entries."
+ ::= { xPDUSystemOutput 13 }
+
+xPDUSystemOutputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUSystemOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of system output table entries.
+ The number of entries is contained in the
+ xPDUSystemOutputTableSize OID."
+ ::= { xPDUSystemOutput 14 }
+
+ xPDUSystemOutputPhaseEntry OBJECT-TYPE
+ SYNTAX XPDUSystemOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular system output phase."
+ INDEX { xPDUSystemOutputPhaseIndex }
+ ::= { xPDUSystemOutputTable 1 }
+
+ XPDUSystemOutputPhaseEntry ::= SEQUENCE {
+ xPDUSystemOutputPhaseIndex INTEGER,
+ xPDUSystemOutputVoltageLtoL INTEGER,
+ xPDUSystemOutputVoltageLtoN INTEGER,
+ xPDUSystemOutputPhaseCurrent INTEGER,
+ xPDUSystemOutputPower INTEGER,
+ xPDUSystemOutputApparentPower INTEGER,
+ xPDUSystemOutputPowerFactor INTEGER
+ }
+
+ xPDUSystemOutputPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each output phase entry in the table."
+ ::= { xPDUSystemOutputPhaseEntry 1 }
+
+ xPDUSystemOutputVoltageLtoL OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-line system output voltage available at the cicuit panel.
+ Measured in tenths of Volts."
+ ::= { xPDUSystemOutputPhaseEntry 2 }
+
+ xPDUSystemOutputVoltageLtoN OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-neutral system output voltage available at the cicuit panel.
+ Measured in tenths of Volts."
+ ::= { xPDUSystemOutputPhaseEntry 3 }
+
+
+ xPDUSystemOutputPhaseCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System load current per phase. Measured in tenths of Amps."
+ ::= { xPDUSystemOutputPhaseEntry 4 }
+
+ xPDUSystemOutputPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System output power per phase. Measured in tenths of kW."
+ ::= { xPDUSystemOutputPhaseEntry 5 }
+
+ xPDUSystemOutputApparentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System output power per phase. Measured in tenths of kVA."
+ ::= { xPDUSystemOutputPhaseEntry 6 }
+
+ xPDUSystemOutputPowerFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the Power Factor of the system output per phase.
+ A value of 100 representing a unity Power Factor (1.00).
+ Measured in hundredths."
+ ::= { xPDUSystemOutputPhaseEntry 7 }
+
+xPDUGroundCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the current measured in the earth ground conductor in tenths of Amps."
+ ::= { xPDUGroundMonitorPoint 1 }
+
+xPDUGroundCurrentThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..50)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which a ground current over current
+ condition will be generated. Measured in tenths of Amps."
+ ::= { xPDUGroundMonitorPoint 2 }
+
+-- System Breakers
+
+xPDUSystemBreakerTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of system breaker entries."
+ ::= { xPDUSystemBreakers 1 }
+
+xPDUSystemBreakerTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUSystemBreakerTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of system breaker entries.
+ The number of entries is contained in the
+ xPDUSystemBreakerTableSize OID."
+ ::= { xPDUSystemBreakers 2 }
+
+ xPDUSystemBreakerTableEntry OBJECT-TYPE
+ SYNTAX XPDUSystemBreakerTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular system breaker."
+ INDEX { xPDUSystemBreakerTableIndex }
+ ::= { xPDUSystemBreakerTable 1 }
+
+ XPDUSystemBreakerTableEntry ::= SEQUENCE {
+ xPDUSystemBreakerTableIndex INTEGER,
+ xPDUSystemBreakerDescription DisplayString,
+ xPDUSystemBreakerPosition INTEGER
+ }
+
+ xPDUSystemBreakerTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of system breaker entries in the table."
+ ::= { xPDUSystemBreakerTableEntry 1 }
+
+xPDUSystemBreakerDescription OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..79))
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A brief description of the system breakers."
+ ::= { xPDUSystemBreakerTableEntry 2 }
+
+ xPDUSystemBreakerPosition OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether this breaker is open(1) or closed(2)."
+ ::= { xPDUSystemBreakerTableEntry 3 }
+
+-- Branch Breakers (Breaker Panel)
+
+xPDUNumOfBranchBreakers OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of branch breakers in the Panel."
+ ::= { xPDUBranchBreakers 1 }
+
+-- Branch Breakers Table
+
+xPDUBranchBreakerTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of branch breaker entries."
+ ::= { xPDUBranchBreakers 2 }
+
+xPDUBranchBreakerTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUBranchBreakerEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of branch breaker table entries. The
+ number of entries is given by the value of xPDUBranchBreakerTableSize
+ The number of entries is contained in the
+ xPDUBranchBreakerTableSize OID."
+ ::= { xPDUBranchBreakers 3 }
+
+ xPDUBranchBreakerEntry OBJECT-TYPE
+ SYNTAX XPDUBranchBreakerEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular branch breaker."
+ INDEX { xPDUBranchBreakerTableIndex }
+ ::= { xPDUBranchBreakerTable 1 }
+
+ XPDUBranchBreakerEntry ::= SEQUENCE {
+ xPDUBranchBreakerTableIndex INTEGER,
+ xPDUBranchBreakerRating INTEGER,
+ xPDUBranchBreakerRDPFeed INTEGER,
+ xPDUBranchBreakerTieIndicator INTEGER,
+ xPDUBranchBreakerCurrent INTEGER,
+ xPDUBranchBreakerOverCurrentThreshold INTEGER,
+ xPDUBranchBreakerUnderCurrentThreshold INTEGER
+ }
+
+ xPDUBranchBreakerTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of branch breaker entries in the table."
+ ::= { xPDUBranchBreakerEntry 1 }
+
+ xPDUBranchBreakerRating OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates current rating of this breaker.
+ 0=Breaker is not present.
+ 1=Earth leakage connection.
+ 2=Neutral connection.
+ A value greater than 2 indicates breaker current rating in Amps."
+ ::= { xPDUBranchBreakerEntry 2 }
+
+ xPDUBranchBreakerRDPFeed OBJECT-TYPE
+ SYNTAX INTEGER {
+ remoteDistribution (1),
+ noRemoteDistribution (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates that a breaker position is feeding a remote
+ distribution panel."
+ ::= { xPDUBranchBreakerEntry 3 }
+
+ xPDUBranchBreakerTieIndicator OBJECT-TYPE
+ SYNTAX INTEGER {
+ breakerTied (1),
+ breakerUntied (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether or not the breaker pole is physically
+ connected to the breaker immediately below."
+ ::= { xPDUBranchBreakerEntry 4 }
+
+ xPDUBranchBreakerCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the branch current in tenths of Amps or -1 when not available."
+ ::= { xPDUBranchBreakerEntry 5 }
+
+ xPDUBranchBreakerOverCurrentThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which a branch circuit over current
+ condition will be generated.
+ Specified as a percent of the branch breaker rating."
+ ::= { xPDUBranchBreakerEntry 6 }
+
+ xPDUBranchBreakerUnderCurrentThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which a branch circuit under current
+ condition will be generated.
+ Specified as a percent of the branch breaker rating."
+ ::= { xPDUBranchBreakerEntry 7 }
+
+-- the xPDUInputContacts group
+
+xPDUInputContactNumContacts OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of contacts supported by the PDU."
+ ::= { xPDUInputContacts 1 }
+
+xPDUInputContactTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input contact entries."
+ ::= { xPDUInputContacts 2 }
+
+xPDUInputContactTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUInputContactEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of contacts supported by the PDU.
+ The number of entries is contained in the
+ xPDUInputContactTableSize OID."
+ ::= { xPDUInputContacts 3 }
+
+xPDUInputContactEntry OBJECT-TYPE
+ SYNTAX XPDUInputContactEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A contact entry containing information for a given contact."
+ INDEX { xPDUInputContactNumber }
+ ::= { xPDUInputContactTable 1 }
+
+XPDUInputContactEntry ::=
+ SEQUENCE {
+ xPDUInputContactNumber INTEGER,
+ xPDUInputContactName DisplayString,
+ xPDUInputContactNormalState INTEGER,
+ xPDUInputContactCurrentState INTEGER
+ }
+
+xPDUInputContactNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An index identifying the contact on the PDU."
+ ::= { xPDUInputContactEntry 1 }
+
+xPDUInputContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The description of the purpose/use of the contact."
+ ::= { xPDUInputContactEntry 2 }
+
+xPDUInputContactNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The normal operating position of the contact."
+ ::= { xPDUInputContactEntry 3 }
+
+xPDUInputContactCurrentState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This value indicates the current state of the contact."
+ ::= { xPDUInputContactEntry 4 }
+
+-- the xPDUOutputRelays group
+
+xPDUOutputRelaysNumRelays OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output relays supported by the PDU."
+ ::= { xPDUOutputRelays 1 }
+
+xPDUOutputRelaysTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output relay entries."
+ ::= { xPDUOutputRelays 2 }
+
+xPDUOutputRelayTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XPDUOutputRelayEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output relays supported by the PDU.
+ The number of entries is contained in the
+ xPDUOutputRelayTableSize OID."
+ ::= { xPDUOutputRelays 3 }
+
+xPDUOutputRelayEntry OBJECT-TYPE
+ SYNTAX XPDUOutputRelayEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A output relay entry containing information for a given contact."
+ INDEX { xPDUOutputRelayNumber }
+ ::= { xPDUOutputRelayTable 1 }
+
+XPDUOutputRelayEntry ::=
+ SEQUENCE {
+ xPDUOutputRelayNumber INTEGER,
+ xPDUOutputRelayName DisplayString,
+ xPDUOutputRelayNormalState INTEGER,
+ xPDUOutputRelayCurrentState INTEGER
+ }
+
+xPDUOutputRelayNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An index identifying the output relay on the PDU."
+ ::= { xPDUOutputRelayEntry 1 }
+
+xPDUOutputRelayName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The description of the purpose/use of the output relay."
+ ::= { xPDUOutputRelayEntry 2 }
+
+xPDUOutputRelayNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The normal operating position of the output relay."
+ ::= { xPDUOutputRelayEntry 3 }
+
+xPDUOutputRelayCurrentState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This value indicates the current state of the output relay."
+ ::= { xPDUOutputRelayEntry 4 }
+
+-- the xPDUMiscGroup
+
+xPDUEPOMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ armed (1),
+ disarmed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether the EPO System is armed(1) or disarmed(2)."
+ ::= { xPDUMiscGroup 1 }
+
+xPDUTransformTempStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ overtemp (2),
+ noTransformerPresent (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates if the PDU's isolation transformer is over temperature."
+ ::= { xPDUMiscGroup 2 }
+
+xPDUCoolingFanStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ normal (1),
+ failed (2),
+ noCoolingFansPresent (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates if one or more of the PDU's cooling fans have failed."
+ ::= { xPDUMiscGroup 3 }
+
+-- The xATSIdent group
+
+xATSIdentProductName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the transfer switch unit."
+ ::= { xATSIdent 1 }
+
+xATSIdentHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the transfer switch.
+ This value is set at the factory."
+ ::= { xATSIdent 2 }
+
+xATSIdentFirmwareAppRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ID string identifying the application firmware revision of the transfer switch."
+ ::= { xATSIdent 3 }
+
+xATSIdentFirmwareAppOSRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ID string identifying the application operating system firmware revision of the transfer switch."
+ ::= { xATSIdent 4 }
+
+xATSIdentFirmwareControllerRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ID string identifying the transfer switch controller firmware revision."
+ ::= { xATSIdent 5 }
+
+xATSIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the transfer switch was manufactured in mm/dd/yyyy format.
+ This value is set at the factory."
+ ::= { xATSIdent 6 }
+
+xATSIdentModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the model number of the transfer switch.
+ This value is set at the factory."
+ ::= { xATSIdent 7 }
+
+xATSIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the serial number of the transfer switch.
+ This value is set at the factory."
+ ::= { xATSIdent 8 }
+
+-- The xATSDevice group
+
+xATSDeviceServiceType OBJECT-TYPE
+ SYNTAX INTEGER {
+ threeWire (1),
+ fourWire (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The type of utility input to the transfer switch.
+ Either 3 wires (delta), or 4 wires (wye)."
+ ::= { xATSDevice 1 }
+
+xATSDeviceNominalVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The nominal line-to-neutral system voltage.
+ Measured in Volts, line-to-line for a 3-wire service or
+ line-to-neutral for a 4-wire service. -1 if not available."
+ ::= { xATSDevice 2 }
+
+xATSDeviceNominalFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The nominal system frequency. Measured in tenths of Hertz.
+ -1 if not available."
+ ::= { xATSDevice 3 }
+
+xATSDeviceTransferSwitchRating OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The rating of the transfer switch.
+ Measured in Amps."
+ ::= { xATSDevice 4 }
+
+xATSDeviceDCBackUpPresent OBJECT-TYPE
+ SYNTAX INTEGER{
+ yes (1),
+ no (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates if a DC backup is present or not."
+ ::= { xATSDevice 5 }
+
+-- The xATS Switch Status group
+
+xATSSwitchStatusSelectedSource OBJECT-TYPE
+ SYNTAX INTEGER{
+ none (1),
+ source1 (2),
+ source2 (3),
+ fault (4),
+ unknown (5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The source which is currently selected, i.e. supplying power to the load."
+ ::= { xATSSwitchStatus 1 }
+
+xATSSwitchStatusOperationalMode OBJECT-TYPE
+ SYNTAX INTEGER{
+ automatic (1),
+ notInAutoAbnormal (2),
+ notInAuto (3),
+ unknown (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current operating mode of the transfer switch. When the ATS is in
+ automatic mode, generator starting and ATS transferring is all done automatically
+ as needed based on the state of source 1. Automatic operation is halted when the
+ ATS is in either of the notInAuto modes.
+ A mode of notInAuto indicates that the automatic operation switch is in the
+ disabled position, as indicated by the xATSSwitchStatusAutomaticOperationSwitch OID.
+ The notInAutoAbnormal condition indicates that an abnormal
+ condition has caused the transfer switch to halt automatic operation.
+ In this case, traps can indicate the exact problem. In the case of
+ notInAutoAbnormal, refer to the operation manual for details
+ on how debug the condition and restore automatic operation."
+ ::= { xATSSwitchStatus 2 }
+
+xATSSwitchStatusAutomaticOperationSwitch OBJECT-TYPE
+ SYNTAX INTEGER{
+ disabled (1),
+ enabled (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The position of the automatic operation switch on the front of the transfer switch."
+ ::= { xATSSwitchStatus 3 }
+
+xATSSwitchStatusEngineStartSignal OBJECT-TYPE
+ SYNTAX INTEGER{
+ run (1),
+ stop (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The position of the Start/Stop contact which signals the generator
+ engine to start/run. When the ATS is in automatic mode,
+ generator starting/stopping is under ATS control."
+ ::= { xATSSwitchStatus 4 }
+
+-- The xATS Switch Setting group
+
+xATSSwitchSettingsLowVoltageTransferPoint OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The lowest acceptable voltage condition at source 1.
+ When any phase of source 1 is lower than this voltage,
+ source quality is considered bad and the generator run signal
+ is asserted to begin generator operation.
+ Specified in volts, line-to-line for a 3-wire service or
+ line-to-neutral for a 4-wire service.
+ -1 if not available."
+ ::= { xATSSwitchSettings 1 }
+
+xATSSwitchSettingsHighVoltageTransferPoint OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The highest acceptable voltage condition at source 1.
+ When any phase of source 1 is greater than this voltage,
+ source quality is considered bad and the generator run signal
+ is asserted to begin generator operation.
+ Specified in volts, line-to-line for a 3-wire service or
+ line-to-neutral for a 4-wire service.
+ -1 if not available."
+ ::= { xATSSwitchSettings 2 }
+
+xATSSwitchSettingsMaxFrequencyDeviation OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum acceptable frequency deviation condition from nominal at source 1.
+ When source 1 frequency is outside the specified range,
+ source quality is considered bad and the generator run signal
+ is asserted to begin generator operation.
+ Specified in tenths of Hertz above or below nominal.
+ A value of zero indicates that frequency is ignored when
+ determining source quality.
+ -1 if not available."
+ ::= { xATSSwitchSettings 3 }
+
+xATSSwitchSettingsMinPhaseBalance OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum required phase balance at source 1.
+ When the percentage difference between the minimum and maximum
+ phase voltage measurements at source 1 is greater than this value,
+ source quality is considered bad and the generator run signal
+ is asserted to begin generator operation.
+ Specified as a percentage. A value of zero indicates that phase balance
+ is ignored when determining source quality.
+ -1 if not available."
+ ::= { xATSSwitchSettings 4 }
+
+xATSSwitchSettingsNominalRotation OBJECT-TYPE
+ SYNTAX INTEGER{
+ abc (1),
+ cba (2),
+ any (3),
+ unknown (4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The nominal phase rotation (or phase sequence) required by the load.
+ For certain types of equipment, such as rotating machinery, phase rotation
+ is critical for proper operation as it determines the direction which motors
+ will rotate (clockwise or counterclockwise).
+ Source quality will be seen as bad if the rotation measured at that
+ ATS input does not match this setting.
+ If this setting is set to any, phase rotation is ignored."
+ ::= { xATSSwitchSettings 5 }
+
+xATSSwitchSettingsAllowClosedTransfer OBJECT-TYPE
+ SYNTAX INTEGER{
+ yes (1),
+ no (2),
+ unknown (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This setting enables seemless (closed) transfers between sources.
+ When possible, both source 1 and source 2 are closed to the output
+ for a brief time. If closed transfer is not possible within the amount
+ of time specified by the xATSSwitchSettingsMaxSyncTime OID,
+ an open transfer will be executed."
+ ::= { xATSSwitchSettings 6 }
+
+xATSSwitchSettingsMaxSyncTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "When attempting/seeking to perform a closed transfer, this setting defines
+ the maximum time allowed before the transfer switch will give up and perform
+ an open transfer. Specified in seconds.
+ -1 if not available."
+ ::= { xATSSwitchSettings 7 }
+
+xATSSwitchSettingsNeutralTransferTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This setting defines how long both source 1 and source 2 will be
+ disconnected from the output, during an open transfer.
+ Specified in seconds.
+ -1 if not available."
+ ::= { xATSSwitchSettings 8 }
+
+xATSSwitchSettingsClearLatchedAlarms OBJECT-TYPE
+ SYNTAX INTEGER{
+ yes (1),
+ no (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Clears any latched alarm conditions."
+ ::= { xATSSwitchSettings 9 }
+
+xATSSwitchSettingsSetToFactoryDefaults OBJECT-TYPE
+ SYNTAX INTEGER{
+ yes (1),
+ no (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Sets all transfer switch settings to factory default values."
+ ::= { xATSSwitchSettings 10 }
+
+
+-- The xATSSwitchTimers group
+
+ xATSSwitchTimersTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of transfer switch timer entries."
+ ::= { xATSSwitchTimers 1 }
+
+ xATSSwitchTimersTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSSwitchTimersEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of timers supported by ATS.
+ The number of entries is contained in the xATSSwitchTimersTableSize OID."
+ ::= { xATSSwitchTimers 2 }
+
+ xATSSwitchTimersEntry OBJECT-TYPE
+ SYNTAX XATSSwitchTimersEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information about an individual ATS timer."
+ INDEX { xATSSwitchTimersIndex }
+ ::= { xATSSwitchTimersTable 1 }
+
+ XATSSwitchTimersEntry ::=
+ SEQUENCE {
+ xATSSwitchTimersIndex INTEGER,
+ xATSSwitchTimersName DisplayString,
+ xATSSwitchTimersAbort INTEGER,
+ xATSSwitchTimersStatus INTEGER,
+ xATSSwitchTimersRemainingTime INTEGER,
+ xATSSwitchTimersDelaySetting INTEGER
+ }
+
+xATSSwitchTimersIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of timer entries in the table."
+ ::= { xATSSwitchTimersEntry 1 }
+
+xATSSwitchTimersName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Name of the individual timer.Refer to ATS operation manual,
+ or on-line help, for detailed descriptions of ATS timers."
+ ::= { xATSSwitchTimersEntry 2 }
+
+xATSSwitchTimersAbort OBJECT-TYPE
+ SYNTAX INTEGER{
+ yes (1),
+ no (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This aborts the individual timer."
+ ::= { xATSSwitchTimersEntry 3 }
+
+xATSSwitchTimersStatus OBJECT-TYPE
+ SYNTAX INTEGER{
+ inactive (1),
+ active (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the individual timer. Designates whether this timer
+ entry is currently running or inactive."
+ ::= { xATSSwitchTimersEntry 4 }
+
+xATSSwitchTimersRemainingTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The time remaining for this timer entry.
+ Specified in seconds."
+ ::= { xATSSwitchTimersEntry 5 }
+
+xATSSwitchTimersDelaySetting OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The delay settings associated with this timer entry.
+ When this timer entry is active, the timer value must exceed this setting
+ before the ATS behavior associated with this timer is executed.
+ Refer to ATS operation manual, or on-line help, for detailed
+ descriptions of ATS timers."
+ ::= { xATSSwitchTimersEntry 6 }
+
+-- The xATSSwitchBlockMap group
+
+ xATSSwitchBlockMapTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of blocking map entries, or how many ATS actions can be blocked."
+ ::= { xATSSwitchBlockMap 1 }
+
+ xATSSwitchBlockMapTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSSwitchBlockMapEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of blocking maps supported by the ATS.
+ The number of entries is contained in the xATSSwitchBlockMapTableSize OID."
+ ::= { xATSSwitchBlockMap 2 }
+
+ xATSSwitchBlockMapEntry OBJECT-TYPE
+ SYNTAX XATSSwitchBlockMapEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information about a specific ATS blocking map."
+ INDEX { xATSSwitchBlockMapIndex }
+ ::= { xATSSwitchBlockMapTable 1 }
+
+ XATSSwitchBlockMapEntry ::=
+ SEQUENCE {
+ xATSSwitchBlockMapIndex INTEGER,
+ xATSSwitchBlockMapName DisplayString,
+ xATSSwitchBlockMapStatus INTEGER,
+ xATSSwitchBlockMapSetting INTEGER
+ }
+
+ xATSSwitchBlockMapIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of blocking map entries in the table."
+ ::= { xATSSwitchBlockMapEntry 1 }
+
+ xATSSwitchBlockMapName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A string describing the ATS action to be blocked."
+ ::= { xATSSwitchBlockMapEntry 2 }
+
+ xATSSwitchBlockMapStatus OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Represents the status of this blocking map entry, in bit-mapped format.
+ A non-zero value indicates that this entry's ATS action is currently being blocked.
+ The bit(s) set indicate which input(s) are causing the blocking (bit0, bit1, etc).
+
+ bit 0 - Contact 1
+ bit 1 - Contact 2
+ bit 2 - Contact 3
+ bit 3 - Contact 4."
+ ::= { xATSSwitchBlockMapEntry 3 }
+
+ xATSSwitchBlockMapSetting OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This setting designates the inputs that block the ATS action
+ The mapping is specified as a bit-field, where each bit set indicates
+ the input that blocks the ATS action associated with the entry.
+
+ bit 0 - Contact 1
+ bit 1 - Contact 2
+ bit 2 - Contact 3
+ bit 3 - Contact 4."
+ ::= { xATSSwitchBlockMapEntry 4 }
+
+-- The xATSSwitchStatistics group
+
+ xATSSwitchStatisticsTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of transfer switch statistics entries."
+ ::= { xATSSwitchStatistics 1 }
+
+ xATSSwitchStatisticsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSSwitchStatisticsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of statistics supported by ATS.
+ The number of entries is contained in the xATSSwitchStatisticsTableSize OID."
+ ::= { xATSSwitchStatistics 2 }
+
+ xATSSwitchStatisticsEntry OBJECT-TYPE
+ SYNTAX XATSSwitchStatisticsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information about an individual ATS statistic."
+ INDEX { xATSSwitchStatisticsIndex }
+ ::= { xATSSwitchStatisticsTable 1 }
+
+ XATSSwitchStatisticsEntry ::=
+ SEQUENCE {
+ xATSSwitchStatisticsIndex INTEGER,
+ xATSSwitchStatisticsName DisplayString,
+ xATSSwitchStatisticsValue DisplayString,
+ xATSSwitchStatisticsReset INTEGER
+ }
+
+ xATSSwitchStatisticsIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Index of ATS statistics entries in the table."
+ ::= { xATSSwitchStatisticsEntry 1 }
+
+ xATSSwitchStatisticsName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This is the name of the ATS statistic associated with this entry."
+ ::= { xATSSwitchStatisticsEntry 2 }
+
+ xATSSwitchStatisticsValue OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This is the value of the ATS statistic associated with this entry."
+ ::= { xATSSwitchStatisticsEntry 3 }
+
+ xATSSwitchStatisticsReset OBJECT-TYPE
+ SYNTAX INTEGER{
+ yes (1),
+ no (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This will reset the individual ATS statistic associated with this entry."
+ ::= { xATSSwitchStatisticsEntry 4 }
+
+-- The xATS Source 1 group
+
+xATSSource1Name OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "String used to identify source 1."
+ ::= { xATSSource1 1 }
+
+xATSSource1Position OBJECT-TYPE
+ SYNTAX INTEGER{
+ open (1),
+ closed (2),
+ tripped (3),
+ unknown (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current position of the switch at source 1."
+ ::= { xATSSource1 2 }
+
+xATSSource1Frequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frequency at source 1 in tenths of Hertz.
+ -1 if unavailable."
+ ::= { xATSSource1 3 }
+
+xATSSource1Quality OBJECT-TYPE
+ SYNTAX INTEGER{
+ sourceGood (1),
+ lowVoltage (2),
+ highVoltage (3),
+ phaseImbalance (4),
+ freqOutOfRange (5),
+ badRotation (6),
+ unknown (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current line quality of source 1."
+ ::= { xATSSource1 4 }
+
+xATSSource1Rotation OBJECT-TYPE
+ SYNTAX INTEGER{
+ abc (1),
+ cba (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The phase rotation measured at the source 1 input of the ATS.
+ The sequence is a reference to the order in which the three phases
+ pass the zero-crossing boundary in time."
+ ::= { xATSSource1 5 }
+
+xATSSource1TableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input voltage entries at the source 1 input of the ATS."
+ ::= { xATSSource1 6 }
+
+ xATSSource1Table OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSSource1PhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of voltage table entries for source 1. The number of
+ entries are the phase entries. The number of entries is contained in the
+ xATSSource1TableSize OID."
+ ::= { xATSSource1 7 }
+
+ xATSSource1PhaseEntry OBJECT-TYPE
+ SYNTAX XATSSource1PhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular input voltage phase at the source 1 input of the ATS."
+ INDEX { xATSSource1Index }
+ ::= { xATSSource1Table 1 }
+
+ XATSSource1PhaseEntry ::= SEQUENCE {
+ xATSSource1Index INTEGER,
+ xATSSource1VoltageLtoL INTEGER,
+ xATSSource1VoltageLtoN INTEGER
+ }
+
+ xATSSource1Index OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each phase utilized at source 1."
+ ::= { xATSSource1PhaseEntry 1 }
+
+ xATSSource1VoltageLtoL OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Source 1 line-to-line input voltage.
+ Measured in tenths of Volts."
+ ::= { xATSSource1PhaseEntry 2 }
+
+ xATSSource1VoltageLtoN OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Source 1 line-to-neutral input voltage.
+ Measured in tenths of Volts. -1 for a 3-wire service type."
+ ::= { xATSSource1PhaseEntry 3 }
+
+-- The xATS Source 2 group
+
+xATSSource2Name OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "String used to identify source 2."
+ ::= { xATSSource2 1 }
+
+xATSSource2Position OBJECT-TYPE
+ SYNTAX INTEGER{
+ open (1),
+ closed (2),
+ tripped (3),
+ unknown (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current position of the switch at source 2."
+ ::= { xATSSource2 2 }
+
+xATSSource2Frequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frequency at source 2 in tenths of Hertz.
+ -1 if not available."
+ ::= { xATSSource2 3 }
+
+xATSSource2Quality OBJECT-TYPE
+ SYNTAX INTEGER{
+ sourceGood (1),
+ lowVoltage (2),
+ highVoltage (3),
+ phaseImbalance (4),
+ freqOutOfRange (5),
+ badRotation (6),
+ unknown (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current line quality of source 2."
+ ::= { xATSSource2 4 }
+
+xATSSource2Rotation OBJECT-TYPE
+ SYNTAX INTEGER{
+ abc (1),
+ cba (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The phase rotation measured at the source 2 input of the ATS.
+ -1 if not available."
+ ::= { xATSSource2 5 }
+
+xATSSource2TableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input voltage entries at the source 2 input of the ATS."
+ ::= { xATSSource2 6 }
+
+ xATSSource2Table OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSSource2PhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of voltage table entries for the source 2. The number of
+ entries are the phase entries. The number of entries is contained in the
+ xATSSource2TableSize OID."
+ ::= { xATSSource2 7 }
+
+ xATSSource2PhaseEntry OBJECT-TYPE
+ SYNTAX XATSSource2PhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular input voltage phase at the source 2 input of the ATS."
+ INDEX { xATSSource2Index }
+ ::= { xATSSource2Table 1 }
+
+ XATSSource2PhaseEntry ::= SEQUENCE {
+ xATSSource2Index INTEGER,
+ xATSSource2VoltageLtoL INTEGER,
+ xATSSource2VoltageLtoN INTEGER
+ }
+
+ xATSSource2Index OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each phase utilized at the source 2."
+ ::= { xATSSource2PhaseEntry 1 }
+
+ xATSSource2VoltageLtoL OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Source 2 line-to-line input voltage.
+ Measured in tenths of Volts."
+ ::= { xATSSource2PhaseEntry 2 }
+
+ xATSSource2VoltageLtoN OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Source 2 line-to-neutral input voltage.
+ Measured in tenths of Volts. -1 for a 3-wire service type."
+ ::= { xATSSource2PhaseEntry 3 }
+
+-- The xATSSystemOutput
+
+xATSSystemOutputFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system output frequency in tenths of Hertz."
+ ::= { xATSSystemOutput 1 }
+
+xATSSystemOutputTotalPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the total system output power in tenths of kW."
+ ::= { xATSSystemOutput 2 }
+
+xATSSystemOutputTotalApparentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the total system output power in tenths of kVA."
+ ::= { xATSSystemOutput 3 }
+
+xATSSystemOutputTotalPowerFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the total power factor of the system output.
+ A value of 100 representing a unity power factor (1.00)
+ Specified in hundredths."
+ ::= { xATSSystemOutput 4 }
+
+xATSSystemOutputFrequencyTolerance OBJECT-TYPE
+ SYNTAX INTEGER{
+ freqToleranceOff (1),
+ freqTolerancePointTwo (2),
+ freqTolerancePointFive (3),
+ freqToleranceOne (4),
+ freqToleranceOnePointFive (5),
+ freqToleranceTwo (6),
+ freqToleranceThree (7),
+ freqToleranceFour (8),
+ freqToleranceFive (9),
+ freqToleranceNine (10)
+
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Shows the panel output frequency tolerance in +/- Hertz."
+ ::= { xATSSystemOutput 5 }
+
+xATSSystemOutputOverVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which an output over voltage condition will be generated.
+ Specified as tenths of percent deviation from nominal.
+ A value of zero indicates that the threshold is disabled."
+ ::= { xATSSystemOutput 6 }
+
+xATSSystemOutputUnderVoltThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which an output under voltage condition will be generated.
+ Specified as tenths of percent deviation from nominal.
+ A value of zero indicates that the threshold is disabled."
+ ::= { xATSSystemOutput 7 }
+
+xATSSystemOutputOverCurrentThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold above which an over current condition will be generated.
+ Specified as a percent of the transfer switch rating (xATSDeviceTransferSwitchRating OID).
+ A value of zero indicates that the threshold is disabled."
+ ::= { xATSSystemOutput 8 }
+
+xATSSystemOutputUnderCurrentThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which an under current condition will be generated.
+ Specified as a percent of the transfer switch rating (xATSDeviceTransferSwitchRating OID).
+ A value of zero indicates that the threshold is disabled."
+ ::= { xATSSystemOutput 9 }
+
+xATSSystemOutputAlarmDelayThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Delay the generation of an output alarm.
+ Specified in seconds."
+ ::= { xATSSystemOutput 10 }
+
+xATSSystemOutputTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of system output phase entries."
+ ::= { xATSSystemOutput 11 }
+
+xATSSystemOutputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSSystemOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of system output table entries.
+ The number of entries is contained in the xATSSystemOutputTableSize OID."
+ ::= { xATSSystemOutput 12 }
+
+ xATSSystemOutputPhaseEntry OBJECT-TYPE
+ SYNTAX XATSSystemOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular system output phase."
+ INDEX { xATSSystemOutputPhaseIndex }
+ ::= { xATSSystemOutputTable 1 }
+
+ XATSSystemOutputPhaseEntry ::= SEQUENCE {
+ xATSSystemOutputPhaseIndex INTEGER,
+ xATSSystemOutputVoltageLtoL INTEGER,
+ xATSSystemOutputVoltageLtoN INTEGER,
+ xATSSystemOutputPhaseCurrent INTEGER,
+ xATSSystemOutputPower INTEGER,
+ xATSSystemOutputApparentPower INTEGER,
+ xATSSystemOutputPowerFactor INTEGER
+ }
+
+ xATSSystemOutputPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each system output phase utilized in this device."
+ ::= { xATSSystemOutputPhaseEntry 1 }
+
+ xATSSystemOutputVoltageLtoL OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-line system output voltage, measured in tenths of Volts, available at the circuit panel.
+ -1 if not available."
+ ::= { xATSSystemOutputPhaseEntry 2 }
+
+ xATSSystemOutputVoltageLtoN OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-neutral system output voltage, measured in tenths of Volts, available at the circuit panel.
+ -1 for a 3-wire service type or if not available."
+ ::= { xATSSystemOutputPhaseEntry 3 }
+
+ xATSSystemOutputPhaseCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System load current per phase. Measured in Amps.
+ -1 if not available."
+ ::= { xATSSystemOutputPhaseEntry 4 }
+
+ xATSSystemOutputPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System output power per phase. Measured in tenths of kW."
+ ::= { xATSSystemOutputPhaseEntry 5 }
+
+ xATSSystemOutputApparentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "system output power per phase. Measured in tenths of kVA."
+ ::= { xATSSystemOutputPhaseEntry 6 }
+
+ xATSSystemOutputPowerFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "indicates the power factor of the system output per phase.
+ A value of 100 representing a unity power factor (1.00).
+ Measured in hundredths."
+ ::= { xATSSystemOutputPhaseEntry 7 }
+
+-- xATS TestingStatus group
+
+xATSTestingStatusSelectTestProcess OBJECT-TYPE
+ SYNTAX INTEGER {
+ engineStartTest (1),
+ systemLoadTest (2),
+ generatorHoldTest (3),
+ cancelTest (4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Type of tests that can be selected when no test has been scheduled.
+ engineStartTest and systemLoadTest may be selected when no tests
+ are running. Tests that are selected may be cancelled manually."
+ ::= { xATSTestingStatus 1 }
+
+xATSTestingStatusTestStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ noTestInProcess (1),
+ testPending (2),
+ startingEngine (3),
+ engineWarmingUp (4),
+ awaitingTransferToS2 (5),
+ testingWithLoad (6),
+ awaitingRetransferToS1 (7),
+ testingWithoutLoad (8),
+ stoppingEngine (9),
+ holdingOnGenerator (10)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The present system test status/state."
+ ::= { xATSTestingStatus 2 }
+
+xATSTestingStatusProfileWarmupTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time that the generator will warm up during a test.
+ This is portion of the test when the xATSTestingStatusTestStatus
+ OID returns the value engineWarmingUp.
+ Specified in seconds."
+ ::= { xATSTestingStatus 3 }
+
+xATSTestingStatusProfileLoadedTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time that ATS will apply the system load to the generator
+ during a system load test.
+ This is portion of the test when the xATSTestingStatusTestStatus
+ OID returns the value testingWithLoad.
+ Specified in minutes."
+ ::= { xATSTestingStatus 4 }
+
+xATSTestingStatusProfileUnloadedTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time that the generator will run following the warm up
+ portion of a start test, or the loaded portion of a load test.
+ This is portion of the test when the xATSTestingStatusTestStatus
+ OID returns the value testingWithoutLoad.
+ Specified in seconds."
+ ::= { xATSTestingStatus 5 }
+
+-- xATS TestingResults group
+
+xATSTestingResultsLastDateOfTest OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Date of the last test that was performed, either scheduled or manual.
+ Test results are available in the xATSTestingResultsLastResult OID.
+ Specified in the dd/mm/yyyy format, or 'none' if not available."
+ ::= { xATSTestingResults 1 }
+
+xATSTestingResultsLastResult OBJECT-TYPE
+ SYNTAX INTEGER {
+ startTestPassed (1),
+ loadTestPassed (2),
+ startSignalFailure (3),
+ failedGenNotInAuto (4),
+ failedGenEmerStop (5),
+ failedGenShutdown (6),
+ failedGenDidNotStart (7),
+ failedS2NeverGood (8),
+ genFailedDuringWarmup (9),
+ failureOnXferToS1 (10),
+ genFailedLoaded (11),
+ failureOnRexferToS2 (12),
+ genFailedToStop (13),
+ failedAtsInternalFault (14),
+ failedAtsNotInAuto (15),
+ cancelledManualTest (16),
+ cancelledScheduledTest (17)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The result of the last ATS/generator system test."
+ ::= { xATSTestingResults 2 }
+
+xATSTestingResultsTestLastTestTime OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Time of day at which the last test was performed, either scheduled or manual.
+ Test results are available in the xATSTestingResultsLastResult OID.
+ Specified in the hh:mm:ss format, or 'none' if not available."
+ ::= { xATSTestingResults 3 }
+
+xATSTestingResultsLastCrankDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The time spent cranking the generator before it started during the last test.
+ Specified in seconds, or -1 if not available."
+ ::= { xATSTestingResults 4 }
+
+xATSTestingResultsLastWarmupDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The time spent in the engineWarmingUp state during the last system test.
+ Specified in seconds, or -1 if not available."
+ ::= { xATSTestingResults 5 }
+
+xATSTestingResultsLastLoadedDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The time spent in the testingWithLoad state during the last system test.
+ Specified in seconds, or -1 if not available."
+ ::= { xATSTestingResults 6 }
+
+xATSTestingResultsLastUnloadedDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The time spent in the testingWithoutLoad state during the last system test.
+ Specified in seconds, or -1 if not available."
+ ::= { xATSTestingResults 7 }
+
+-- xATS TestingSchedule group
+
+xATSTestingScheduleFrequency OBJECT-TYPE
+ SYNTAX INTEGER {
+ never (1),
+ daily (2),
+ weekly (3),
+ monthly (4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The frequency of running scheduled tests."
+ ::= { xATSTestingSchedule 1 }
+
+xATSTestingScheduleTestDay OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The desired day for the scheduled test. This object applies only
+ when the xATSTestingScheduleFrequency OID is set to weekly or monthly.
+ For weekly test frequency, the string is the day the test will be run.
+ For monthly test frequency, the string indicates the day,
+ and the instance within the month.
+ For example, for monthly frequency: 2nd sunday, 3rd monday, 4th tuesday,
+ for weekly frequency: sunday, monday, tuesday."
+ ::= { xATSTestingSchedule 2 }
+
+xATSTestingScheduleTestTime OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The time of day that the scheduled test will occur.
+ Specified in the format hh:mm."
+ ::= { xATSTestingSchedule 3 }
+
+xATSTestingScheduleTestWithLoadInterval OBJECT-TYPE
+ SYNTAX INTEGER {
+ applyLoadEveryTest (1),
+ neverApplyLoad (2),
+ applyLoadMonthly (3),
+ applyLoadMonthlyDetailed (4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This setting specifies which system tests should include applying the
+ load to the generator. The applyLoadMonthlyDetailed entry
+ in the list will apply load once, for each month represented in the
+ xATSTestingScheduleTestWithLoadSelectMonth OID."
+ ::= { xATSTestingSchedule 4 }
+
+xATSTestingScheduleTestWithLoadSelectMonth OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The detailed selection for testing with load on a month-by-month basis.
+ This object is applicable when the xATSTestingScheduleTestWithLoadInterval
+ is set to applyLoadMonthlyDetailed. Otherwise this selection will be ignored.
+ Format for this string is a comma-separated entry of months.
+ For example: Jan,Mar,Dec.
+ The string will return 'No Months Scheduled' if no months have been selected."
+ ::= { xATSTestingSchedule 5 }
+
+xATSTestingScheduleNextTestDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date of the next scheduled test, in the format dd-mmm-yyyy."
+ ::= { xATSTestingSchedule 6 }
+
+-- xATSTestingSimulatePowerFail group
+
+xATSTestingSimulatePowerFailTest OBJECT-TYPE
+ SYNTAX INTEGER{
+ cancelSimulation (1),
+ fiveSecondsSimulation (2),
+ tenSecondsSimulation (3),
+ thirtySecondsSimulation (4),
+ oneMinuteSimulation (5),
+ threeMinutesSimulation (6),
+ fiveMinutesSimulation (7),
+ tenMinutesSimulation (8)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This object executes a simulated power failure for the duration indicated.
+ Simulation can be aborted by selecting cancelSimulation."
+ ::= { xATSTestingSimulatePowerFail 1 }
+
+xATSTestingSimulatePowerFailTimeRemaining OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the time remaining in seconds, for a simulated power failure.
+ a value of zero indicates that simulated power failure is not active."
+ ::= { xATSTestingSimulatePowerFail 2 }
+
+-- The xATS Input Contact group
+
+xATSInputContactNumContacts OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of contacts supported by the ATS."
+ ::= { xATSInputContacts 1 }
+
+xATSInputContactTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input contact entries."
+ ::= { xATSInputContacts 2 }
+
+xATSInputContactTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSContactEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of contacts supported by the ATS.
+ The number of entries is contained in the
+ xATSInputContactTableSize OID."
+ ::= { xATSInputContacts 3 }
+
+ xATSInputContactEntry OBJECT-TYPE
+ SYNTAX XATSContactEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A contact entry containing information for a given contact."
+ INDEX { xATSInputContactNumber }
+ ::= { xATSInputContactTable 1 }
+
+ XATSContactEntry ::=
+ SEQUENCE {
+ xATSInputContactNumber INTEGER,
+ xATSInputContactName DisplayString,
+ xATSInputContactNormalState INTEGER,
+ xATSInputContactCurrentState INTEGER
+ }
+
+ xATSInputContactNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An index identifying the contact on the ATS."
+ ::= { xATSInputContactEntry 1 }
+
+ xATSInputContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The description of the purpose/use of the contact."
+ ::= { xATSInputContactEntry 2 }
+
+ xATSInputContactNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The normal operating position of the contact."
+ ::= { xATSInputContactEntry 3 }
+
+ xATSInputContactCurrentState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This value indicates the current state of the contact."
+ ::= { xATSInputContactEntry 4 }
+
+-- the xATS OutputRelays group
+
+ xATSOutputRelayNumRelays OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output relays supported by the ATS."
+ ::= { xATSOutputRelays 1 }
+
+ xATSOutputRelayTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output relay entries."
+ ::= { xATSOutputRelays 2 }
+
+ xATSOutputRelayTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSOutputRelayEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output relays supported by the ATS.
+ The number of entries is contained in the
+ xATSOutputRelayTableSize OID."
+ ::= { xATSOutputRelays 3 }
+
+ xATSOutputRelayEntry OBJECT-TYPE
+ SYNTAX XATSOutputRelayEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A output relay entry containing information for a given contact."
+ INDEX { xATSOutputRelayNumber }
+ ::= { xATSOutputRelayTable 1 }
+
+ XATSOutputRelayEntry ::=
+ SEQUENCE {
+ xATSOutputRelayNumber INTEGER,
+ xATSOutputRelayName DisplayString,
+ xATSOutputRelayNormalState INTEGER,
+ xATSOutputRelayCurrentState INTEGER
+ }
+
+ xATSOutputRelayNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An index identifying the output relay on the ATS."
+ ::= { xATSOutputRelayEntry 1 }
+
+ xATSOutputRelayName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The description of the purpose/use of the output relay."
+ ::= { xATSOutputRelayEntry 2 }
+
+ xATSOutputRelayNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The normal operating position of the output relay."
+ ::= { xATSOutputRelayEntry 3 }
+
+ xATSOutputRelayCurrentState OBJECT-TYPE
+ SYNTAX INTEGER {
+ open (1),
+ closed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This value indicates the current state of the output relay."
+ ::= { xATSOutputRelayEntry 4 }
+
+-- The xATS Generator Ident group
+
+xATSGeneratorIdentModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the model number of the generator.
+ This value is set at the factory."
+ ::= { xATSGeneratorIdent 1 }
+
+xATSGeneratorIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the serial number of the generator.
+ This value is set at the factory."
+ ::= { xATSGeneratorIdent 2 }
+
+xATSGeneratorIdentDateofManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying when the generator was manufactured in mm/dd/yyyy format.
+ This value is set at the factory."
+ ::= { xATSGeneratorIdent 3 }
+
+xATSGeneratorIdentVoltageConfiguration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The voltage for which the generator's alternator is designed.
+ Specified in Volts line-to-line."
+ ::= { xATSGeneratorIdent 4 }
+
+xATSGeneratorIdentMaxPowerRating OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The max power rating of the generator. Specified in kW."
+ ::= { xATSGeneratorIdent 5 }
+
+xATSGeneratorIdentAlternatorFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frequency for which the generator's alternator is designed.
+ Specified in Hertz."
+ ::= { xATSGeneratorIdent 6 }
+
+-- The xATS Generator Status group
+
+xATSGeneratorStatusGeneratorName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name or label for the generator connected to the source 2 of the ATS."
+ ::= { xATSGeneratorStatus 1 }
+
+xATSGeneratorStatusOperational OBJECT-TYPE
+ SYNTAX INTEGER{
+ nocomm (1),
+ off (2),
+ ready (3),
+ starting (4),
+ idle (5),
+ running (6),
+ normalStop (7),
+ emergencyStop (8),
+ notInAuto (9),
+ shutdown (10),
+ unknown (11)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The operational status of the generator. unavailable when unrecognized status is received."
+ ::= { xATSGeneratorStatus 2 }
+
+xATSGeneratorStatusModeSwitchPosition OBJECT-TYPE
+ SYNTAX INTEGER{
+ off (1),
+ manual (2),
+ automatic (3),
+ unknown (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The position of the generator's auto-mode switch.
+ In automatic mode, the generator is started and stopped via the
+ remote start contact, which has state indicated in the
+ xATSGeneratorStatusRemoteStart OID.
+ In manual mode generator start/stop control is via local command only.
+ Off prevents the generator from running."
+ ::= { xATSGeneratorStatus 3 }
+
+xATSGeneratorStatusRemoteStart OBJECT-TYPE
+ SYNTAX INTEGER{
+ stop (1),
+ run (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the generator's remote start contact, which is
+ provided as an output from the transfer switch to start/stop the
+ generator when in automatic mode."
+ ::= { xATSGeneratorStatus 4 }
+
+-- The xATS Generator Advanced Status group
+
+xATSGeneratorAdvStatusBatteryVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The voltage of the generator's starting battery.
+ Measured in tenths of VDC, or -1 if not available."
+ ::= { xATSGeneratorAdvStatus 1 }
+
+xATSGeneratorAdvStatusOilPressure OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The generator's engine oil pressure.
+ Measured in tenths of Psi or kPa, based on the
+ value of the xATSGeneratorSettingsMetricUnit OID,
+ or -1 if not available."
+ ::= { xATSGeneratorAdvStatus 2 }
+
+xATSGeneratorAdvStatusCoolantTemperature OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Current coolant temperature in the generator.
+ Measured in degrees Celsius or Fahrenheit, based on the
+ value of the xATSGeneratorSettingsMetricUnit OID,
+ or -1 if not available."
+ ::= { xATSGeneratorAdvStatus 3 }
+
+xATSGeneratorAdvStatusEngineRPM OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Current engine speed of the generator.
+ Measured in RPM, or -1 if not available."
+ ::= { xATSGeneratorAdvStatus 4 }
+
+xATSGeneratorAdvStatusOilLevel OBJECT-TYPE
+ SYNTAX INTEGER{
+ ok (1),
+ low (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates adequate oil level in the generator."
+ ::= { xATSGeneratorAdvStatus 5 }
+
+xATSGeneratorAdvStatusCoolantLevel OBJECT-TYPE
+ SYNTAX INTEGER{
+ ok (1),
+ low (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates adequate coolant level in the generator."
+ ::= { xATSGeneratorAdvStatus 6 }
+
+-- The xATS Generator Output group
+
+xATSGeneratorOutputFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output frequency of the generator.
+ Measured in tenths of Hertz, or -1 if not avaialble."
+ ::= { xATSGeneratorOutput 1 }
+
+xATSGeneratorOutputTotalPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total output power of the generator.
+ Measured in tenths of tenths of kW, or -1 if not avaialble."
+ ::= { xATSGeneratorOutput 2 }
+
+xATSGeneratorOutputTotalApparentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total output power of the generator.
+ Measured in tenths of kVA, or -1 if not avaialble."
+ ::= { xATSGeneratorOutput 3 }
+
+xATSGeneratorOutputTotalPowerFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the total load power factor of the generator.
+ A value of 100 representing a unity power factor (1.00),
+ or -1 when if not avaialble."
+ ::= { xATSGeneratorOutput 4 }
+
+xATSGeneratorOutputTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of generator output phase entries."
+ ::= { xATSGeneratorOutput 5 }
+
+ xATSGeneratorOutputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF XATSGeneratorOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of generator output table entries.
+ The number of entries is contained in the xATSGeneratorOutputTableSize OID."
+ ::= { xATSGeneratorOutput 6 }
+
+ xATSGeneratorOutputPhaseEntry OBJECT-TYPE
+ SYNTAX XATSGeneratorOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular generator output phase."
+ INDEX { xATSGeneratorOutputPhaseIndex }
+ ::= { xATSGeneratorOutputTable 1 }
+
+ XATSGeneratorOutputPhaseEntry ::= SEQUENCE {
+ xATSGeneratorOutputPhaseIndex INTEGER,
+ xATSGeneratorOutputVoltageLtoL INTEGER,
+ xATSGeneratorOutputVoltageLtoN INTEGER,
+ xATSGeneratorOutputPhaseCurrent INTEGER,
+ xATSGeneratorOutputPower INTEGER,
+ xATSGeneratorOutputApparentPower INTEGER,
+ xATSGeneratorOutputPowerFactor INTEGER
+ }
+
+ xATSGeneratorOutputPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each generator output phase utilized in this device."
+ ::= { xATSGeneratorOutputPhaseEntry 1 }
+
+ xATSGeneratorOutputVoltageLtoL OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-line generator output voltage.
+ Measured in Volts, or -1 if not available."
+ ::= { xATSGeneratorOutputPhaseEntry 2 }
+
+ xATSGeneratorOutputVoltageLtoN OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Line-to-neutral generator output voltage.
+ Measured in volts, or -1 if not avaialble."
+ ::= { xATSGeneratorOutputPhaseEntry 3 }
+
+ xATSGeneratorOutputPhaseCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Generator load current per phase.
+ Measured in Amps, or -1 if not avaialble."
+ ::= { xATSGeneratorOutputPhaseEntry 4 }
+
+ xATSGeneratorOutputPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Generator output power per phase.
+ Measured in tenths of kW, or -1 if not avaialble."
+ ::= { xATSGeneratorOutputPhaseEntry 5 }
+
+ xATSGeneratorOutputApparentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Generator output power per phase.
+ Measured in tenths of kVA, or -1 if not available."
+ ::= { xATSGeneratorOutputPhaseEntry 6 }
+
+ xATSGeneratorOutputPowerFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates the load power factor of the generator output per phase.
+ A value of 100 representing a unity power factor (1.00),
+ or -1 if not avaialble."
+ ::= { xATSGeneratorOutputPhaseEntry 7 }
+
+-- xATS Generator Settings group
+
+xATSGeneratorSettingsVoltageAdjust OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The voltage adjust of the generator.
+ Specified in volts line-to-line,
+ or -1 if not available."
+ ::= { xATSGeneratorSettings 1 }
+
+xATSGeneratorSettingsFrequencyAdjust OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frequency adjust of the generator.
+ Specified in tenths of Hertz."
+ ::= { xATSGeneratorSettings 2 }
+
+xATSGeneratorSettingsStartDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The delay, in seconds, after the remote run signal is activated
+ before the generator's engine will be cranked to start,
+ or -1 if not available."
+ ::= { xATSGeneratorSettings 3 }
+
+xATSGeneratorSettingsStopDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The delay, in seconds, before the generator will stop
+ after the remote run signal is deactivated,
+ or -1 if not available."
+ ::= { xATSGeneratorSettings 4 }
+
+xATSGeneratorSettingsCrankCycleEnable OBJECT-TYPE
+ SYNTAX INTEGER{
+ disabled (1),
+ enabled (2),
+ unknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "When Crank Cycle is enabled, the engine will be cranked up to the time
+ specified by the xATSGeneratorSettingsCrankTime OID.
+ If the generator's engine does not start, there will be a pause as
+ specified by the xATSGeneratorSettingsCrankRestTime OID before the
+ engine will be cranked again. This cycle is repeated as specified by
+ the xATSGeneratorSettingsNumberCrank OID.
+ When crank cycle is disabled, the generator's engine will be
+ cranked continuously until it starts."
+ ::= { xATSGeneratorSettings 5 }
+
+xATSGeneratorSettingsCrankTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The duration of engine cranking, in seconds, when starting the generator.
+ Applicable when the xATSGeneratorSettingsCrankCycleEnable OID is enabled.
+ -1 if not available."
+ ::= { xATSGeneratorSettings 6 }
+
+xATSGeneratorSettingsCrankRestTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The pause duration, in seconds, following an unsuccessful attempt to start the generator.
+ Applicable when the xATSGeneratorSettingsCrankCycleEnable OID is enabled.
+ -1 if not available."
+ ::= { xATSGeneratorSettings 7 }
+
+xATSGeneratorSettingsNumberCrank OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of failed crank attempts before giving up on starting the generator.
+ Applicable when the xATSGeneratorSettingsCrankCycleEnable OID is enabled.
+ -1 if not available."
+ ::= { xATSGeneratorSettings 8 }
+
+xATSGeneratorSettingsMetricUnit OBJECT-TYPE
+ SYNTAX INTEGER{
+ disabled (1),
+ enabled (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Specifies the use of metric units in generator related OIDs, as well
+ as on all other interfaces including the generator's local interface."
+ ::= { xATSGeneratorSettings 9 }
+
+-- xATS generator service group
+
+xATSGeneratorServiceTotalRunHoursLifetime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Total time that the generator engine has been run,
+ over the life of the generator. Measured in hours.
+ -1 if not available."
+ ::= { xATSGeneratorService 1 }
+
+xATSGeneratorServiceEngineStartsLifetime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Number of engine starts over the life of the generator.
+ -1 if not available."
+ ::= { xATSGeneratorService 2 }
+
+xATSGeneratorServiceTotalkWhLifetime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Total kWh of operation over the life of the generator.
+ -1 if not available."
+ ::= { xATSGeneratorService 3 }
+
+xATSGeneratorServiceTotalRunHoursSinceMaintanence OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Total time that the generator engine has been run,
+ since last service maintenance. Measured in tenths of hours.
+ -1 if not available."
+ ::= { xATSGeneratorService 4 }
+
+xATSGeneratorServiceEngineStartsSinceMaintanence OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Number of engine starts since last service maintenance.
+ -1 if not available."
+ ::= { xATSGeneratorService 5 }
+
+xATSGeneratorServiceTotalkWhMaintanence OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Total kWh of operation since last service maintenance.
+ -1 if not available."
+ ::= { xATSGeneratorService 6 }
+
+xATSGeneratorServiceResetRecord OBJECT-TYPE
+ SYNTAX INTEGER{
+ yes (1),
+ no (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Resets the engine start counter, engine run-hours, and kWh values that have
+ accumulated in the generator since last maintenance.
+ Also, the last service date will be reset to the current system date, and
+ any service alarms will be cleared."
+ ::= { xATSGeneratorService 7 }
+
+xATSGeneratorServiceRecordResetDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Date at which the generator's service record was reset, in dd-mmm-yyyy format."
+ ::= { xATSGeneratorService 8 }
+
+xATSGeneratorServiceNextServiceDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Date at which the next generator service is due in dd-mmm-yyyy format.
+ Based on the xATSGeneratorServiceCalendarIntervalThreshold OID
+ or '' if the calander-based threshold is set to off."
+ ::= { xATSGeneratorService 9 }
+
+xATSGeneratorServiceRunHoursUntilServiceDate OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Runhours until the next generator service is due, in hours.
+ Based on the xATSGeneratorServiceRunHoursThreshold OID
+ or -1 if the runhour-based threshold is set to off."
+ ::= { xATSGeneratorService 10 }
+
+xATSGeneratorServiceRunHoursThreshold OBJECT-TYPE
+ SYNTAX INTEGER{
+ disabled (1),
+ runThreshold100Hours (2),
+ runThreshold150Hours (3),
+ runThreshold200Hours (4),
+ runThreshold250Hours (5),
+ runThreshold300Hours (6),
+ runThreshold400Hours (7),
+ runThreshold500Hours (8)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Runhour-based service interval. When the run-hours since
+ service surpasses this threshold, generator service is due."
+ ::= { xATSGeneratorService 11 }
+
+xATSGeneratorServiceCalendarIntervalThreshold OBJECT-TYPE
+ SYNTAX INTEGER{
+ disabled (1),
+ interval1month (2),
+ interval2month (3),
+ interval3month (4),
+ interval6month (5),
+ intervalyearly (6)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Calander-based service interval. When the next service date,
+ as indicated by the xATSGeneratorServiceNextServiceDate OID
+ is in the past, generator is due for service."
+ ::= { xATSGeneratorService 12 }
+
+-- The xATS Generator Fuel system group
+
+xATSGeneratorFuelSystemType OBJECT-TYPE
+ SYNTAX INTEGER{
+ diesel (1),
+ propane (2),
+ naturalGas (3),
+ unknown (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The type of fuel used by the generator."
+ ::= { xATSGeneratorFuelSystem 1 }
+
+xATSGeneratorFuelSystemTankSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Size of the generator's fuel tank.
+ Specified in gallons or liters, based on the value of the
+ xATSGeneratorSettingsMetricUnit OID, or -1 if not available."
+ ::= { xATSGeneratorFuelSystem 2 }
+
+xATSGeneratorFuelSystemFuelLevel OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Fuel remaining in the generator tank.
+ Measured in percent of tank fill, or -1 if if not available."
+ ::= { xATSGeneratorFuelSystem 3 }
+
+xATSGeneratorFuelSystemRuntimePower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The power value used in the runtime remaining calculation.
+ Measured in tenths of kW, or -1 if not available."
+ ::= { xATSGeneratorFuelSystem 4 }
+
+xATSGeneratorFuelSystemEstimatedRunTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An estimate of available runtime for the generator, based on
+ available fuel as specified in the xATSGeneratorFuelSystemFuelLevel OID
+ and kW load as specified in the xATSGeneratorFuelSystemRuntimePower OID.
+ Measured in tenths of hours, or -1 if not available."
+ ::= { xATSGeneratorFuelSystem 5 }
+
+xATSGeneratorFuelSystemLowRunTimeThreshold OBJECT-TYPE
+ SYNTAX INTEGER{
+ disabled (1),
+ oneHour (2),
+ twoHours (3),
+ threeHours (4),
+ fourHours (5),
+ fiveHours (6),
+ sixHours (7),
+ twelveHours (8),
+ oneDay (9),
+ twoDays (10),
+ threeDays (11),
+ fourDays (12),
+ fiveDays (13),
+ sixDays (14),
+ sevenDays (15)
+
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which a low runtime alarm will exist."
+ ::= { xATSGeneratorFuelSystem 6 }
+
+xATSGeneratorFuelSystemVeryLowRunTimeThreshold OBJECT-TYPE
+ SYNTAX INTEGER{
+ disabled (1),
+ oneHour (2),
+ twoHours (3),
+ threeHours (4),
+ fourHours (5),
+ fiveHours (6),
+ sixHours (7),
+ twelveHours (8),
+ oneDay (9),
+ twoDays (10),
+ threeDays (11),
+ fourDays (12),
+ fiveDays (13),
+ sixDays (14),
+ sevenDays (15)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which a very low runtime alarm will exist."
+ ::= { xATSGeneratorFuelSystem 7 }
+
+xATSGeneratorFuelSystemLowFuelLevelThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which a low fuel alarm will exist, with a value of 0 indicating disabled.
+ Specified as percent of tank fill."
+ ::= { xATSGeneratorFuelSystem 8 }
+
+xATSGeneratorFuelSystemVeryLowFuelLevelThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold below which a very low fuel alarm will exist, with a value of 0 indicating disabled.
+ Specified as percent of tank fill."
+ ::= { xATSGeneratorFuelSystem 9 }
+
+-- the software group
+-- the powerNetSubAgent group
+-- the powerNetSoftwareSystem group
+
+powerNetSoftwareSystemDescription OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..79))
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A brief description of the PowerNet sub-agent."
+ ::= { powerNetSoftwareSystem 1 }
+
+powerNetSoftwareOid OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The object identifier of the PowerNet sub-agent."
+ ::= { powerNetSoftwareSystem 2 }
+
+-- powerNetSmuxPeer OBJECT IDENTIFIER ::= { powerNetSoftwareOid 1 }
+-- powerNetDPIPeer OBJECT IDENTIFIER ::= { powerNetSoftwareOid 2 }
+
+powerNetSoftwareSystemUpTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The time that the sub-agent has been running."
+ ::= { powerNetSoftwareSystem 3 }
+
+
+-- powerNetSoftwareConfig group
+
+powerNetSoftwareTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of software modules supporting the UPS."
+ ::= { powerNetSoftwareConfig 1 }
+
+powerNetSoftwareTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF SoftwareEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of the software monitoring the UPS."
+ ::= { powerNetSoftwareConfig 2 }
+
+powerNetSoftwareEntry OBJECT-TYPE
+ SYNTAX SoftwareEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information on a software module."
+ INDEX { moduleNumber }
+ ::= { powerNetSoftwareTable 1 }
+
+SoftwareEntry ::=
+ SEQUENCE {
+ moduleNumber
+ INTEGER,
+ moduleName
+ DisplayString,
+ moduleVersion
+ DisplayString,
+ moduleDate
+ DisplayString
+ }
+
+moduleNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index into the Software Entry Table"
+ ::= { powerNetSoftwareEntry 1 }
+
+moduleName OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..79))
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the software module."
+ ::= { powerNetSoftwareEntry 2 }
+
+moduleVersion OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..8))
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The version of the software module."
+ ::= { powerNetSoftwareEntry 3 }
+
+moduleDate OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..9))
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date of the software module represented as mm-dd-yy."
+ ::= { powerNetSoftwareEntry 4 }
+
+
+-- the ups group
+-- the upsIdent group
+-- the upsBasicIdent
+
+upsBasicIdentModel OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The UPS model name (e.g. 'APC Smart-UPS 600')."
+ ::= { upsBasicIdent 1 }
+
+upsBasicIdentName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "An 8 byte ID string identifying the UPS. This object
+ can be set by the administrator."
+ ::= { upsBasicIdent 2 }
+
+
+-- the upsAdvIdent group
+
+upsAdvIdentFirmwareRevision OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the UPS system's microprocessor."
+ ::= { upsAdvIdent 1 }
+
+upsAdvIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the UPS was manufactured in mm/dd/yy format."
+ ::= { upsAdvIdent 2 }
+
+upsAdvIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An 8-character string identifying the serial number of
+ the UPS internal microprocessor. This number is set at
+ the factory. NOTE: This number does NOT correspond to
+ the serial number on the rear of the UPS."
+ ::= { upsAdvIdent 3 }
+
+
+
+-- the upsBattery group
+-- the upsBasicBattery group
+
+upsBasicBatteryStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ batteryNormal(2),
+ batteryLow(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the UPS batteries. A batteryLow(3)
+ value indicates the UPS will be unable to sustain the
+ current load, and its services will be lost if power is
+ not restored. The amount of run time in reserve at the
+ time of low battery can be configured by the
+ upsAdvConfigLowBatteryRunTime."
+ ::= { upsBasicBattery 1 }
+
+upsBasicBatteryTimeOnBattery OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The elapsed time since the UPS has switched to battery
+ power."
+ ::= { upsBasicBattery 2 }
+
+upsBasicBatteryLastReplaceDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the UPS system's batteries were last replaced
+ in mm/dd/yy format. For Smart-UPS models, this value
+ is originally set in the factory. When the UPS batteries
+ are replaced, this value should be reset by the administrator."
+ ::= { upsBasicBattery 3 }
+
+
+
+-- the upsAdvBattery group
+
+upsAdvBatteryCapacity OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The remaining battery capacity expressed in
+ percent of full capacity."
+ ::= { upsAdvBattery 1 }
+
+upsAdvBatteryTemperature OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current internal UPS temperature expressed in
+ Celsius."
+ ::= { upsAdvBattery 2 }
+
+upsAdvBatteryRunTimeRemaining OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The UPS battery run time remaining before battery
+ exhaustion."
+ ::= { upsAdvBattery 3 }
+
+upsAdvBatteryReplaceIndicator OBJECT-TYPE
+ SYNTAX INTEGER {
+ noBatteryNeedsReplacing(1),
+ batteryNeedsReplacing(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Indicates whether the UPS batteries need replacing."
+ ::= { upsAdvBattery 4 }
+
+upsAdvBatteryNumOfBattPacks OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of external battery packs connected to the UPS. If
+ the UPS does not use smart cells then the agent reports
+ ERROR_NO_SUCH_NAME."
+ ::= { upsAdvBattery 5 }
+
+upsAdvBatteryNumOfBadBattPacks OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of external battery packs connected to the UPS that
+ are defective. If the UPS does not use smart cells then the
+ agent reports ERROR_NO_SUCH_NAME."
+ ::= { upsAdvBattery 6 }
+
+upsAdvBatteryNominalVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The nominal battery voltage in Volts."
+ ::= { upsAdvBattery 7 }
+
+upsAdvBatteryActualVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The actual battery bus voltage in Volts."
+ ::= { upsAdvBattery 8 }
+
+upsAdvBatteryCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery current in Amps."
+ ::= { upsAdvBattery 9 }
+
+upsAdvTotalDCCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total DC current in Amps."
+ ::= { upsAdvBattery 10 }
+
+
+-- the upsBasicInput group
+
+upsBasicInputPhase OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current AC input phase."
+ ::= { upsBasicInput 1 }
+
+
+-- the upsAdvInput group
+
+upsAdvInputLineVoltage OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current utility line voltage in VAC."
+ ::= { upsAdvInput 1 }
+
+upsAdvInputMaxLineVoltage OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum utility line voltage in VAC over the
+ previous 1 minute period."
+ ::= { upsAdvInput 2 }
+
+upsAdvInputMinLineVoltage OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum utility line voltage in VAC over the
+ previous 1 minute period."
+ ::= { upsAdvInput 3 }
+
+upsAdvInputFrequency OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current input frequency to the UPS system in Hz."
+ ::= { upsAdvInput 4 }
+
+
+upsAdvInputLineFailCause OBJECT-TYPE
+ SYNTAX INTEGER {
+ noTransfer(1),
+ highLineVoltage(2),
+ brownout(3),
+ blackout(4),
+ smallMomentarySag(5),
+ deepMomentarySag(6),
+ smallMomentarySpike(7),
+ largeMomentarySpike(8),
+ selfTest(9),
+ rateOfVoltageChnage(10)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The reason for the occurrence of the last transfer to UPS
+ battery power. The variable is set to:
+ - noTransfer(1) -- if there is no transfer yet.
+ - highLineVoltage(2) -- if the transfer to battery is caused
+ by an over voltage greater than the high transfer voltage.
+ - brownout(3) -- if the duration of the outage is greater than
+ five seconds and the line voltage is between 40% of the
+ rated output voltage and the low transfer voltage.
+ - blackout(4) -- if the duration of the outage is greater than five
+ seconds and the line voltage is between 40% of the rated
+ output voltage and ground.
+ - smallMomentarySag(5) -- if the duration of the outage is less
+ than five seconds and the line voltage is between 40% of the
+ rated output voltage and the low transfer voltage.
+ - deepMomentarySag(6) -- if the duration of the outage is less
+ than five seconds and the line voltage is between 40% of the
+ rated output voltage and ground. The variable is set to
+ - smallMomentarySpike(7) -- if the line failure is caused by a
+ rate of change of input voltage less than ten volts per cycle.
+ - largeMomentarySpike(8) -- if the line failure is caused by
+ a rate of change of input voltage greater than ten volts per cycle.
+ - selfTest(9) -- if the UPS was commanded to do a self test.
+ - rateOfVoltageChange(10) -- if the failure is due to the rate of change of
+ the line voltage."
+ ::= { upsAdvInput 5 }
+
+
+-- the upsBasicOutput group
+
+upsBasicOutputStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ onLine(2),
+ onBattery(3),
+ onSmartBoost(4),
+ timedSleeping(5),
+ softwareBypass(6),
+ off(7),
+ rebooting(8),
+ switchedBypass(9),
+ hardwareFailureBypass(10),
+ sleepingUntilPowerReturn(11),
+ onSmartTrim(12)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current state of the UPS. If the UPS is unable
+ to determine the state of the UPS this variable is set
+ to unknown(1)."
+ ::= { upsBasicOutput 1 }
+
+upsBasicOutputPhase OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current output phase."
+ ::= { upsBasicOutput 2 }
+
+
+-- the upsAdvOutput group
+
+upsAdvOutputVoltage OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output voltage of the UPS system in VAC."
+ ::= { upsAdvOutput 1 }
+
+upsAdvOutputFrequency OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current output frequency of the UPS system in Hz."
+ ::= { upsAdvOutput 2 }
+
+upsAdvOutputLoad OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current UPS load expressed in percent
+ of rated capacity."
+ ::= { upsAdvOutput 3 }
+
+upsAdvOutputCurrent OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current in amperes drawn by the load on the UPS."
+ ::= { upsAdvOutput 4 }
+
+
+-- the upsBasicConfig group
+
+upsBasicConfigNumDevices OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of devices that are plugged into the UPS."
+ ::= { upsBasicConfig 1 }
+
+upsBasicConfigDeviceTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsBasicConfigDeviceEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of devices that are plugged into the UPS.
+ The number of entries is given by the value of
+ upsBasicConfigNumDevices."
+ ::= { upsBasicConfig 2 }
+
+upsBasicConfigDeviceEntry OBJECT-TYPE
+ SYNTAX UpsBasicConfigDeviceEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The devices plugged in to the UPS."
+ INDEX { deviceIndex }
+ ::= { upsBasicConfigDeviceTable 1 }
+
+UpsBasicConfigDeviceEntry ::=
+ SEQUENCE {
+ deviceIndex
+ INTEGER,
+ deviceName
+ DisplayString,
+ vaRating
+ INTEGER,
+ acceptThisDevice
+ INTEGER
+ }
+
+deviceIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the device that is plugged into the UPS."
+ ::= { upsBasicConfigDeviceEntry 1 }
+
+deviceName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name/description of the device plugged into the UPS."
+ ::= { upsBasicConfigDeviceEntry 2 }
+
+vaRating OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The volt-amp rating of the device plugged into the UPS."
+ ::= { upsBasicConfigDeviceEntry 3 }
+
+acceptThisDevice OBJECT-TYPE
+ SYNTAX INTEGER {
+ yes(1),
+ no(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "An entry is added if yes, the entry is deleted if no."
+ ::= { upsBasicConfigDeviceEntry 4 }
+
+
+
+
+-- the upsAdvConfig group
+
+upsAdvConfigRatedOutputVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The nominal output voltage from the UPS in VAC.
+
+ For a list of allowed values supported by your UPS model,
+ see the UPS User's Manual.
+
+ If a value other than a supported value is provided in a
+ set request, the UPS interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+ ::= { upsAdvConfig 1 }
+
+upsAdvConfigHighTransferVolt OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum line voltage in VAC allowed before the
+ UPS system transfers to battery backup.
+
+ For a list of allowed values supported by your UPS model,
+ see the UPS User's Manual.
+
+ If a value other than a supported value is provided in a
+ set request, the UPS interprets it as a the next higher
+ acceptable value. If the provided value is higher than
+ the highest acceptable value, the highest acceptable
+ value is used."
+ ::= { upsAdvConfig 2 }
+
+upsAdvConfigLowTransferVolt OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum line voltage in VAC allowed before the
+ UPS system transfers to battery backup.
+
+ For a list of allowed values supported by your UPS model,
+ see the UPS User's Manual.
+
+ If a value other than a supported value is provided in a
+ set request, the UPS interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+ ::= { upsAdvConfig 3 }
+
+upsAdvConfigAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ timed(1),
+ atLowBattery(2),
+ never(3),
+ mute(4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A flag indicating how the UPS should handle audible
+ line fail alarms:
+ timed(1): UPS alarm will sound after a preset timed duration starting
+ from the line fail condition (see OID upsAdvConfigAlarmTimer for the
+ alarm timer value)
+ atLowBattery(2): UPS alarm will sound when the UPS has reached a Low
+ Battery condition during a line fail
+ never(3): Disables the UPS audible alarm
+ mute(4): Mutes the current alarm for some UPSs only when it is in an
+ alarm state and will return to the previously configured option when
+ the UPS recovers from the alarm condition"
+ ::= { upsAdvConfig 4 }
+
+upsAdvConfigAlarmTimer OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The time after initial line failure at which the UPS
+ begins emitting audible alarms (beeping). This timer is
+ observed only if the value of extControlAlarm is timed(2).
+ Allowed values are 0 or 30 seconds.
+
+ If a value other than a supported value is provided in a
+ set request, the UPS interprets it as a the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+ ::= { upsAdvConfig 5 }
+
+upsAdvConfigMinReturnCapacity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum battery capacity required before the UPS will
+ return from a low battery shutdown condition. The capacity is
+ measured from 0% battery capacity (or Low Battery) as a percent
+ of full capacity (100%). In other words, the UPS will not re-energize
+ the output until the battery has charged so that its' capacity is equal
+ to this value.
+
+ For a list of allowed values supported by your UPS model,
+ see the UPS User's Manual.
+
+ If a value other than a supported value is provided in a
+ set request, the UPS interprets it as a the next higher
+ acceptable value. If the provided value is higher than
+ the highest acceptable value, the highest acceptable
+ value is used."
+ ::= { upsAdvConfig 6 }
+
+upsAdvConfigSensitivity OBJECT-TYPE
+ SYNTAX INTEGER {
+ auto(1),
+ low(2),
+ medium(3),
+ high(4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The sensitivity of the UPS to utility line abnormalities
+ or noises."
+ ::= { upsAdvConfig 7 }
+
+upsAdvConfigLowBatteryRunTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The desired run time of the UPS, in seconds, once the
+ low battery condition is reached. During this time the UPS will
+ produce a constant warning tone which can not be disabled.
+
+ For a list of allowed values supported by your UPS model,
+ see the UPS User's Manual.
+
+ If a value other than a supported value is provided in a set
+ request, the UPS interprets the value as the next higher
+ acceptable value. If the provided value is higher than the
+ highest acceptable value, the highest acceptable value is used."
+ ::= { upsAdvConfig 8 }
+
+upsAdvConfigReturnDelay OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The delay in seconds after utility line power returns
+ before the UPS will turn on. This value is also used
+ when the UPS comes out of a reboot and before the UPS
+ wakes up from 'sleep' mode.
+
+ For a list of allowed values supported by your UPS model,
+ see the UPS User's Manual.
+
+ If a value other than a supported value is provided in a
+ set request, the UPS interprets it as a the next higher
+ acceptable value. If the provided value is higher than
+ the highest acceptable value, the highest acceptable
+ value is used."
+ ::= { upsAdvConfig 9 }
+
+upsAdvConfigShutoffDelay OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The delay in seconds the UPS remains on after being told
+ to turn off.
+
+ For a list of allowed values supported by your UPS model,
+ see the UPS User's Manual.
+
+ If a value other than a supported value is provided in a
+ set request, the UPS interprets it as a the next higher
+ acceptable value. If the provided value is higher than
+ the highest acceptable value, the highest acceptable
+ value is used."
+ ::= { upsAdvConfig 10 }
+
+upsAdvConfigUpsSleepTime OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The time in seconds for the UPS to go to 'sleep' when
+ instructed. When in sleep mode, the UPS will not provide
+ output power regardless of the input line state. Once the
+ specified time has elapsed, output power will be restored.
+
+ This is a configuration setting. The UPS will not go to
+ sleep until told to do so by the manager from a management
+ station.
+
+ Any input value is allowed, however the UPS only recognizes
+ 1/10 of an hour increments. The provided value will be
+ rounded to the closest 1/10 of an hour with one exception:
+ Any value entered between 1 and 540 seconds will be rounded
+ to 360 seconds (or 6 minutes)."
+ ::= { upsAdvConfig 11 }
+
+
+upsAdvConfigSetEEPROMDefaults OBJECT-TYPE
+ SYNTAX INTEGER {
+ noSetEEPROMDefaults(1),
+ setEEPROMDefaults(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "WRITE: Resets the UPS EEPROM variables to default values.
+ READ: returns 0"
+ ::= { upsAdvConfig 12 }
+
+upsAdvConfigDipSwitchSetting OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsAdvConfigDipSwitchEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Current settings of UPS dip switches."
+ ::= { upsAdvConfig 13 }
+
+upsAdvConfigDipSwitchEntry OBJECT-TYPE
+ SYNTAX UpsAdvConfigDipSwitchEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The current setting of one dip switch."
+ INDEX { dipSwitchIndex }
+ ::= { upsAdvConfigDipSwitchSetting 1 }
+
+UpsAdvConfigDipSwitchEntry ::=
+ SEQUENCE {
+ dipSwitchIndex
+ INTEGER,
+ dipSwitchStatus
+ INTEGER
+ }
+
+dipSwitchIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of a UPS dip switch."
+ ::= { upsAdvConfigDipSwitchEntry 1 }
+
+dipSwitchStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ on(1),
+ off(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The setting of a UPS dip switch."
+ ::= { upsAdvConfigDipSwitchEntry 2 }
+
+upsAdvConfigBattExhaustThresh OBJECT-TYPE
+ SYNTAX TimeTicks
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The number of seconds prior to battery exhaustion when the
+ UPS will switch off power to its load."
+ ::= { upsAdvConfig 14 }
+
+upsAdvConfigPassword OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The password entered at the UPS front panel to enable local
+ configuration of the EEProm. If the password is disabled or
+ is not supported, then the agent returns a null string."
+ ::= { upsAdvConfig 15 }
+
+upsAdvConfigAllowedSetTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ApcUpsConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The table listing the allowed values for all discrete
+ configurable UPS variables."
+ ::= { upsAdvConfig 16 }
+
+apcUpsConfigEntry OBJECT-TYPE
+ SYNTAX ApcUpsConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The table entry for a configurable UPS variable."
+ INDEX { apcUpsConfigFieldIndex }
+ ::= { upsAdvConfigAllowedSetTable 1 }
+
+ApcUpsConfigEntry ::= SEQUENCE {
+ apcUpsConfigFieldIndex INTEGER,
+ apcUpsConfigFieldOID OBJECT IDENTIFIER,
+ apcUpsConfigFieldValueRange DisplayString
+ }
+
+apcUpsConfigFieldIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to an eeprom field entry."
+ ::= { apcUpsConfigEntry 1 }
+
+apcUpsConfigFieldOID OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The OID of the current configurable value."
+ ::= { apcUpsConfigEntry 2 }
+
+apcUpsConfigFieldValueRange OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The discrete set of allowed values of a configurable
+ register. Individual values are delimited by a comma."
+ ::= { apcUpsConfigEntry 3 }
+
+upsAdvConfigBattCabAmpHour OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure settings of UPS battery cabinet amp hour setting."
+ ::= { upsAdvConfig 17 }
+
+upsAdvConfigPositionSelector OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ rack (2),
+ tower (3)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure UPS position selector. If the UPS doesn't
+ support this configuration it will report unknown (1).
+ The positions are either rack (2) for rack mounted or
+ tower (3) for tower unit."
+ ::= { upsAdvConfig 18 }
+
+upsAdvConfigOutputFreqRange OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ freqRangeAUTO (2),
+ freqRange60Var1 (3),
+ freqRange60Var3 (4),
+ freqRange50Var1 (5),
+ freqRange50Var3 (6),
+ freqRange60Var10 (7),
+ freqRange50Var10 (8)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure the output frequency tolerance range.
+ unknown(1) indicates the output frequency is unknown.
+ freqRangeAUTO(2) configure the output frequency range for automatic.
+ freqRange60Var1(3) configure the output frequency range for 60 +/- 0.1 Hz
+ freqRange60Var3(4) configure the output frequency range for 60 +/- 3.0 Hz
+ freqRange50Var1(5) configure the output frequency range for 50 +/- 0.1 Hz
+ freqRange50Var3(6) configure the output frequency range for 50 +/- 3.0 Hz
+ freqRange60Var10(7) configure the output frequency range for 60 +/- 10 Hz
+ freqRange50Var10(8) configure the output frequency range for 50 +/- 10 Hz"
+ ::= { upsAdvConfig 19 }
+
+upsAdvConfigUPSFail OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ gotoBypass (2),
+ dropLoad (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure the UPS fail action. If UPS fails,
+ and frequency or voltage is out of range it will either
+ GotoBypass (2) or DropLoad (3). This OID will report
+ unknown (1) if it is not supported feature or option."
+ ::= { upsAdvConfig 20 }
+
+upsAdvConfigAlarmRedundancy OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure settings of UPS alarm if the redundancy is
+ under the current redundancy. Use -1 for never."
+ ::= { upsAdvConfig 21 }
+
+upsAdvConfigAlarmLoadOver OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure settings of UPS alarm if the load is
+ over the current load in kVA. Use -1 for never."
+ ::= { upsAdvConfig 22 }
+
+upsAdvConfigAlarmRuntimeUnder OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure settings of UPS alarm if the runtime is
+ under the current time of minutes. Use -1 for never."
+ ::= { upsAdvConfig 23 }
+
+upsAdvConfigVoutReporting OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ voutAUTO (2),
+ vout208 (3),
+ vout240 (4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure the way the UPS scales its output voltage readings.
+ unknown(1) indicates the Vout Reporting is unknown.
+ voutAUTO(2) configure the Vout Reporting for automatic scalling.
+ vout208(3) configure the Vout Reporting for 208 Volts.
+ vout240(4) configure the Vout Reporting for 240 Volts."
+ ::= { upsAdvConfig 24 }
+
+upsAdvConfigNumExternalBatteries OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure the number of external batteries connected to the UPS."
+ ::= { upsAdvConfig 25 }
+
+upsAdvConfigSimpleSignalShutdowns OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ disabled (2),
+ enabled (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Configure Simple Signal shutdown commands from the Simple Signal
+ port to be issued to the UPS.
+ unknown(1) indicates the Simple Signal Shutdown setting is unknown.
+ disabled(2) configure to disable Simple Signal Shutdowns.
+ enabled(3) configure to enable Simple Signal Shutdowns."
+ ::= { upsAdvConfig 26 }
+
+
+-- the upsSyncCtrlGroupConfig group
+
+upsSCGMembershipGroupNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The SCG Membership Group number (MGN) is a 16-bit number allowing
+ up to 65534 separate groups that can be identified and distinguished
+ per IP subnet. Zero and 65535 are not used. The MGN is used in all
+ communication between members of the SCG and a Network Management Card
+ (NMC) will listen and only respond to commands sent to it using its
+ configured SCG ID."
+ ::= { upsSyncCtrlGroupConfig 1 }
+
+upsSCGActiveMembershipStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ enabledSCG (1),
+ disabledSCG (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Membership in the configured SCG can be enabled and
+ disabled. If an NMC is configured for an SCG, but
+ has its membership disabled, all synchronized control commands
+ received will be ignored."
+ ::= { upsSyncCtrlGroupConfig 2 }
+
+upsSCGPowerSynchronizationDelayTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The Power Synchronization Delay Time (PSD) setting is the maximum
+ number of seconds an SCG Initiator will wait for all SCG members to
+ recover utility power before completing the reboot sequence of a
+ reboot or sleep command. If all SCG members are ready to proceed,
+ no additional delay is introduced."
+ ::= { upsSyncCtrlGroupConfig 3 }
+
+upsSCGReturnBatteryCapacityOffset OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A reboot command uses the Initiator’s Return battery Capacity (RBC) to control
+ when the SCG completes this operation. In a Normal Control Operation (NCC) the
+ UPS will only complete the reboot if RBC is reached. Due to normal battery
+ charge rate variations it may be desirable for the Followers to complete the
+ reboot if they are within some range of the Initiator’s RBC when the Initiator
+ is prepared (charged to RBC) to complete the reboot. The Return Battery
+ Capacity Offset (RBCO) defines a percent battery capacity subtracted from an
+ RBC above which a Follower’s battery must be charged for it to complete a
+ reboot. For example, if the Initiator’s RBC is 50% and the Initiator’s RBCO is
+ 5% then a Follower’s battery capacity is within range if it is greater or equal
+ to 45% (50% - 5%) at the time when the Initiator tries to complete the reboot
+ command. The default RBCO is 10%. "
+ ::= { upsSyncCtrlGroupConfig 4 }
+
+upsSCGMultiCastIP OBJECT-TYPE
+ SYNTAX IpAddress
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The MultiCast IP address of the SCG Group."
+ ::= { upsSyncCtrlGroupConfig 5 }
+
+-- the upsSyncCtrlGroupStatus group
+
+upsSCGNumOfGroupMembers OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of active, communicating members in the Sync Control Group (SCG).
+ This variable indicates the number of rows in the SCG Status Table."
+ ::= { upsSyncCtrlGroupStatus 1 }
+
+-- Sync Control Group Status Table
+
+upsSCGStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsSCGStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of SCG status table entries. The number of entries
+ is given by the value of upsSCGNumOfGroupMembers."
+ ::= { upsSyncCtrlGroupStatus 2 }
+
+ upsSCGStatusEntry OBJECT-TYPE
+ SYNTAX UpsSCGStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular SCG Member."
+ INDEX { upsSCGStatusTableIndex }
+ ::= { upsSCGStatusTable 1 }
+
+ UpsSCGStatusEntry ::= SEQUENCE {
+ upsSCGStatusTableIndex INTEGER,
+ upsSCGMemberIP IpAddress,
+ upsSCGACInputStatus INTEGER,
+ upsSCGACOutputStatus INTEGER
+ }
+
+ upsSCGStatusTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of a status entry for an active, communicating SCG member."
+ ::= { upsSCGStatusEntry 1 }
+
+ upsSCGMemberIP OBJECT-TYPE
+ SYNTAX IpAddress
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The IP address of an active, communicating SCG Member."
+ ::= { upsSCGStatusEntry 2 }
+
+ upsSCGACInputStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ acInGood(1),
+ acInBad(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID indicates the AC Input Status of the SCG Member.
+ acInGood(1) indicates the AC Input is within tolerance.
+ acInBad(2) indicates the AC Input is not within tolerance."
+ ::= { upsSCGStatusEntry 3 }
+
+ upsSCGACOutputStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ acOutOn(1),
+ acOutOff(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID indicates the AC Output Status of the SCG Member.
+ acOutOn(1) indicates the UPS output is providing power to the load.
+ acOutOff(2) indicates the UPS output is not providing power to the load. "
+ ::= { upsSCGStatusEntry 4 }
+
+-- the upsBasicState group
+
+upsBasicStateOutputState OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ASCII string containing the 64 flags representing
+ the current state(s) of the UPS. If the Network Card
+ is unable to determine the state of the UPS, this
+ variable is set to ‘UNKNOWN’.
+
+ The flags are numbered 1 to 64, read from left to
+ right. The flags are defined as follows:
+
+ Flag 1: Abnormal Condition Present
+ Flag 2: On Battery
+ Flag 3: Low Battery
+ Flag 4: On Line
+
+ Flag 5: Replace Battery
+ Flag 6: Serial Communication Established
+ Flag 7: AVR Boost Active*
+ Flag 8: AVR Trim Active*
+
+ Flag 9: Overload
+ Flag 10: Runtime Calibration
+ Flag 11: Batteries Discharged
+ Flag 12: Manual Bypass
+
+ Flag 13: Software Bypass
+ Flag 14: In Bypass due to Internal Fault
+ Flag 15: In Bypass due to Supply Failure*
+ Flag 16: In Bypass due to Fan Failure*
+
+ Flag 17: Sleeping on a Timer
+ Flag 18: Sleeping until Utility Power Returns
+ Flag 19: On
+ Flag 20: Rebooting
+
+ Flag 21: Battery Communication Lost*
+ Flag 22: Graceful Shutdown Initiated
+ Flag 23: Smart Boost or Smart Trim Fault*
+ Flag 24: Bad Output Voltage*
+
+ Flag 25: Battery Charger Failure*
+ Flag 26: High Battery Temperature
+ Flag 27: Self Test In Progress
+ Flag 28: Low Battery / On Battery
+
+ Flag 29: Graceful Shutdown Issued by Upstream Device
+ Flag 30: Graceful Shutdown Issued by Downstream Device
+ Flag 31: No Batteries Attached*
+ Flag 32: Synchronized command is in progress
+
+ Flag 33: <Not Used>
+ Flag 34: <Not Used>
+ Flag 35: <Not Used>
+ Flag 36: <Not Used>
+
+ Flag 37: <Not Used>
+ Flag 38: <Not Used>
+ Flag 39: <Not Used>
+ Flag 40: <Not Used>
+
+ Flag 41: <Not Used>
+ Flag 42: <Not Used>
+ Flag 43: <Not Used>
+ Flag 44: <Not Used>
+
+ Flag 45: <Not Used>
+ Flag 46: <Not Used>
+ Flag 47: <Not Used>
+ Flag 48: <Not Used>
+
+ Flag 49: <Not Used>
+ Flag 50: <Not Used>
+ Flag 51: <Not Used>
+ Flag 52: <Not Used>
+
+ Flag 53: <Not Used>
+ Flag 54: <Not Used>
+ Flag 55: <Not Used>
+ Flag 56: <Not Used>
+
+ Flag 57: <Not Used>
+ Flag 58: <Not Used>
+ Flag 59: <Not Used>
+ Flag 60: <Not Used>
+
+ Flag 61: <Not Used>
+ Flag 62: <Not Used>
+ Flag 63: <Not Used>
+ Flag 64: <Not Used>"
+
+ ::= { upsBasicState 1 }
+
+-- the upsAdvState group
+
+upsAdvStateAbnormalConditions OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ASCII string containing the 32 flags representing
+ the current active UPS faults. If the Network Card
+ is unable to determine the values of the flags, this
+ variable is set to ‘UNKNOWN’. If this variable is not
+ supported by the connected UPS, this variable is set to
+ ‘NOT SUPPORTED’.
+
+ The flags are numbered from 1 to 32, and read from left to
+ right. The flags are defined as follows:
+
+ Flag 1: Power Module Failure
+ Flag 2: Main Intelligence Module Failure
+ Flag 3: Redundant Intelligence Module Failure
+ Flag 4: Battery Failure
+
+ Flag 5: Load(kVA) Alarm Threshold Violation
+ Flag 6: Redundancy Lost
+ Flag 7: Redundancy Below Alarm Threshold
+ Flag 8: Bypass notin Range; Either Frequency or Voltage
+
+ Flag 9: Bypass Contactor Stuck in Bypass Condition
+ Flag 10: Bypass Contactor Stuck in On-Line Condition
+ Flag 11: In Bypass due to an Internal Fault
+ Flag 12: In Bypass due to an Overload
+
+ Flag 13: In Maintanence Bypass
+ Flag 14: Input Circuit Braker Tripped Open
+ Flag 15: System Level Fan Failure
+ Flag 16: Redundant Intelligent Module in Control
+
+ Flag 17: IIC Inter-Module Communication Failure
+ Flag 18: No Working Power Modules
+ Flag 19: Load Shutdown From Bypass; Input Frequency
+ Flag 20: Runtime Below Alarm Threshold
+
+ Flag 21: Extended Run Frame Fault
+ Flag 22: Output Voltage out of Range
+ Flag 23: UPS Not Synchronized
+ Flag 24: No Batteries Installed
+
+ Flag 25: Battery Voltage High
+ Flag 26: UPS Specific Fault Detected
+ Flag 27: Site Wiring Fault
+ Flag 28: Backfeed Protection Relay Opened
+
+ Flag 29: <Not Used>
+ Flag 30: <Not Used>
+ Flag 31: <Not Used>
+ Flag 32: <Not Used>"
+ ::= { upsAdvState 1 }
+
+upsAdvStateSymmetra3PhaseSpecificFaults OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ASCII string containing the 64 flags representing
+ the current active UPS specific faults for the Symmetra
+ 3-Phase UPS models. If the Network Card is unable to
+ determine the values of the flags, this variable is set
+ to ‘UNKNOWN’. If the connected UPS does not use this
+ variable, it is set to ‘NOT SUPPORTED’.
+
+ The flags are numbered from 1 to 64, and read from left
+ to right. The bits are defined as follows:
+
+ Flag 1: External Switch Gear Failure
+ Flag 2: External Transformer Over Temperature
+ Flag 3: External DC Circuit Breaker Tripped
+ Flag 4: System Power Supply Failure
+
+ Flag 5: Battery Monitor Card Failure
+ Flag 6: Battery Monitor Card Removed
+ Flag 7: XR Communication Card Failure
+ Flag 8: XR Communication Card Removed
+
+ Flag 9: External Switch Gear Monitoring Card Failure
+ Flag 10: External Switch Gear Monitoring Card Removed
+ Flag 11: Internal DC Circiut Breaker Tripped
+ Flag 12: Static Bypass Switch Failure
+
+ Flag 13: System EEPROM Removed
+ Flag 14: System EEPROM Failure
+ Flag 15: UPS in Forced Bypass
+ Flag 16: <Not Used>
+
+ Flag 17: <Not Used>
+ Flag 18: <Not Used>
+ Flag 19: <Not Used>
+ Flag 20: <Not Used>
+
+ Flag 21: <Not Used>
+ Flag 22: <Not Used>
+ Flag 23: <Not Used>
+ Flag 24: <Not Used>
+
+ Flag 25: <Not Used>
+ Flag 26: <Not Used>
+ Flag 27: <Not Used>
+ Flag 28: <Not Used>
+
+ Flag 29: <Not Used>
+ Flag 30: <Not Used>
+ Flag 31: <Not Used>
+ Flag 32: <Not Used>
+
+ Flag 33: <Not Used>
+ Flag 34: <Not Used>
+ Flag 35: <Not Used>
+ Flag 36: <Not Used>
+
+ Flag 37: <Not Used>
+ Flag 38: <Not Used>
+ Flag 39: <Not Used>
+ Flag 40: <Not Used>
+
+ Flag 41: <Not Used>
+ Flag 42: <Not Used>
+ Flag 43: <Not Used>
+ Flag 44: <Not Used>
+
+ Flag 45: <Not Used>
+ Flag 46: <Not Used>
+ Flag 47: <Not Used>
+ Flag 48: <Not Used>
+
+ Flag 49: <Not Used>
+ Flag 50: <Not Used>
+ Flag 51: <Not Used>
+ Flag 52: <Not Used>
+
+ Flag 53: <Not Used>
+ Flag 54: <Not Used>
+ Flag 55: <Not Used>
+ Flag 56: <Not Used>
+
+ Flag 57: <Not Used>
+ Flag 58: <Not Used>
+ Flag 59: <Not Used>
+ Flag 60: <Not Used>
+
+ Flag 61: <Not Used>
+ Flag 62: <Not Used>
+ Flag 63: <Not Used>
+ Flag 64: <Not Used>"
+ ::= { upsAdvState 2 }
+
+upsAdvStateDP300ESpecificFaults OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ASCII string containing the 64 flags representing
+ the current active UPS specific faults for the Silcon
+ DP300E UPS models. If the Network Card is unable to
+ determine the values of the flags, this variable is set
+ to ‘UNKNOWN’. If the connected UPS does not use this
+ variable, it is set to ‘NOT SUPPORTED’.
+
+ The flags are numbered from 1 to 64, and read from left
+ to right. The bits are defined as follows:
+
+ Flag 1: Peak Current Limiter Avtive
+ Flag 2: Bypass Power Supply Fault
+ Flag 3: Delta Current LImiter Active
+ Flag 4: Fan Fault
+
+ Flag 5: High DC warning
+ Flag 6: Inverter Voltage Error
+ Flag 7: Parallel Synchronization Error
+ Flag 8: Second Power Supply Fault
+
+ Flag 9: Internal Power Supply Fault
+ Flag 10: <Not Used>
+ Flag 11: <Not Used>
+ Flag 12: <Not Used>
+
+ Flag 13: <Not Used>
+ Flag 14: Bypass Static Switch High Temperature
+ Flag 15: High Battery Temperature
+ Flag 16: Battery Weak
+
+ Flag 17: <Not Used>
+ Flag 18: System Locked in Operation Mode
+ Flag 19: RAM1 Memory Write Error
+ Flag 20: Memory Write Error
+
+ Flag 21: Communication to VQ Bypass Lost
+ Flag 22: Communication to VQ Output Lost
+ Flag 23: Communication to DMU Lost
+ Flag 24: Communication to Controller Lost
+
+ Flag 25: Communication to Parallel IF Lost
+ Flag 26: External Shutdown Accepted
+ Flag 27: DC Capacitor Charge Error
+ Flag 28: Communication to VQ Mains Lost
+
+ Flag 29: Bypass Synchronization Error
+ Flag 30: Charge Error
+ Flag 31: <Not Used>
+ Flag 32: <Not Used>
+
+ Flag 33: <Not Used>
+ Flag 34: <Not Used>
+ Flag 35: <Not Used>
+ Flag 36: <Not Used>
+
+ Flag 37: <Not Used>
+ Flag 38: <Not Used>
+ Flag 39: <Not Used>
+ Flag 40: <Not Used>
+
+ Flag 41: <Not Used>
+ Flag 42: <Not Used>
+ Flag 43: <Not Used>
+ Flag 44: <Not Used>
+
+ Flag 45: <Not Used>
+ Flag 46: <Not Used>
+ Flag 47: <Not Used>
+ Flag 48: <Not Used>
+
+ Flag 49: <Not Used>
+ Flag 50: <Not Used>
+ Flag 51: <Not Used>
+ Flag 52: <Not Used>
+
+ Flag 53: <Not Used>
+ Flag 54: <Not Used>
+ Flag 55: <Not Used>
+ Flag 56: <Not Used>
+
+ Flag 57: <Not Used>
+ Flag 58: <Not Used>
+ Flag 59: <Not Used>
+ Flag 60: <Not Used>
+
+ Flag 61: <Not Used>
+ Flag 62: <Not Used>
+ Flag 63: <Not Used>
+ Flag 64: <Not Used>"
+ ::= { upsAdvState 3 }
+
+
+-- the upsBasicControl group
+
+upsBasicControlConserveBattery OBJECT-TYPE
+ SYNTAX INTEGER {
+ noTurnOffUps(1),
+ turnOffUpsToConserveBattery(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to turnUpsOffToConserveBattery(2)
+ causes a UPS on battery to be put into 'sleep' mode. The
+ UPS will turn back on when utility power is restored.
+ Attempting to turn off a UPS that is not on battery will
+ result in a badValue error.
+
+ Setting this value to noTurnOffUps(1) has no
+ effect.
+
+ The value noTurnOffUps(1) will always be returned
+ when the variable is read."
+::= { upsBasicControl 1 }
+
+
+
+-- the upsAdvControl group
+
+upsAdvControlUpsOff OBJECT-TYPE
+ SYNTAX INTEGER {
+ noTurnUpsOff(1),
+ turnUpsOff(2),
+ turnUpsOffGracefully(3),
+ turnUpsSyncGroupOff(4),
+ turnUpsSyncGroupOffAfterDelay(5),
+ turnUpsSyncGroupOffGracefully(6)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to turnUpsOff(2) causes
+ the UPS to shut off. When in this state, the UPS
+ will not provide output power regardless of the input
+ line state.
+
+ Setting this variable to turnUpsOffGracefully(3) causes
+ the UPS to shut off after a delay period. This allows the
+ host to shut down in a graceful manner. When in this state,
+ the UPS will not provide output power regardless of the
+ input line state.
+
+ If this UPS is an active member of a Synchronized
+ Control Group (SCG) the turnUpsSyncGroupOff(4) command
+ will perform a Synchronized Turn Off of all active Group
+ members regardless of their current AC output status.
+
+ If this UPS is an active member of a Synchronized
+ Control Group (SCG) the turnUpsSyncGroupOffAfterDelay(5)
+ command will perform a Synchronized Turn Off After Delay
+ of all active Group members regardless of their current
+ AC output status. This unit's Shutdown Delay will be used
+ to execute the Turn Off After Delay command.
+
+ If this UPS is an active member of an SCG, the
+ turnUpsSyncGroupOffGracefully(6) command will perform a
+ Synchronized Turn Off Gracefully of all active Group
+ members regardless of their current AC output status.
+ This unit's Maximum Shutdown Time and Shutdown Delay will
+ be used to execute the Turn Off Gracefully command.
+
+ Setting this value to noTurnUpsOff(1) has no
+ effect.
+
+ The value noTurnUpsOff(1) will always be returned
+ when the variable is read."
+ ::= { upsAdvControl 1 }
+
+upsAdvControlRebootUps OBJECT-TYPE
+ SYNTAX INTEGER {
+ noRebootUps(1),
+ rebootUps(2),
+ rebootUpsGracefully(3),
+ rebootSyncGroupUps(4),
+ rebootSyncGroupUpsGracefully(5)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to rebootUps(2) causes the
+ UPS to shut off and turn back on.
+
+ Setting this variable to rebootUpsGracefully(3) causes the
+ UPS to shut off and turn back on after a delay period.
+ This allows the host to shut down in a graceful manner.
+
+ If this UPS is an active member of a Synchronized Control
+ Group (SCG) the rebootSyncGroupUps(4) command will perform
+ a Synchronized Reboot of all active Group members regardless
+ of their current AC output status. This unit's Power
+ Synchronization Delay, Shutdown Delay, Return Delay,
+ Return Battery Capacity, and Return Battery Capacity Offset
+ will be used to execute the Reboot command.
+
+ If this UPS is an active member of a SCG the
+ rebootSyncGroupUpsGracefully(5) command will perform a
+ Synchronized Reboot of all active Group members regardless
+ of their current AC output status. This unit's Power
+ Synchronization Delay, Maximum Shutdown Time,
+ Shutdown Delay, Return Delay, Return Battery Capacity, and
+ Return Battery Capacity Offset will be used
+ to execute the Reboot command.
+
+ Setting this value to noRebootUps(1) has no effect.
+
+ The value noRebootUps(1) will always be returned
+ when the variable is read."
+ ::= { upsAdvControl 2 }
+
+upsAdvControlUpsSleep OBJECT-TYPE
+ SYNTAX INTEGER {
+ noPutUpsToSleep(1),
+ putUpsToSleep(2),
+ putUpsToSleepGracefully(3),
+ putUpsSyncGroupToSleep(4),
+ putUpsSyncGroupToSleepGracefully(5)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to putUpsToSleep(2) causes
+ the UPS to go to sleep for the time specified by
+ upsAdvConfigUpsSleepTime.
+
+ Setting this variable to putUpsToSleepGracefully(3)
+ causes the UPS to go to sleep for the time specified
+ by upsAdvConfigUpsSleepTime after a delay period.
+ This allows the host to shut down in a graceful manner.
+
+ If this UPS is an active member of a Synchronized Control
+ Group (SCG), the putUpsSyncGroupToSleep(4) command will perform
+ a Synchronized Sleep of all active Group members regardless
+ of their current AC output status. This unit's Power
+ Synchronization Delay, Shutdown Delay, Sleep Time,
+ and Return Delay will be used to execute the sleep command.
+
+ If this UPS is an active member of a SCG the
+ putUpsSyncGroupToSleepGracefully(5) command will perform a
+ Synchronized Sleep Gracefully of all active Group members
+ regardless of their current AC output status. This unit's
+ Power Synchronization Delay, Maximum Shutdown Time, Shutdown
+ Delay, Sleep Time, and Return Delay to execute the sleep
+ command.
+
+ When in sleep mode, the UPS will not provide output
+ power regardless of the input line state. Once the
+ specified time has elapsed, output power will be
+ restored.
+
+ Setting this value to noPutUpsToSleep(1) has no
+ effect.
+
+ The value noPutUpsToSleep(1) will always be returned
+ when the variable is read."
+ ::= { upsAdvControl 3 }
+
+
+upsAdvControlSimulatePowerFail OBJECT-TYPE
+ SYNTAX INTEGER {
+ noSimulatePowerFailure(1),
+ simulatePowerFailure(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to simulatePowerFailure(2) causes
+ the UPS switch to battery power.
+
+ Setting this value to noSimulatePowerFailure(1) has no
+ effect.
+
+ The value noSimulatePowerFailure(1) will always be returned
+ when the variable is read."
+ ::= { upsAdvControl 4 }
+
+
+upsAdvControlFlashAndBeep OBJECT-TYPE
+ SYNTAX INTEGER {
+ noFlashAndBeep(1),
+ flashAndBeep(2),
+ flashAndBeepSyncGroup(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to flashAndBeep(2) causes the
+ UPS to beep and simultaneously turn on the UPS front
+ panel lights (Smart-UPS only).
+
+ If this UPS is an active member of a Synchronized Control
+ Group (SCG), the flashAndBeepSyncGroup(3) command will
+ Flash and Beep all active Group members regardless of
+ current AC output status.
+
+ Setting this value to noFlashAndBeep(1) has no
+ effect.
+
+ The value noFlashAndBeep(1) will always be returned
+ when the variable is read."
+ ::= { upsAdvControl 5 }
+
+
+upsAdvControlTurnOnUPS OBJECT-TYPE
+ SYNTAX INTEGER {
+ noTurnOnUPS(1),
+ turnOnUPS(2),
+ turnOnUPSSyncGroup(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to turnOnUPS(2) causes the
+ UPS to be turned on immediately.
+
+ If this UPS is an active member of a Synchronized Control
+ Group (SCG), the turnOnUPSSyncGroup(3) command will perform
+ a Synchronized Turn On of all active Group members
+ regardless of their current AC output status.
+
+ Setting this value to noTurnOnUPS(1) has no
+ effect.
+
+ The value noTurnOnUPS(1) will always be returned
+ when the variable is read."
+ ::= { upsAdvControl 6 }
+
+upsAdvControlBypassSwitch OBJECT-TYPE
+ SYNTAX INTEGER {
+ noBypassSwitch (1),
+ switchToBypass (2),
+ switchOutOfBypass(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This switch puts the UPS in or out of bypass mode."
+ ::= { upsAdvControl 7 }
+
+
+-- the upsTest group
+
+-- the upsBasicTest group
+
+-- the upsAdvTest group
+
+upsAdvTestDiagnosticSchedule OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ biweekly(2),
+ weekly(3),
+ atTurnOn(4),
+ never(5)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The UPS system's automatic battery test schedule."
+ ::= { upsAdvTest 1 }
+
+
+upsAdvTestDiagnostics OBJECT-TYPE
+ SYNTAX INTEGER {
+ noTestDiagnostics(1),
+ testDiagnostics(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to testDiagnostics(2) causes
+ the UPS to perform a diagnostic self test.
+
+ Setting this value to noTestDiagnostics(1) has no
+ effect.
+
+ The value noTestDiagnostics(1) will always be returned
+ when the variable is read."
+ ::= { upsAdvTest 2 }
+
+upsAdvTestDiagnosticsResults OBJECT-TYPE
+ SYNTAX INTEGER {
+ ok(1),
+ failed(2),
+ invalidTest(3),
+ testInProgress(4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The results of the last UPS diagnostics test performed."
+ ::= { upsAdvTest 3 }
+
+upsAdvTestLastDiagnosticsDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date the last UPS diagnostics test was performed in
+ mm/dd/yy format."
+ ::= { upsAdvTest 4 }
+
+upsAdvTestRuntimeCalibration OBJECT-TYPE
+ SYNTAX INTEGER {
+ noPerformCalibration(1),
+ performCalibration(2),
+ cancelCurrentCalibration(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to performCalibration(2) causes
+ the UPS to discharge to calibrate the UPS.
+ The test will only start if the battery capacity is 100%.
+ The test runs until capacity is less than 25%.
+
+ Setting this variable to cancelCurrentCalibration(3)
+ after setting performCalibration(2) will cancel the
+ current discharge.
+
+ Setting this variable to noPerformCalibration(1)
+ will have no effect.
+
+ The value noPerformCalibration(1) will always be returned
+ when the variable is read.
+
+ The result of the calibration will be saved in
+ upsAdvTestCalibrationResult."
+ ::= { upsAdvTest 5 }
+
+upsAdvTestCalibrationResults OBJECT-TYPE
+ SYNTAX INTEGER {
+ ok(1),
+ invalidCalibration(2),
+ calibrationInProgress(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The results of the last runtime calibration.
+
+ Value ok(1) means a successful runtime calibration.
+
+ Value invalidCalibration(2) indicates last calibration did
+ not take place since the battery capacity was below
+ 100%.
+
+ Value calibrationInProgress(3) means a calibration
+ is occurring now. "
+ ::= { upsAdvTest 6 }
+
+upsAdvTestCalibrationDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date the last UPS runtime calibration was
+ performed in mm/dd/yy format."
+ ::= { upsAdvTest 7 }
+
+-- the upsComm group
+
+upsCommStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ ok(1),
+ noComm(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of agent's communication with UPS. "
+ ::= { upsComm 1 }
+
+
+-- the measureUps group
+-- the Environ group
+
+mUpsEnvironAmbientTemperature OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The ambient temperature in Celsius for Probe 1."
+ ::= { mUpsEnviron 1 }
+
+mUpsEnvironRelativeHumidity OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The relative humidity as a percentage for Probe 1."
+ ::= { mUpsEnviron 2 }
+
+
+mUpsEnvironAmbientTemperature2 OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The ambient temperature in Celsius for Probe 2."
+ ::= { mUpsEnviron 3 }
+
+mUpsEnvironRelativeHumidity2 OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The relative humidity as a percentage for Probe 2."
+ ::= { mUpsEnviron 4 }
+
+-- the mUpsContact group
+
+mUpsContactNumContacts OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of contacts supported by the Measure-UPS."
+ ::= { mUpsContact 1 }
+
+mUpsContactTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ContactEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of contacts supported by the Measure-UPS."
+ ::= { mUpsContact 2 }
+
+mUpsContactEntry OBJECT-TYPE
+ SYNTAX ContactEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A contact entry containing information for a given contact."
+ INDEX { contactNumber }
+ ::= { mUpsContactTable 1 }
+
+ContactEntry ::=
+ SEQUENCE {
+ contactNumber
+ INTEGER,
+ normalState
+ INTEGER,
+ description
+ DisplayString,
+ monitoringStatus
+ INTEGER,
+ currentStatus
+ INTEGER
+ }
+
+contactNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An index identifying the contact on the Measure-UPS."
+ ::= { mUpsContactEntry 1 }
+
+normalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ open(2),
+ closed(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The normal operating position of the contact. If the normal
+ operating position cannot be set then it is controlled via the
+ dip switch on the Measure-UPS and is therefore read-only."
+ ::= { mUpsContactEntry 2 }
+
+description OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The description of the purpose/use of the contact."
+ ::= { mUpsContactEntry 3 }
+
+monitoringStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ enabled(2),
+ disabled(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A flag indicating whether this contact is
+ monitored, or not."
+ ::= { mUpsContactEntry 4 }
+
+currentStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ noFault(2),
+ fault(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This value indicates the current state of the contact.
+ If the contact is not in its normal state. This value
+ is set to fault(2)."
+ ::= { mUpsContactEntry 5 }
+
+-- Three Phase Group
+
+--
+-- Reset Max/Min Values Group
+--
+
+ upsPhaseResetMaxMinValues OBJECT-TYPE
+ SYNTAX INTEGER {
+ none (1),
+ reset (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Reset the maximum and minimum UPS values:
+ upsPhaseInputMaxVoltage, upsPhaseInputMinVoltage,
+ upsPhaseInputMaxCurrent, upsPhaseInputMinCurrent,
+ upsPhaseInputMaxPower, upsPhaseInputMinPower,
+ upsPhaseOutputMaxCurrent, upsPhaseOutputMinCurrent,
+ upsPhaseOutputMaxLoad, upsPhaseOutputMinLoad,
+ upsPhaseOutputMaxPercentLoad, upsPhaseOutputMinPercentLoad,
+ upsPhaseOutputMaxPower, upsPhaseOutputMinPower,
+ upsPhaseOutputMaxPercentPower, upsPhaseOutputMinPercentPower."
+ ::= { upsPhaseResetValues 1 }
+
+--
+-- Input Group
+--
+
+-- Number of Inputs
+
+ upsPhaseNumInputs OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input feeds to this device.
+ This variable indicates the number of rows in the
+ input table."
+ ::= { upsPhaseInput 1 }
+
+-- Input Table
+
+ upsPhaseInputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsPhaseInputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of input table entries. The number of entries
+ is given by the value of upsPhaseNumInputs."
+ ::= { upsPhaseInput 2 }
+
+ upsPhaseInputEntry OBJECT-TYPE
+ SYNTAX UpsPhaseInputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular input."
+ INDEX { upsPhaseInputTableIndex }
+ ::= { upsPhaseInputTable 1 }
+
+ UpsPhaseInputEntry ::= SEQUENCE {
+ upsPhaseInputTableIndex INTEGER,
+ upsPhaseNumInputPhases INTEGER,
+ upsPhaseInputVoltageOrientation INTEGER,
+ upsPhaseInputFrequency INTEGER,
+ upsPhaseInputType INTEGER,
+ upsPhaseInputName DisplayString
+ }
+
+ upsPhaseInputTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input identifier."
+ ::= { upsPhaseInputEntry 1 }
+
+ upsPhaseNumInputPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input phases utilized in this
+ device. The sum of all the upsPhaseNumInputPhases
+ variable indicates the number of rows in the
+ input phase table."
+ ::= { upsPhaseInputEntry 2 }
+
+ upsPhaseInputVoltageOrientation OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ singlePhase(2),
+ splitPhase(3),
+ threePhasePhaseToNeutral(4),
+ threePhasePhaseToPhase(5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input voltage orientation:
+ 1: unknown for this UPS
+ 2: singlePhase - phase 1 voltage is between Phase 1
+ and Neutral.
+ 3: splitPhase - phase 1 voltage is between Phase 1 and
+ Neutral; phase 2 voltage is between Phase 2 and Neutral;
+ phase 3 voltage is between Phase 1 and Phase2.
+ 4: threePhasePhaseToNeutral - phase 1 voltage is between
+ Phase 1 and Neutral; phase 2 voltage is between Phase 2
+ and Neutral; phase 3 voltage is between Phase3 and
+ Neutral.
+ 5: threePhasePhaseToPhase - phase 1 voltage is between
+ Phase 1 and Phase 2; phase 2 voltage is between Phase 2
+ and Phase 3; phase 3 voltage is between Phase 3 and
+ Phase 1."
+ ::= { upsPhaseInputEntry 3 }
+
+ upsPhaseInputFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input frequency in 0.1 Hertz, or -1 if it's unsupported
+ by this UPS."
+ ::= { upsPhaseInputEntry 4 }
+
+ upsPhaseInputType OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ main(2),
+ bypass(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input type."
+ ::= { upsPhaseInputEntry 5 }
+
+ upsPhaseInputName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A name given to a particular input."
+ ::= { upsPhaseInputEntry 6 }
+
+-- Input Phase Table
+
+ upsPhaseInputPhaseTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsPhaseInputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of input table entries. The number of entries
+ is given by the sum of the upsPhaseNumInputPhases."
+ ::= { upsPhaseInput 3 }
+
+ upsPhaseInputPhaseEntry OBJECT-TYPE
+ SYNTAX UpsPhaseInputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular input phase."
+ INDEX { upsPhaseInputPhaseTableIndex, upsPhaseInputPhaseIndex }
+ ::= { upsPhaseInputPhaseTable 1 }
+
+ UpsPhaseInputPhaseEntry ::= SEQUENCE {
+ upsPhaseInputPhaseTableIndex INTEGER,
+ upsPhaseInputPhaseIndex INTEGER,
+ upsPhaseInputVoltage INTEGER,
+ upsPhaseInputMaxVoltage INTEGER,
+ upsPhaseInputMinVoltage INTEGER,
+ upsPhaseInputCurrent INTEGER,
+ upsPhaseInputMaxCurrent INTEGER,
+ upsPhaseInputMinCurrent INTEGER,
+ upsPhaseInputPower INTEGER,
+ upsPhaseInputMaxPower INTEGER,
+ upsPhaseInputMinPower INTEGER
+ }
+
+ upsPhaseInputPhaseTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input identifier."
+ ::= { upsPhaseInputPhaseEntry 1 }
+
+ upsPhaseInputPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input phase identifier."
+ ::= { upsPhaseInputPhaseEntry 2 }
+
+ upsPhaseInputVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input voltage in VAC, or -1 if it's unsupported
+ by this UPS."
+ ::= { upsPhaseInputPhaseEntry 3 }
+
+ upsPhaseInputMaxVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum input voltage in VAC measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseInputPhaseEntry 4 }
+
+ upsPhaseInputMinVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum input voltage in VAC measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseInputPhaseEntry 5 }
+
+ upsPhaseInputCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input current in 0.1 amperes, or -1 if it's
+ unsupported by this UPS."
+ ::= { upsPhaseInputPhaseEntry 6 }
+
+ upsPhaseInputMaxCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum input current in 0.1 amperes measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseInputPhaseEntry 7 }
+
+ upsPhaseInputMinCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum input current in 0.1 amperes measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseInputPhaseEntry 8 }
+
+ upsPhaseInputPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input power in Watts, or -1 if it's unsupported
+ by this UPS."
+ ::= { upsPhaseInputPhaseEntry 9 }
+
+ upsPhaseInputMaxPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum input power in Watts measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseInputPhaseEntry 10 }
+
+ upsPhaseInputMinPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum input power in Watts measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseInputPhaseEntry 11 }
+
+ --
+ -- The Output group.
+ --
+
+ -- Number of Outputs
+
+ upsPhaseNumOutputs OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output feeds to this device.
+ This variable indicates the number of rows in the
+ output table."
+ ::= { upsPhaseOutput 1 }
+
+ -- Output Table
+
+ upsPhaseOutputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsPhaseOutputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output table entries. The number of entries
+ is given by the value of upsOutputNumPhases."
+ ::= { upsPhaseOutput 2 }
+
+ upsPhaseOutputEntry OBJECT-TYPE
+ SYNTAX UpsPhaseOutputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular output."
+ INDEX { upsPhaseOutputTableIndex }
+ ::= { upsPhaseOutputTable 1 }
+
+ UpsPhaseOutputEntry ::= SEQUENCE {
+ upsPhaseOutputTableIndex INTEGER,
+ upsPhaseNumOutputPhases INTEGER,
+ upsPhaseOutputVoltageOrientation INTEGER,
+ upsPhaseOutputFrequency INTEGER
+ }
+
+ upsPhaseOutputTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output identifier."
+ ::= { upsPhaseOutputEntry 1 }
+
+ upsPhaseNumOutputPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output phases utilized in this
+ device. The sum of all the upsPhaseNumOutputPhases
+ variable indicates the number of rows in the
+ output phase table."
+ ::= { upsPhaseOutputEntry 2 }
+
+ upsPhaseOutputVoltageOrientation OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ singlePhase(2),
+ splitPhase(3),
+ threePhasePhaseToNeutral(4),
+ threePhasePhaseToPhase(5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output voltage orientation:
+ 1: unknown for this UPS
+ 2: singlePhase - phase 1 voltage is between Phase 1
+ and Neutral.
+ 3: splitPhase - phase 1 voltage is between Phase 1 and
+ Neutral; phase 2 voltage is between Phase 2 and Neutral;
+ phase 3 voltage is between Phase 1 and Phase2.
+ 4: threePhasePhaseToNeutral - phase 1 voltage is between
+ Phase 1 and Neutral; phase 2 voltage is between Phase 2
+ and Neutral; phase 3 voltage is between Phase3 and
+ Neutral.
+ 5: threePhasePhaseToPhase - phase 1 voltage is between
+ Phase 1 and Phase 2; phase 2 voltage is between Phase 2
+ and Phase 3; phase 3 voltage is between Phase 3 and
+ Phase 1."
+ ::= { upsPhaseOutputEntry 3 }
+
+ upsPhaseOutputFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output frequency in 0.1 Hertz, or -1 if it's
+ unsupported by this UPS."
+ ::= { upsPhaseOutputEntry 4 }
+
+ -- Output Phase Table
+
+ upsPhaseOutputPhaseTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsPhaseOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output table entries. The number of
+ entries is given by the sum of the upsPhaseNumOutputPhases."
+ ::= { upsPhaseOutput 3 }
+
+ upsPhaseOutputPhaseEntry OBJECT-TYPE
+ SYNTAX UpsPhaseOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular output phase."
+ INDEX { upsPhaseOutputPhaseTableIndex, upsPhaseOutputPhaseIndex }
+ ::= { upsPhaseOutputPhaseTable 1 }
+
+ UpsPhaseOutputPhaseEntry ::= SEQUENCE {
+ upsPhaseOutputPhaseTableIndex INTEGER,
+ upsPhaseOutputPhaseIndex INTEGER,
+ upsPhaseOutputVoltage INTEGER,
+ upsPhaseOutputCurrent INTEGER,
+ upsPhaseOutputMaxCurrent INTEGER,
+ upsPhaseOutputMinCurrent INTEGER,
+ upsPhaseOutputLoad INTEGER,
+ upsPhaseOutputMaxLoad INTEGER,
+ upsPhaseOutputMinLoad INTEGER,
+ upsPhaseOutputPercentLoad INTEGER,
+ upsPhaseOutputMaxPercentLoad INTEGER,
+ upsPhaseOutputMinPercentLoad INTEGER,
+ upsPhaseOutputPower INTEGER,
+ upsPhaseOutputMaxPower INTEGER,
+ upsPhaseOutputMinPower INTEGER,
+ upsPhaseOutputPercentPower INTEGER,
+ upsPhaseOutputMaxPercentPower INTEGER,
+ upsPhaseOutputMinPercentPower INTEGER
+ }
+
+ upsPhaseOutputPhaseTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output identifier."
+ ::= { upsPhaseOutputPhaseEntry 1 }
+
+ upsPhaseOutputPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output phase identifier."
+ ::= { upsPhaseOutputPhaseEntry 2 }
+
+ upsPhaseOutputVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output voltage in VAC, or -1 if it's unsupported
+ by this UPS."
+ ::= { upsPhaseOutputPhaseEntry 3 }
+
+ upsPhaseOutputCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output current in 0.1 amperes drawn
+ by the load on the UPS, or -1 if it's unsupported
+ by this UPS."
+ ::= { upsPhaseOutputPhaseEntry 4 }
+
+ upsPhaseOutputMaxCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum output current in 0.1 amperes measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 5 }
+
+ upsPhaseOutputMinCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum output current in 0.1 amperes measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 6 }
+
+ upsPhaseOutputLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output load in VA, or -1 if it's unsupported
+ by this UPS."
+ ::= { upsPhaseOutputPhaseEntry 7 }
+
+ upsPhaseOutputMaxLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum output load in VA measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 8 }
+
+ upsPhaseOutputMinLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum output load in VA measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 9 }
+
+ upsPhaseOutputPercentLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The percentage of the UPS load capacity in VA at
+ redundancy @ (n + x) presently being used on this
+ output phase, or -1 if it's unsupported by this UPS."
+ ::= { upsPhaseOutputPhaseEntry 10 }
+
+ upsPhaseOutputMaxPercentLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum percentage of the UPS load capacity in
+ VA measured at redundancy @ (n + x) presently
+ being used on this output phase since the last reset
+ (upsPhaseResetMaxMinValues), or -1 if it's unsupported
+ by this UPS. Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 11 }
+
+ upsPhaseOutputMinPercentLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum percentage of the UPS load capacity in
+ VA measured at redundancy @ (n + x) presently
+ being used on this output phase since the last reset
+ (upsPhaseResetMaxMinValues), or -1 if it's unsupported
+ by this UPS. Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 12 }
+
+ upsPhaseOutputPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output power in Watts, or -1 if it's
+ unsupported by this UPS."
+ ::= { upsPhaseOutputPhaseEntry 13 }
+
+ upsPhaseOutputMaxPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum output power in Watts measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 14 }
+
+ upsPhaseOutputMinPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum output power in Watts measured
+ since the last reset (upsPhaseResetMaxMinValues), or
+ -1 if it's unsupported by this UPS.
+ Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 15 }
+
+ upsPhaseOutputPercentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The percentage of the UPS power capacity in Watts at
+ redundancy @ (n + x) presently being used on this
+ output phase, or -1 if it's unsupported by this UPS."
+ ::= { upsPhaseOutputPhaseEntry 16 }
+
+ upsPhaseOutputMaxPercentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum percentage of the UPS power capacity
+ in Watts measured at redundancy @ (n + x) presently
+ being used on this output phase since the last
+ reset (upsPhaseResetMaxMinValues), or -1 if it's
+ unsupported by this UPS. Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 17 }
+
+ upsPhaseOutputMinPercentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum percentage of the UPS power capacity
+ in Watts measured at redundancy @ (n + x) presently
+ being used on this output phase since the last
+ reset (upsPhaseResetMaxMinValues), or -1 if it's
+ unsupported by this UPS. Sampled every 30 seconds."
+ ::= { upsPhaseOutputPhaseEntry 18 }
+
+-- the upsOutletGroupStatus group
+
+upsOutletGroupStatusTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of outlet groups for the UPS."
+ ::= { upsOutletGroupStatus 1 }
+
+upsOutletGroupStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsOutletGroupStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting status of the outlet groups. The number of
+ entries is contained in the upsOutletGroupStatusTableSize OID."
+ ::= { upsOutletGroupStatus 2 }
+
+upsOutletGroupStatusEntry OBJECT-TYPE
+ SYNTAX UpsOutletGroupStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlet group status to get."
+ INDEX { upsOutletGroupStatusIndex}
+ ::= { upsOutletGroupStatusTable 1 }
+
+UpsOutletGroupStatusEntry ::=
+ SEQUENCE {
+ upsOutletGroupStatusIndex INTEGER,
+ upsOutletGroupStatusName DisplayString,
+ upsOutletGroupStatusGroupState INTEGER,
+ upsOutletGroupStatusCommandPending INTEGER
+ }
+
+upsOutletGroupStatusIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet group entry."
+ ::= { upsOutletGroupStatusEntry 1 }
+
+upsOutletGroupStatusName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet group. This OID is provided
+ for informational purposes only. This value is set
+ by the upsOutletGroupConfigName OID."
+ ::= { upsOutletGroupStatusEntry 2 }
+
+upsOutletGroupStatusGroupState OBJECT-TYPE
+ SYNTAX INTEGER {
+ upsOutletGroupStatusOn (1),
+ upsOutletGroupStatusOff (2),
+ upsOutletGroupStatusUnknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet group state. If the outlet
+ group is on, the upsOutletGroupStatusOn (1) value will be returned. If
+ the outlet group is off, the upsOutletGroupStatusOff (2) value will be
+ returned. If the state of the outlet group cannot be determined, the
+ upsOutletGroupStatusUnknown (3) value will be returned."
+
+ ::= { upsOutletGroupStatusEntry 3 }
+
+upsOutletGroupStatusCommandPending OBJECT-TYPE
+ SYNTAX INTEGER {
+ upsOutletGroupCommandPending (1),
+ upsOutletGroupNoCommandPending (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the command pending
+ state of the outlet group. If a command is pending on the
+ outlet group, the upsOutletGroupCommandPending (1) value
+ will be returned. If there is not a command pending
+ on the outlet group, the upsOutletGroupNoCommandPending (2)
+ will be returned."
+ ::= { upsOutletGroupStatusEntry 4 }
+
+-- the upsOutletGroupConfig group
+
+upsOutletGroupConfigTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of outlet groups for the UPS."
+ ::= { upsOutletGroupConfig 1 }
+
+upsOutletGroupConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsOutletGroupConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The list of outlet groups to configure. The number of entries
+ is defined by the upsOutletGroupConfigTableSize OID."
+ ::= { upsOutletGroupConfig 2 }
+
+upsOutletGroupConfigEntry OBJECT-TYPE
+ SYNTAX UpsOutletGroupConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlet groups to configure."
+ INDEX { upsOutletGroupConfigIndex}
+ ::= { upsOutletGroupConfigTable 1 }
+
+UpsOutletGroupConfigEntry ::=
+ SEQUENCE {
+ upsOutletGroupConfigIndex INTEGER,
+ upsOutletGroupConfigName DisplayString,
+ upsOutletGroupConfigPowerOnDelay INTEGER,
+ upsOutletGroupConfigPowerOffDelay INTEGER,
+ upsOutletGroupConfigRebootDuration INTEGER
+ }
+
+upsOutletGroupConfigIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet group entry."
+ ::= { upsOutletGroupConfigEntry 1 }
+
+upsOutletGroupConfigName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet group."
+ ::= { upsOutletGroupConfigEntry 2 }
+
+upsOutletGroupConfigPowerOnDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet group will delay
+ powering on when the delayed on or reboot command is applied.
+ Allowed values are -1 (for Never) or 0 to 600 seconds."
+ ::= { upsOutletGroupConfigEntry 3 }
+
+upsOutletGroupConfigPowerOffDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet group will delay
+ powering off when the delayed off command is applied.
+ Allowed values are 0 to 600 seconds."
+ ::= { upsOutletGroupConfigEntry 4 }
+
+upsOutletGroupConfigRebootDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "During a reboot sequence, power is turned off and then
+ back on. This OID defines the amount of time to wait,
+ in seconds, after turning the power off, at the start
+ of the sequence, before initiating the power on sequence.
+ Allowed values are 0 to 600 seconds."
+ ::= { upsOutletGroupConfigEntry 5 }
+
+-- the upsOutletGroupControl group
+
+upsOutletGroupControlTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of outlet groups for the UPS."
+ ::= { upsOutletGroupControl 1 }
+
+upsOutletGroupControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsOutletGroupControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of individual outlet groups. The number of
+ entries is contained in the upsOutletGroupControlTableSize OID."
+ ::= { upsOutletGroupControl 2 }
+
+upsOutletGroupControlEntry OBJECT-TYPE
+ SYNTAX UpsOutletGroupControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlet group to control."
+ INDEX { upsOutletGroupControlIndex}
+ ::= { upsOutletGroupControlTable 1 }
+
+UpsOutletGroupControlEntry ::=
+ SEQUENCE {
+ upsOutletGroupControlIndex INTEGER,
+ upsOutletGroupControlName DisplayString,
+ upsOutletGroupControlCommand INTEGER
+ }
+
+upsOutletGroupControlIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet group entry."
+ ::= { upsOutletGroupControlEntry 1 }
+
+upsOutletGroupControlName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet group. This OID is provided
+ for informational purposes only. This value is set
+ by the upsOutletGroupConfigName OID."
+ ::= { upsOutletGroupControlEntry 2 }
+
+upsOutletGroupControlCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ upsOutletGroupImmediateOn (1),
+ upsOutletGroupImmediateOff (2),
+ upsOutletGroupImmediateReboot (3),
+ upsOutletGroupDelayedOn (4),
+ upsOutletGroupDelayedOff (5),
+ upsOutletGroupDelayedReboot (6),
+ upsOutletGroupCancelPendingCommand (7),
+ upsOutletGroupControlUnknown (8)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet group state. If the outlet
+ group is on, the upsOutletGroupImmediateOn (1) value will be returned. If
+ the outlet group is off, the upsOutletGroupImmediateOff (2) value will be
+ returned.
+
+ If the state of the outlet group cannot be determined, the
+ upsOutletGroupControlUnknown (8) value will be returned.
+
+ Setting this variable to upsOutletGroupImmediateOn (1) will turn the
+ outlet group on.
+
+ Setting this variable to upsOutletGroupImmediateOff (2) will turn the
+ outlet group off.
+
+ Setting this variable to upsOutletGroupImmediateReboot (3) will turn the outlet
+ group off, wait the upsOutletGroupConfigRebootDuration OID time, wait the
+ upsOutletGroupConfigPowerOnDelay OID, and then turn the outlet group on.
+
+ Setting this variable to upsOutletGroupDelayedOn (4) will turn the outlet
+ group on after the upsOutletGroupConfigPowerOnDelay OID has elapsed.
+
+ Setting this variable to upsOutletGroupDelayedOff (5) will turn the outlet
+ group off after the upsOutletGroupConfigPowerOffDelay OID has elapsed.
+
+ Setting this variable to upsOutletGroupDelayedReboot (6) will turn the outlet
+ group off after the upsOutletGroupConfigPowerOffDelay OID has elapsed, wait the
+ upsOutletGroupConfigRebootDuration OID time, wait the
+ upsOutletGroupConfigPowerOnDelay OID, and then turn the outlet group on.
+
+ Setting this variable to upsOutletGroupCancelPendingCommand (7) will
+ cause any pending command to this outlet group to be canceled."
+ ::= { upsOutletGroupControlEntry 3 }
+
+-- the upsDiagnosticIM group
+
+upsDiagIMTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of Intelligence Modules in or attached to the UPS."
+ ::= { upsDiagnosticIM 1 }
+
+upsDiagIMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagIMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual Intelligence Modules. The number of
+ entries is contained in the upsDiagIMTableSize OID."
+ ::= { upsDiagnosticIM 2 }
+
+upsDiagIMEntry OBJECT-TYPE
+ SYNTAX UpsDiagIMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics and information of an Intelligence Module."
+ INDEX { upsDiagIMIndex}
+ ::= { upsDiagIMTable 1 }
+
+UpsDiagIMEntry ::=
+ SEQUENCE {
+ upsDiagIMIndex INTEGER,
+ upsDiagIMType INTEGER,
+ upsDiagIMStatus INTEGER,
+ upsDiagIMFirmwareRev DisplayString,
+ upsDiagIMSlaveFirmwareRev DisplayString,
+ upsDiagIMHardwareRev DisplayString,
+ upsDiagIMSerialNum DisplayString,
+ upsDiagIMManufactureDate DisplayString
+ }
+
+upsDiagIMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the Intelligence Module entry."
+ ::= { upsDiagIMEntry 1 }
+
+upsDiagIMType OBJECT-TYPE
+ SYNTAX INTEGER {
+ imUnknown (1),
+ imMIM (2),
+ imRIM (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The type of the Intelligence Module.
+ imUnknown(1) indicates the IM type is unknown.
+ imMIM(2) indicates the IM type is a Main Intelligence Module.
+ imRIM(3) indicates the IM type is Redundant Intelligence Module."
+ ::= { upsDiagIMEntry 2 }
+
+upsDiagIMStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Intelligence Module.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagIMEntry 3 }
+
+upsDiagIMFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the Intelligence Module."
+ ::= { upsDiagIMEntry 4 }
+
+upsDiagIMSlaveFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The slave firmware revision of the Intelligence Module."
+ ::= { upsDiagIMEntry 5 }
+
+upsDiagIMHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the Intelligence Module."
+ ::= { upsDiagIMEntry 6 }
+
+upsDiagIMSerialNum OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the Intelligence Module."
+ ::= { upsDiagIMEntry 7 }
+
+upsDiagIMManufactureDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The manufacture date of the Intelligence Module."
+ ::= { upsDiagIMEntry 8 }
+
+-- the upsDiagnosticPowerModules group
+
+upsDiagPMTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of Power Modules in or attached to the UPS."
+ ::= { upsDiagnosticPowerModules 1 }
+
+upsDiagPMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagPMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of Individual Power modules. The number of
+ entries is contained in the upsDiagPMTableSize OID."
+ ::= { upsDiagnosticPowerModules 2 }
+
+upsDiagPMEntry OBJECT-TYPE
+ SYNTAX UpsDiagPMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of an Power Module."
+ INDEX { upsDiagPMIndex}
+ ::= { upsDiagPMTable 1 }
+
+UpsDiagPMEntry ::=
+ SEQUENCE {
+ upsDiagPMIndex INTEGER,
+ upsDiagPMStatus INTEGER,
+ upsDiagPMFirmwareRev DisplayString,
+ upsDiagPMHardwareRev DisplayString,
+ upsDiagPMSerialNum DisplayString,
+ upsDiagPMManufactureDate DisplayString
+ }
+
+upsDiagPMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the Power Module entry."
+ ::= { upsDiagPMEntry 1 }
+
+upsDiagPMStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Power Module.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagPMEntry 2 }
+
+upsDiagPMFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the Power Module."
+ ::= { upsDiagPMEntry 3 }
+
+upsDiagPMHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the Power Module."
+ ::= { upsDiagPMEntry 4 }
+
+upsDiagPMSerialNum OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the Power Module."
+ ::= { upsDiagPMEntry 5 }
+
+upsDiagPMManufactureDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The manufacture date of the Power Module."
+ ::= { upsDiagPMEntry 6 }
+
+-- the upsDiagnosticBatteries group
+
+upsDiagBatteryTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of batteries in or attached to the UPS."
+ ::= { upsDiagnosticBatteries 1 }
+
+upsDiagBatteryTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagBatteryEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual batteries. The number of
+ entries is contained in the upsDiagBattTableSize OID."
+ ::= { upsDiagnosticBatteries 2 }
+
+upsDiagBatteryEntry OBJECT-TYPE
+ SYNTAX UpsDiagBatteryEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of a battery."
+ INDEX { upsDiagBatteryIndex}
+ ::= { upsDiagBatteryTable 1 }
+
+UpsDiagBatteryEntry ::=
+ SEQUENCE {
+ upsDiagBatteryFrameIndex INTEGER,
+ upsDiagBatteryIndex INTEGER,
+ upsDiagBatteryStatus INTEGER,
+ upsDiagBatterySerialNumber DisplayString,
+ upsDiagBatteryFirmwareRev DisplayString,
+ upsDiagBatteryManufactureDate DisplayString,
+ upsDiagBatteryType DisplayString
+ }
+
+upsDiagBatteryFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the battery frame entry.
+ Frame 0 indicates the Main frame. Extended Run (XR) frames
+ start from index 1."
+ ::= { upsDiagBatteryEntry 1 }
+
+upsDiagBatteryIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the battery entry."
+ ::= { upsDiagBatteryEntry 2 }
+
+upsDiagBatteryStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ failed (4),
+ highTemperature (5),
+ replaceImmediately (6),
+ lowCapacity (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the battery.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the battery status is OK.
+ failed(4) indicates the battery status is failed.
+ highTemperature(5) indicates the battery has a high temperature condition.
+ replaceImmediately(6) indicates the battery must be replaced immediately.
+ lowCapacity(7) indicates the battery has a low capacity."
+ ::= { upsDiagBatteryEntry 3 }
+
+upsDiagBatterySerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the battery."
+ ::= { upsDiagBatteryEntry 4 }
+
+upsDiagBatteryFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the battery."
+ ::= { upsDiagBatteryEntry 5 }
+
+upsDiagBatteryManufactureDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The manufacture date of the battery."
+ ::= { upsDiagBatteryEntry 6 }
+
+upsDiagBatteryType OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The battery type or rating for the battery."
+ ::= { upsDiagBatteryEntry 7 }
+
+-- the upsDiagnosticSubsystem group
+
+upsDiagSubSysFrameTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of frames attached to the UPS including the Main frame."
+ ::= { upsDiagnosticSubsystem 1 }
+
+upsDiagSubSysFrameTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysFrameEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual XR Frames."
+ ::= { upsDiagnosticSubsystem 2 }
+
+upsDiagSubSysFrameEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysFrameEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of an XR Frame."
+ INDEX { upsDiagSubSysFrameIndex}
+ ::= { upsDiagSubSysFrameTable 1 }
+
+UpsDiagSubSysFrameEntry ::=
+ SEQUENCE {
+ upsDiagSubSysFrameIndex INTEGER,
+ upsDiagSubSysFrameType INTEGER,
+ upsDiagSubSysFrameFirmwareRev DisplayString,
+ upsDiagSubSysFrameHardwareRev DisplayString,
+ upsDiagSubSysFrameSerialNum DisplayString,
+ upsDiagSubSysFrameManufactureDate DisplayString
+ }
+
+upsDiagSubSysFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysFrameEntry 1 }
+
+upsDiagSubSysFrameType OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ frameTypeMain (3),
+ frameTypeXR (4),
+ frameTypeLXR (5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The type of Frame.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ frameTypeMain(3) indicates the the frame type is the Main Frame.
+ frameTypeXR(4) indicates the frame type is an XR Frame.
+ frameTypeLXR(5) indicates the frame type is an LXR Frame."
+ ::= { upsDiagSubSysFrameEntry 2 }
+
+upsDiagSubSysFrameFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the frame."
+ ::= { upsDiagSubSysFrameEntry 3 }
+
+upsDiagSubSysFrameHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the frame."
+ ::= { upsDiagSubSysFrameEntry 4 }
+
+upsDiagSubSysFrameSerialNum OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the frame."
+ ::= { upsDiagSubSysFrameEntry 5 }
+
+upsDiagSubSysFrameManufactureDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The manufacture date of the frame."
+ ::= { upsDiagSubSysFrameEntry 6 }
+
+upsDiagSubSysIntBypSwitchTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of Internal Bypass switches attached to the UPS."
+ ::= { upsDiagnosticSubsystem 3 }
+
+upsDiagSubSysIntBypSwitchTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysIntBypSwitchEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of the Internal Bypass Switch."
+ ::= { upsDiagnosticSubsystem 4 }
+
+upsDiagSubSysIntBypSwitchEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysIntBypSwitchEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of the Internal Bypass Switch."
+ INDEX { upsDiagSubSysIntBypSwitchIndex}
+ ::= { upsDiagSubSysIntBypSwitchTable 1 }
+
+UpsDiagSubSysIntBypSwitchEntry ::=
+ SEQUENCE {
+ upsDiagSubSysIntBypSwitchFrameIndex INTEGER,
+ upsDiagSubSysIntBypSwitchIndex INTEGER,
+ upsDiagSubSysIntBypSwitchStatus INTEGER,
+ upsDiagSubSysIntBypSwitchFirmwareRev DisplayString,
+ upsDiagSubSysIntBypSwitchHardwareRev DisplayString,
+ upsDiagSubSysIntBypSwitchSerialNum DisplayString,
+ upsDiagSubSysIntBypSwitchManufactureDate DisplayString
+ }
+
+upsDiagSubSysIntBypSwitchFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysIntBypSwitchEntry 1 }
+
+upsDiagSubSysIntBypSwitchIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Internal Bypass Switch index entry."
+ ::= { upsDiagSubSysIntBypSwitchEntry 2 }
+
+upsDiagSubSysIntBypSwitchStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Internal Bypass Switch status.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysIntBypSwitchEntry 3 }
+
+upsDiagSubSysIntBypSwitchFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the Internal Bypass Switch."
+ ::= { upsDiagSubSysIntBypSwitchEntry 4 }
+
+upsDiagSubSysIntBypSwitchHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the Internal Bypass Switch."
+ ::= { upsDiagSubSysIntBypSwitchEntry 5 }
+
+upsDiagSubSysIntBypSwitchSerialNum OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the Internal Bypass Switch."
+ ::= { upsDiagSubSysIntBypSwitchEntry 6 }
+
+upsDiagSubSysIntBypSwitchManufactureDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The manufacture date of the Internal Bypass Switch."
+ ::= { upsDiagSubSysIntBypSwitchEntry 7 }
+
+upsDiagSubSysBattMonitorTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of Battery Monitor Boards attached to the UPS."
+ ::= { upsDiagnosticSubsystem 5 }
+
+upsDiagSubSysBattMonitorTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysBattMonitorEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of the Battery Monitor Board."
+ ::= { upsDiagnosticSubsystem 6 }
+
+upsDiagSubSysBattMonitorEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysBattMonitorEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of the Battery Monitor Board."
+ INDEX { upsDiagSubSysBattMonitorIndex}
+ ::= { upsDiagSubSysBattMonitorTable 1 }
+
+UpsDiagSubSysBattMonitorEntry ::=
+ SEQUENCE {
+ upsDiagSubSysBattMonitorFrameIndex INTEGER,
+ upsDiagSubSysBattMonitorIndex INTEGER,
+ upsDiagSubSysBattMonitorStatus INTEGER,
+ upsDiagSubSysBattMonitorFirmwareRev DisplayString,
+ upsDiagSubSysBattMonitorHardwareRev DisplayString,
+ upsDiagSubSysBattMonitorSerialNum DisplayString,
+ upsDiagSubSysBattMonitorManufactureDate DisplayString
+ }
+
+upsDiagSubSysBattMonitorFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysBattMonitorEntry 1 }
+
+upsDiagSubSysBattMonitorIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the Battery Monitor Board."
+ ::= { upsDiagSubSysBattMonitorEntry 2 }
+
+upsDiagSubSysBattMonitorStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Battery Monitor Board.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysBattMonitorEntry 3 }
+
+upsDiagSubSysBattMonitorFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the Battery Monitor Board."
+ ::= { upsDiagSubSysBattMonitorEntry 4 }
+
+upsDiagSubSysBattMonitorHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the Battery Monitor Board."
+ ::= { upsDiagSubSysBattMonitorEntry 5 }
+
+upsDiagSubSysBattMonitorSerialNum OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the Battery Monitor Board."
+ ::= { upsDiagSubSysBattMonitorEntry 6 }
+
+upsDiagSubSysBattMonitorManufactureDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date of the manufacture for the Battery Monitor Board."
+ ::= { upsDiagSubSysBattMonitorEntry 7 }
+
+upsDiagSubSysExternalSwitchGearTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of External Switch Gears attached to the UPS."
+ ::= { upsDiagnosticSubsystem 7 }
+
+upsDiagSubSysExternalSwitchGearTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysExternalSwitchGearEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of the individual External Switch Gear."
+ ::= { upsDiagnosticSubsystem 8 }
+
+upsDiagSubSysExternalSwitchGearEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysExternalSwitchGearEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of an individual External Switch Gear."
+ INDEX { upsDiagSubSysExternalSwitchGearIndex}
+ ::= { upsDiagSubSysExternalSwitchGearTable 1 }
+
+UpsDiagSubSysExternalSwitchGearEntry ::=
+ SEQUENCE {
+ upsDiagSubSysExternalSwitchGearFrameIndex INTEGER,
+ upsDiagSubSysExternalSwitchGearIndex INTEGER,
+ upsDiagSubSysExternalSwitchGearStatus INTEGER,
+ upsDiagSubSysExternalSwitchGearFirmwareRev DisplayString,
+ upsDiagSubSysExternalSwitchGearHardwareRev DisplayString,
+ upsDiagSubSysExternalSwitchGearSerialNum DisplayString,
+ upsDiagSubSysExternalSwitchGearManufactureDate DisplayString
+ }
+
+upsDiagSubSysExternalSwitchGearFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysExternalSwitchGearEntry 1 }
+
+upsDiagSubSysExternalSwitchGearIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the External Switch Gear."
+ ::= { upsDiagSubSysExternalSwitchGearEntry 2 }
+
+upsDiagSubSysExternalSwitchGearStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the External Switch Gear.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysExternalSwitchGearEntry 3 }
+
+upsDiagSubSysExternalSwitchGearFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the External Switch Gear monitor card."
+ ::= { upsDiagSubSysExternalSwitchGearEntry 4 }
+
+upsDiagSubSysExternalSwitchGearHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the External Switch Gear monitor card."
+ ::= { upsDiagSubSysExternalSwitchGearEntry 5 }
+
+upsDiagSubSysExternalSwitchGearSerialNum OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The serial number of the External Switch Gear monitor card."
+ ::= { upsDiagSubSysExternalSwitchGearEntry 6 }
+
+upsDiagSubSysExternalSwitchGearManufactureDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date of the manufacture for the External Switch Gear monitor card."
+ ::= { upsDiagSubSysExternalSwitchGearEntry 7 }
+
+upsDiagSubSysDisplayInterfaceCardTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of Display Interface Cards attached to the UPS."
+ ::= { upsDiagnosticSubsystem 9 }
+
+upsDiagSubSysDisplayInterfaceCardTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysDisplayInterfaceCardEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual Display Interface Cards."
+ ::= { upsDiagnosticSubsystem 10 }
+
+upsDiagSubSysDisplayInterfaceCardEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysDisplayInterfaceCardEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of a Display Interface Card."
+ INDEX { upsDiagSubSysDisplayInterfaceCardIndex}
+ ::= { upsDiagSubSysDisplayInterfaceCardTable 1 }
+
+UpsDiagSubSysDisplayInterfaceCardEntry ::=
+ SEQUENCE {
+ upsDiagSubSysDisplayInterfaceCardFrameIndex INTEGER,
+ upsDiagSubSysDisplayInterfaceCardIndex INTEGER,
+ upsDiagSubSysDisplayInterfaceCardStatus INTEGER
+ }
+
+upsDiagSubSysDisplayInterfaceCardFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysDisplayInterfaceCardEntry 1 }
+
+upsDiagSubSysDisplayInterfaceCardIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the Display Interface Card."
+ ::= { upsDiagSubSysDisplayInterfaceCardEntry 2 }
+
+upsDiagSubSysDisplayInterfaceCardStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Display Interface Card.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysDisplayInterfaceCardEntry 3 }
+
+upsDiagSubSysDCCircuitBreakerTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC Circuit Breakers attached to the UPS."
+ ::= { upsDiagnosticSubsystem 11 }
+
+upsDiagSubSysDCCircuitBreakerTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysDCCircuitBreakerEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual DC Circuit Breakers."
+ ::= { upsDiagnosticSubsystem 12 }
+
+upsDiagSubSysDCCircuitBreakerEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysDCCircuitBreakerEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of a DC Circuit Breaker."
+ INDEX { upsDiagSubSysDCCircuitBreakerIndex}
+ ::= { upsDiagSubSysDCCircuitBreakerTable 1 }
+
+UpsDiagSubSysDCCircuitBreakerEntry ::=
+ SEQUENCE {
+ upsDiagSubSysDCCircuitBreakerFrameIndex INTEGER,
+ upsDiagSubSysDCCircuitBreakerIndex INTEGER,
+ upsDiagSubSysDCCircuitBreakerStatus INTEGER
+ }
+
+upsDiagSubSysDCCircuitBreakerFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysDCCircuitBreakerEntry 1 }
+
+upsDiagSubSysDCCircuitBreakerIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the DC Circuit Breaker."
+ ::= { upsDiagSubSysDCCircuitBreakerEntry 2 }
+
+upsDiagSubSysDCCircuitBreakerStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ opened (3),
+ closed (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the DC Circuit Breaker.
+ unknown(1) indicates the circuit breaker status is unknown.
+ notInstalled(2) indicates the circuit breaker is not installed.
+ opened(3) indicates the circuit breaker is opened.
+ closed(4) indicates the circuit breaker is closed."
+ ::= { upsDiagSubSysDCCircuitBreakerEntry 3 }
+
+upsDiagSubSysSystemPowerSupplyTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of System Power Supplies attached to the UPS."
+ ::= { upsDiagnosticSubsystem 13 }
+
+upsDiagSubSysSystemPowerSupplyTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysSystemPowerSupplyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual System Power Supplies."
+ ::= { upsDiagnosticSubsystem 14 }
+
+upsDiagSubSysSystemPowerSupplyEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysSystemPowerSupplyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of a System Power Supply."
+ INDEX { upsDiagSubSysSystemPowerSupplyIndex}
+ ::= { upsDiagSubSysSystemPowerSupplyTable 1 }
+
+UpsDiagSubSysSystemPowerSupplyEntry ::=
+ SEQUENCE {
+ upsDiagSubSysSystemPowerSupplyFrameIndex INTEGER,
+ upsDiagSubSysSystemPowerSupplyIndex INTEGER,
+ upsDiagSubSysSystemPowerSupplyStatus INTEGER
+ }
+
+upsDiagSubSysSystemPowerSupplyFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysSystemPowerSupplyEntry 1 }
+
+upsDiagSubSysSystemPowerSupplyIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of a System Power Supply."
+ ::= { upsDiagSubSysSystemPowerSupplyEntry 2 }
+
+upsDiagSubSysSystemPowerSupplyStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the System Power Supply.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysSystemPowerSupplyEntry 3 }
+
+upsDiagSubSysXRCommunicationCardTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of XR Communication Cards attached to the UPS."
+ ::= { upsDiagnosticSubsystem 15 }
+
+upsDiagSubSysXRCommunicationCardTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysXRCommunicationCardEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual XR Communication Cards."
+ ::= { upsDiagnosticSubsystem 16 }
+
+upsDiagSubSysXRCommunicationCardEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysXRCommunicationCardEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of an XR Communication Card."
+ INDEX { upsDiagSubSysXRCommunicationCardIndex}
+ ::= { upsDiagSubSysXRCommunicationCardTable 1 }
+
+UpsDiagSubSysXRCommunicationCardEntry ::=
+ SEQUENCE {
+ upsDiagSubSysXRCommunicationCardFrameIndex INTEGER,
+ upsDiagSubSysXRCommunicationCardIndex INTEGER,
+ upsDiagSubSysXRCommunicationCardStatus INTEGER
+ }
+
+upsDiagSubSysXRCommunicationCardFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysXRCommunicationCardEntry 1 }
+
+upsDiagSubSysXRCommunicationCardIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of an XR Communication Card."
+ ::= { upsDiagSubSysXRCommunicationCardEntry 2 }
+
+upsDiagSubSysXRCommunicationCardStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the XR Communication Card.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysXRCommunicationCardEntry 3 }
+
+upsDiagSubSysExternalPowerFrameBoardTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of External Power Frame Boards attached to the UPS."
+ ::= { upsDiagnosticSubsystem 17 }
+
+upsDiagSubSysExternalPowerFrameBoardTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysExternalPowerFrameBoardEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual External Power Frame Boards."
+ ::= { upsDiagnosticSubsystem 18 }
+
+upsDiagSubSysExternalPowerFrameBoardEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysExternalPowerFrameBoardEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of an External Power Frame Board."
+ INDEX { upsDiagSubSysExternalPowerFrameBoardIndex}
+ ::= { upsDiagSubSysExternalPowerFrameBoardTable 1 }
+
+UpsDiagSubSysExternalPowerFrameBoardEntry ::=
+ SEQUENCE {
+ upsDiagSubSysExternalPowerFrameBoardFrameIndex INTEGER,
+ upsDiagSubSysExternalPowerFrameBoardIndex INTEGER,
+ upsDiagSubSysExternalPowerFrameBoardStatus INTEGER
+ }
+
+upsDiagSubSysExternalPowerFrameBoardFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysExternalPowerFrameBoardEntry 1 }
+
+upsDiagSubSysExternalPowerFrameBoardIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of an External Power Frame Board."
+ ::= { upsDiagSubSysExternalPowerFrameBoardEntry 2 }
+
+upsDiagSubSysExternalPowerFrameBoardStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the External Power Frame Board.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysExternalPowerFrameBoardEntry 3 }
+
+upsDiagSubSysChargerTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of Chargers attached to the UPS."
+ ::= { upsDiagnosticSubsystem 19 }
+
+ upsDiagSubSysChargerTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF UpsDiagSubSysChargerEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for diagnostics of individual chargers."
+ ::= { upsDiagnosticSubsystem 20 }
+
+upsDiagSubSysChargerEntry OBJECT-TYPE
+ SYNTAX UpsDiagSubSysChargerEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The diagnostics of a charger."
+ INDEX { upsDiagSubSysChargerIndex}
+ ::= { upsDiagSubSysChargerTable 1 }
+
+UpsDiagSubSysChargerEntry ::=
+ SEQUENCE {
+ upsDiagSubSysChargerFrameIndex INTEGER,
+ upsDiagSubSysChargerIndex INTEGER,
+ upsDiagSubSysChargerStatus INTEGER
+ }
+
+upsDiagSubSysChargerFrameIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The frame index entry."
+ ::= { upsDiagSubSysChargerEntry 1 }
+
+upsDiagSubSysChargerIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of a charger."
+ ::= { upsDiagSubSysChargerEntry 2 }
+
+upsDiagSubSysChargerStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ offOk (3),
+ onOk (4),
+ offFail (5),
+ onFail (6),
+ lostComm (7)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Charger.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ offOk(3) indicates the device status is off and OK.
+ onOk(4) indicates the device status is on and OK.
+ offFail(5) indicates the device status is off and failed.
+ onFail(6) indicates the device status is on and failed.
+ lostComm(7) indicates the device has lost communication."
+ ::= { upsDiagSubSysChargerEntry 3 }
+
+-- the upsDiagnosticExternalDevices group
+
+upsDiagSwitchGearStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ fail (4),
+ lostComm (5),
+ overtemp (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Switch Gear.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the device status is OK.
+ fail(4) indicates the device status has failed.
+ lostComm(5) indicates the device has lost communication.
+ overtemp(6) indicates the device has an over temperature condition."
+ ::= { upsDiagSwitchGear 1 }
+
+upsDiagSwitchGearInputSwitchStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ opened (3),
+ closed (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Switch Gear Input Switch.
+ unknown(1) indicates the switch status is unknown.
+ notInstalled(2) indicates the switch is not installed.
+ opened(3) indicates the switch is opened.
+ closed(4) indicates the switch is closed."
+ ::= { upsDiagSwitchGear 2 }
+
+upsDiagSwitchGearOutputSwitchStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ opened (3),
+ closed (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Switch Gear Output Switch.
+ unknown(1) indicates the switch status is unknown.
+ notInstalled(2) indicates the switch is not installed.
+ opened(3) indicates the switch is opened.
+ closed(4) indicates the switch is closed."
+ ::= { upsDiagSwitchGear 3 }
+
+upsDiagSwitchGearBypassSwitchStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ opened (3),
+ closed (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Switch Gear Bypass Switch.
+ unknown(1) indicates the switch status is unknown.
+ notInstalled(2) indicates the switch is not installed.
+ opened(3) indicates the switch is opened.
+ closed(4) indicates the switch is closed."
+ ::= { upsDiagSwitchGear 4 }
+
+upsDiagMCCBBoxStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ opened (3),
+ closed (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the MCCB Box (Molded Case Circuit Breaker Box) external device.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ opened(3) indicates the circuit is opened.
+ closed(4) indicates the circuit is closed."
+ ::= { upsDiagMCCBBox 1 }
+
+upsDiagTransformerStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ fail (4),
+ lostComm (5),
+ overtemp (6),
+ opened (7),
+ closed (8)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the External Transformer.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the device status is OK.
+ fail(4) indicates the device status has failed.
+ lostComm(5) indicates the device has lost communication.
+ overtemp(6) indicates the device has an over temperature condition.
+ opened(7) indicates the circuit is opened.
+ closed(8) indicates the circuit is closed."
+ ::= { upsDiagTransformer 1 }
+
+-- the upsDiagnosticComBus group
+
+upsDiagComBusInternalMIMStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ lostComm (4),
+ rxFailure (5),
+ txFailure (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the internal MIM communication bus.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the device status is OK.
+ lostComm(4) indicates the device has lost communication.
+ rxFailure(5) indicates the device has a receive failure.
+ txFailure(6) indicates the device has a transmit failure."
+ ::= { upsDiagnosticComBus 1 }
+
+upsDiagComBusInternalRIMStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ lostComm (4),
+ rxFailure (5),
+ txFailure (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the internal RIM communication bus.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the device status is OK.
+ lostComm(4) indicates the device has lost communication.
+ rxFailure(5) indicates the device has a receive failure.
+ txFailure(6) indicates the device has a transmit failure."
+ ::= { upsDiagnosticComBus 2 }
+
+upsDiagComBusMIMtoRIMStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ lostComm (4),
+ rxFailure (5),
+ txFailure (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the MIM to RIM communication bus.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the device status is OK.
+ lostComm(4) indicates the device has lost communication.
+ rxFailure(5) indicates the device has a receive failure.
+ txFailure(6) indicates the device has a transmit failure."
+ ::= { upsDiagnosticComBus 3 }
+
+upsDiagComBusExternalMIMStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ lostComm (4),
+ rxFailure (5),
+ txFailure (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the external MIM communication bus.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the device status is OK.
+ lostComm(4) indicates the device has lost communication.
+ rxFailure(5) indicates the device has a receive failure.
+ txFailure(6) indicates the device has a transmit failure."
+ ::= { upsDiagnosticComBus 4 }
+
+upsDiagComBusExternalRIMStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown (1),
+ notInstalled (2),
+ ok (3),
+ lostComm (4),
+ rxFailure (5),
+ txFailure (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the external RIM communication bus.
+ unknown(1) indicates the device status is unknown.
+ notInstalled(2) indicates the device is not installed.
+ ok(3) indicates the device status is OK.
+ lostComm(4) indicates the device has lost communication.
+ rxFailure(5) indicates the device has a receive failure.
+ txFailure(6) indicates the device has a transmit failure."
+ ::= { upsDiagnosticComBus 5 }
+
+-- the serialPort2Config group
+
+serialPort2Mode OBJECT-TYPE
+ SYNTAX INTEGER {
+ localConsole(1),
+ passthrough(2)
+ }
+ ACCESS read-write
+ STATUS obsolete
+ DESCRIPTION
+ "Setting this variable to passthrough will enable mini's port2
+ behave like a UPS port. Choosing localConsole will enable the port
+ to be used as local console."
+ ::= { serialPort2Config 1 }
+-- the serialPort2Control group
+
+setPulseOnTXD OBJECT-TYPE
+ SYNTAX INTEGER {
+ noSetPulseOnTXD(1),
+ setPulseOnTXD(2),
+ setTXDLow(3),
+ setTXDHigh(4)
+
+ }
+ ACCESS read-write
+ STATUS obsolete
+ DESCRIPTION
+ "Setting this variable to setPulseOnTXD(2)
+ causes adapter to generate a PULSE on TXD pin of serial port 2.
+ The duration in the prototype implementation will be 1 second.
+
+ Setting this value to noSetPulseOnTXD(1) has no
+ effect.
+
+ The value noSetPulseOnTXD(1) will always be returned
+ when the variable is read.
+
+ Setting this value to setTXDLow(3), or setTXDHigh(4) will keep TXD
+ always low or high respectively."
+ ::= { serialPort2Control 1 }
+
+-- the sPDUIdent group
+
+sPDUIdentHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the PDU. This value
+ is set at the factory."
+ ::= { sPDUIdent 1 }
+
+sPDUIdentFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An 8 byte ID string identifying the PDU firmware revision.
+ This value is set at the factory."
+ ::= { sPDUIdent 2 }
+
+
+sPDUIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the PDU was manufactured in mm/dd/yy format.
+ This value is set at the factory. The year 2000 will be
+ represented by 00."
+ ::= { sPDUIdent 3 }
+
+sPDUIdentModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 10-character string identifying the model number of
+ the PDU internal. This value is set at the factory."
+ ::= { sPDUIdent 4 }
+
+sPDUIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 12-character string identifying the serial number of
+ the PDU internal microprocessor. This value is set at
+ the factory."
+ ::= { sPDUIdent 5 }
+
+
+-- the sPDUMasterControl group
+
+sPDUMasterControlSwitch OBJECT-TYPE
+ SYNTAX INTEGER {
+ turnAllOnNow (1),
+ turnAllOnSequence (2),
+ turnAllOffNow (3),
+ rebootAllNow (4),
+ rebootAllSequence (5),
+ noCommand (6),
+ turnAllOffSequence (7)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to turnAllOnNow (1) will turn all outlets
+ on immediately.
+
+ Setting this OID to turnAllOnSequence (2) will turn all outlets
+ on as defined by each outlet's sPDUOutletPowerOnTime OID value.
+
+ Setting this OID to turnAllOff (3) will turn all outlets
+ off immediately.
+
+ Setting this OID to rebootAllNow (4) will reboot all outlets
+ immediately.
+
+ For MasterSwitch firmware version 1.X, setting this OID to
+ rebootAllSequence (5) reboots all outlets, with power returned
+ to the outlets in the sequence defined by each outlet's
+ sPDUOutletPowerOnTime OID value.
+
+ For MasterSwitch firmware version 2.X, setting this OID to
+ rebootAllSequence (5) will cause a turnAllOffSequence to be performed.
+ Once all outlets are off, the MasterSwitch will then delay the
+ sPDUMasterConfigReboot OID time, and then perform a turnAllOnSequence.
+
+ For MasterSwitch firmware version 2.X, setting this OID to
+ turnAllOffSequence (7) will turn all outlets off as defined by
+ each outlet's sPDUOutletPowerOffTime OID value.
+
+ For MasterSwitch firmware version 1.X, setting this OID to
+ turnAllOffSequence (7) will have no effect.
+
+ Getting this OID will return the noCommand (6) value."
+
+ ::= { sPDUMasterControl 1 }
+
+
+sPDUMasterState OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will cause the status of all outlets to be
+ returned. This OID is provided for informational purposes only.
+ To change the outlet state, the user should use the sPDUOutletCtl
+ OID in the sPDUOutletControlTable.
+
+ The format of the data returned is a character string consisting
+ of the word 'On' if the outlet is on or 'Off' if the outlet is
+ off. At least one space will delimit each outlet entry in the
+ string.
+
+ If the outlet states are unknown, the character string 'Unknown'
+ will be returned. This signifies that there is an inconsistancy
+ in the PDU. In the rare case that this should happen, the user
+ is advised to shut down all equipment powered by the PDU and
+ then cycle the PDU's power. This will put the PDU in a consistent
+ state."
+
+ ::= { sPDUMasterControl 2 }
+
+sPDUMasterPending OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will cause the command pending status of all outlets to be returned.
+
+ The format of the data returned is a character string consisting
+ of the word 'Yes' if a command is pending for the outlet or 'No'
+ if there is no command pending for the outlet. At least one
+ space will delimit each outlet entry in the string.
+
+ If the pending states are unknown, the character string 'Unknown'
+ will be returned. This signifies that there is an inconsistancy
+ in the PDU. In the rare case that this should happen, the user
+ is advised to shut down all equipment powered by the PDU and then
+ cycle the PDU's power. This will put the PDU in a consistent state."
+ ::= { sPDUMasterControl 3 }
+
+
+-- the sPDUMasterConfig group
+
+sPDUMasterConfigPowerOn OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in seconds, between when
+ power is provided to the PDU and when the PDU
+ provides basic master power to the outlets.
+
+ Allowed values are:
+
+ -1 never apply power automatically.
+ 0 apply power immediately.
+ 15 apply power in 15 seconds.
+ 30 apply power in 30 seconds.
+ 45 apply power in 45 seconds.
+ 60 apply power in 60 seconds (1 minute).
+ 120 apply power in 120 seconds (2 minutes).
+ 300 apply power in 300 seconds (5 minutes).
+
+ If a value other than a supported value is provided in a
+ set request, the PDU interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+
+ ::= { sPDUMasterConfig 1 }
+
+sPDUMasterConfigReboot OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "During a reboot sequence, power is turned off and then
+ back on. This OID defines the amount of time to wait,
+ in seconds, after turning the power off, at the start
+ of the sequence, before turning power back on, at the
+ end of the reboot sequence.
+
+ Allowed values are:
+
+ 5 wait 5 seconds between off/on.
+ 10 wait 10 seconds between off/on.
+ 15 wait 15 seconds between off/on.
+ 20 wait 20 seconds between off/on.
+ 30 wait 30 seconds between off/on.
+ 45 wait 45 seconds between off/on.
+ 60 wait 60 seconds (1 minute) between off/on.
+
+ If a value other than a supported value is provided in a
+ set request, the PDU interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used.
+
+ This OID is read-only for the MasterSwitch version 2.X and is the
+ maximum sPDUOutletRebootDuration OID of the individual outlets."
+
+ ::= { sPDUMasterConfig 2 }
+
+sPDUMasterConfigPDUName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the PDU. The maximum value is 20 characters."
+ ::= { sPDUMasterConfig 3 }
+
+
+
+-- the sPDUOutletControl group
+sPDUOutletControlTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of outlets for the PDU."
+ ::= { sPDUOutletControl 1 }
+
+
+sPDUOutletControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of individual outlet switches. The number of
+ entries is contained in the sPDUOutletControlTableSize OID."
+ ::= { sPDUOutletControl 2 }
+
+sPDUOutletControlEntry OBJECT-TYPE
+ SYNTAX OutletControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to control."
+ INDEX { sPDUOutletControlIndex}
+ ::= { sPDUOutletControlTable 1 }
+
+OutletControlEntry ::=
+ SEQUENCE {
+ sPDUOutletControlIndex INTEGER,
+ sPDUOutletPending INTEGER,
+ sPDUOutletCtl INTEGER,
+ sPDUOutletCtlName DisplayString
+ }
+
+sPDUOutletControlIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletControlEntry 1 }
+
+sPDUOutletPending OBJECT-TYPE
+ SYNTAX INTEGER{
+ commandPending (1),
+ noCommandPending (2),
+ commandPendingUnknown (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Reports whether the current outlet has a pending command.
+
+ If the commandPendingUnknown (3) value is returned, all
+ devices powered by the PDU should be shut down. The PDU's
+ power should then be cycled to clear this condition."
+
+ ::= { sPDUOutletControlEntry 2 }
+
+sPDUOutletCtl OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletOn (1),
+ outletOff (2),
+ outletReboot (3),
+ outletUnknown (4),
+ outletOnWithDelay (5),
+ outletOffWithDelay (6),
+ outletRebootWithDelay (7)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the outletOn (1) value will be returned.
+ If the outlet is off, the outletOff (2) value will be
+ returned.
+
+ If the state of the outlet cannot be determined, the
+ outletUnknown (4) value will be returned. If the
+ outletUnknown condition should occur, all devices
+ powered by the PDU should be shut down. The PDU's power
+ should then be cycled to clear this condition.
+
+ Setting this variable to outletOn (1) will turn the outlet on.
+
+ Setting this variable to outletOff (2) will turn the outlet off.
+
+ Setting this variable to outletReboot (3) will reboot the outlet.
+
+ Setting this variable to outletOnWithDelay (5) will turn the outlet on
+ after the sPDUOutletPowerOnTime OID has elapsed. This option is not
+ valid for MasterSwitch firmware version 1.X.
+
+ Setting this variable to outletOffWithDelay (6) will turn the outlet off
+ after the sPDUOutletPowerOffTime OID has elapsed. This option is not valid
+ for MasterSwitch firmware version 1.X.
+
+ Setting this variable to outletRebootWithDelay (7) will turn the outlet off
+ after the sPDUOutletPowerOffTime OID has elapsed, wait the sPDUOutletRebootDuration
+ OID time, then turn the outlet back on.
+ This option is not valid for MasterSwitch firmware version 1.X."
+
+ ::= { sPDUOutletControlEntry 3 }
+
+sPDUOutletCtlName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is 20 characters.
+ This OID is provided for informational purposes only.
+ This value is set by the sPDUOutletName OID."
+
+ ::= { sPDUOutletControlEntry 4 }
+
+-- the sPDUOutletConfig group
+sPDUOutletConfigTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of outlets for the PDU."
+ ::= { sPDUOutletConfig 1 }
+
+sPDUOutletConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF SPDUOutletConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The list of outlets to configure. The number of
+ entries is defined by the sPDUOutletConfigTableSize
+ OID."
+
+ ::= { sPDUOutletConfig 2 }
+
+sPDUOutletConfigEntry OBJECT-TYPE
+ SYNTAX SPDUOutletConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to control."
+ INDEX { sPDUOutletConfigIndex}
+ ::= { sPDUOutletConfigTable 1 }
+
+SPDUOutletConfigEntry ::=
+ SEQUENCE {
+ sPDUOutletConfigIndex INTEGER,
+ sPDUOutletPowerOnTime INTEGER,
+ sPDUOutletName DisplayString,
+ sPDUOutletPowerOffTime INTEGER,
+ sPDUOutletRebootDuration INTEGER
+ }
+
+sPDUOutletConfigIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletConfigEntry 1 }
+
+sPDUOutletPowerOnTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet will delay
+ powering on when the MasterSwitch is powered on.
+
+ Allowed values are:
+
+ -1 never power on automatically.
+ 0 power on with the Master Switch.
+ 15 power on 15 seconds after the MasterSwitch has power applied.
+ 30 power on 30 seconds after the MasterSwitch has power applied.
+ 45 power on 45 seconds after the MasterSwitch has power applied.
+ 60 power on 60 seconds (1 minute) after the MasterSwitch has power applied.
+ 120 power on 120 seconds (2 minutes) after the MasterSwitch has power applied.
+ 300 power on 300 seconds (5 minutes) after the MasterSwitch has power applied.
+
+ If a value other than a supported value is provided in a
+ set request, the PDU interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+
+ ::= { sPDUOutletConfigEntry 2 }
+
+sPDUOutletName OBJECT-TYPE
+ SYNTAX DisplayString ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is 20 characters."
+
+ ::= { sPDUOutletConfigEntry 3 }
+
+sPDUOutletPowerOffTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet will delay
+ powering off.
+
+ Allowed values are:
+
+ -1 never power off automatically.
+ 0 power off with the MasterSwitch.
+ 15 power off 15 seconds after being commanded.
+ 30 power off 30 seconds after being commanded.
+ 45 power off 45 seconds after being commanded.
+ 60 power off 60 seconds (1 minute) after being commanded.
+ 120 power off 120 seconds (2 minutes) after being commanded.
+ 300 power off 300 seconds (5 minutes) after being commanded.
+
+ If a value other than a supported value is provided in a
+ set request, the PDU interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used.
+
+ This OID is not available for MasterSwitch firmware version 1.X."
+
+ ::= { sPDUOutletConfigEntry 4 }
+
+sPDUOutletRebootDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "During a reboot sequence, power is turned off and then
+ back on. This OID defines the amount of time to wait,
+ in seconds, after turning the power off, at the start
+ of the sequence, before turning power back on, at the
+ end of the reboot sequence.
+
+ Allowed values are:
+
+ 5 wait 5 seconds between off/on.
+ 10 wait 10 seconds between off/on.
+ 15 wait 15 seconds between off/on.
+ 20 wait 20 seconds between off/on.
+ 30 wait 30 seconds between off/on.
+ 45 wait 45 seconds between off/on.
+ 60 wait 60 seconds (1 minute) between off/on.
+
+ If a value other than a supported value is provided in a
+ set request, the PDU interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used.
+
+ This OID is not available for MasterSwitch firmware version 1.X."
+
+ ::= { sPDUOutletConfigEntry 5 }
+
+
+-- the sPDUIdentVM group
+
+sPDUIdentVMTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch VMs controllable
+ by this IP address."
+ ::= { sPDUIdentVM 1 }
+
+
+sPDUIdentVMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IdentVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for query of the individual MasterSwitch VMs.
+ The number of entries is contained in the
+ sPDUIdentVMTableSize OID."
+ ::= { sPDUIdentVM 2 }
+
+sPDUIdentVMEntry OBJECT-TYPE
+ SYNTAX IdentVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch VMs to query."
+ INDEX { sPDUIdentVMIndex}
+ ::= { sPDUIdentVMTable 1 }
+
+IdentVMEntry ::=
+ SEQUENCE {
+ sPDUIdentVMIndex INTEGER,
+ sPDUIdentNameVM DisplayString,
+ sPDUIdentHardwareRevVM DisplayString,
+ sPDUIdentFirmwareRevVM DisplayString,
+ sPDUIdentDateOfManufactureVM DisplayString,
+ sPDUIdentModelNumberVM DisplayString,
+ sPDUIdentSerialNumberVM DisplayString
+ }
+
+sPDUIdentVMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch VM entry."
+ ::= { sPDUIdentVMEntry 1 }
+
+sPDUIdentNameVM OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 23-character string identifying the
+ MasterSwitch VM. "
+ ::= { sPDUIdentVMEntry 2 }
+
+sPDUIdentHardwareRevVM OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware version of the MasterSwitch VM.
+ This value is set at the factory."
+ ::= { sPDUIdentVMEntry 3 }
+
+sPDUIdentFirmwareRevVM OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An 6-character ID string identifying the MasterSwitch VM
+ firmware version. This value is set at the factory."
+ ::= { sPDUIdentVMEntry 4 }
+
+
+sPDUIdentDateOfManufactureVM OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the MasterSwitch VM was manufactured in mm/dd/yyyy format.
+ This value is set at the factory. "
+ ::= { sPDUIdentVMEntry 5 }
+
+sPDUIdentModelNumberVM OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 17-character string identifying the model number of
+ the MasterSwitch VM. This value is set at the factory."
+ ::= { sPDUIdentVMEntry 6 }
+
+sPDUIdentSerialNumberVM OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 17-character string identifying the serial number of
+ the MasterSwitch VM. This value is set at the factory."
+ ::= { sPDUIdentVMEntry 7 }
+
+
+-- the sPDUMasterControlVM group
+
+sPDUMasterControlVMTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch VMs controllable
+ by this IP address."
+ ::= { sPDUMasterControlVM 1 }
+
+
+sPDUMasterControlVMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MasterControlVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of the individual MasterSwitch VMs.
+ The number of entries is contained in the
+ sPDUMasterControlVMTableSize OID."
+ ::= { sPDUMasterControlVM 2 }
+
+sPDUMasterControlVMEntry OBJECT-TYPE
+ SYNTAX MasterControlVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch VMs to control."
+ INDEX { sPDUMasterControlVMIndex}
+ ::= { sPDUMasterControlVMTable 1 }
+
+MasterControlVMEntry ::=
+ SEQUENCE {
+ sPDUMasterControlVMIndex INTEGER,
+ sPDUMasterControlVMName DisplayString,
+ sPDUMasterControlVMCommand INTEGER
+ }
+
+sPDUMasterControlVMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch VM entry."
+ ::= { sPDUMasterControlVMEntry 1 }
+
+sPDUMasterControlVMName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch VM. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigVMName OID."
+ ::= { sPDUMasterControlVMEntry 2 }
+
+sPDUMasterControlVMCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ noCommandAllVM (1),
+ immediateAllOnVM (2),
+ immediateAllOffVM (3),
+ immediateAllRebootVM (4),
+ delayedAllOnVM (5),
+ delayedAllOffVM (6),
+ sequencedAllRebootVM (7),
+ delayedAllRebootVM (8),
+ delayedSequenceAllRebootVM (9),
+ cancelAllPendingCommandsVM (10),
+ audioAlarmMute (11)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to immediateAllOnVM (2) will turn all outlets
+ on immediately.
+
+ Setting this OID to immediateAllOffVM (3) will turn all outlets
+ off immediately.
+
+ Setting this OID to immediateAllRebootVM (4) will reboot all outlets
+ immediately.
+
+ Setting this OID to delayedAllOnVM (5) will turn all outlets on as
+ defined by each outlet's sPDUOutletConfigVMPowerOnTime OID value.
+
+ Setting this OID to delayedAllOffVM (6) will turn all outlets
+ off as defined by each outlet's sPDUOutletConfigVMPowerOffTime OID value.
+
+ Setting this OID to sequencedAllRebootVM (7) will cause a
+ immediateAllOffVM command to be performed. The MasterSwitch VM will
+ then delay the sPDUMasterStatusVMRebootDuration OID time, and then
+ perform a delayedAllOnVM command.
+
+ Setting this OID to delayedAllRebootVM (8) will cause a delayedAllOffVM
+ command to be performed. Each outlet will then wait its
+ sPDUOutletConfigVMRebootDuration before returning power to the outlet.
+
+ Setting this OID to delayedSequenceAllRebootVM (9) will cause a
+ delayedAllOffVM command to be performed. Once all outlets are off,
+ the MasterSwitch VM will then delay the sPDUMasterStatusVMRebootDuration
+ OID time, and then perform a delayedAllOnVM command.
+
+ Setting this OID to cancelAllPendingCommandsVM (10) will cause all pending
+ commands on the MasterSwitch VM to be canceled.
+
+
+ Setting this OID to audioAlarmMute (11) will temporarily silence the audible
+ alarm for the duration of the current overload condition. The audible alarm
+ will be activated on subsequent overload alarms.
+
+ Getting this OID will return the noCommandAllVM (1) value."
+ ::= { sPDUMasterControlVMEntry 3 }
+
+
+-- the sPDUMasterConfigVM group
+
+sPDUMasterConfigVMTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch VMs configurable
+ by this IP address."
+ ::= { sPDUMasterConfigVM 1 }
+
+
+sPDUMasterConfigVMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MasterConfigVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of the individual MasterSwitch VMs.
+ The number of entries is contained in the
+ sPDUMasterConfigVMTableSize OID."
+ ::= { sPDUMasterConfigVM 2 }
+
+sPDUMasterConfigVMEntry OBJECT-TYPE
+ SYNTAX MasterConfigVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch VMs to configure."
+ INDEX { sPDUMasterConfigVMIndex}
+ ::= { sPDUMasterConfigVMTable 1 }
+
+MasterConfigVMEntry ::=
+ SEQUENCE {
+ sPDUMasterConfigVMIndex INTEGER,
+ sPDUMasterConfigVMName DisplayString,
+ sPDUMasterConfigVMColdstartDelay INTEGER,
+ sPDUMasterConfigVMAudioAlarmActivated INTEGER,
+ sPDUMasterConfigVMHighLoadWarningThreshold INTEGER,
+ sPDUMasterConfigVMLowLoadWarningThreshold INTEGER,
+ sPDUMasterConfigVMOverloadRestriction INTEGER
+ }
+
+sPDUMasterConfigVMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch VM entry."
+ ::= { sPDUMasterConfigVMEntry 1 }
+
+
+sPDUMasterConfigVMName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch VM. Maximum size is 23 characters."
+ ::= { sPDUMasterConfigVMEntry 2 }
+
+sPDUMasterConfigVMColdstartDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in seconds, between when
+ power is provided to the MasterSwitch VM and
+ when the MasterSwitch VM provides basic master
+ power to the outlets.
+
+ Allowed values are:
+
+ -1 never apply power automatically.
+ 0 apply power immediately.
+ 15 apply power in 15 seconds.
+ 30 apply power in 30 seconds.
+ 45 apply power in 45 seconds.
+ 60 apply power in 60 seconds (1 minute).
+ 120 apply power in 120 seconds (2 minutes).
+ 300 apply power in 300 seconds (5 minutes).
+
+ If a value other than a supported value is provided in a
+ set request, the MasterSwitch VM interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+ ::= { sPDUMasterConfigVMEntry 3 }
+
+sPDUMasterConfigVMAudioAlarmActivated OBJECT-TYPE
+ SYNTAX INTEGER {
+ audioAlarmActiveNever (1),
+ audioAlarmActiveOnOverload (2),
+ audioAlarmActiveOnOverloadImminent (3)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to audioAlarmActiveNever (1) will disable
+ the audio alarm on the MasterSwitch VM.
+
+ Setting this OID to audioAlarmActiveOnOverload (2) will
+ activate the audio alarm on the MasterSwitch VM when an
+ overload condition is present.
+
+ Setting this OID to audioAlarmActiveOnOverloadImminent (3)
+ will activate the audio alarm on the MasterSwitch VM when
+ the load on the MasterSwitch VM has surpassed the
+ sPDUMasterConfigVMHighLoadWarningThreshold OID value."
+ ::= { sPDUMasterConfigVMEntry 4 }
+
+sPDUMasterConfigVMHighLoadWarningThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load is nearing an overload condition. It is
+ represented as a percentage of full load."
+ ::= { sPDUMasterConfigVMEntry 5 }
+
+sPDUMasterConfigVMLowLoadWarningThreshold OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load is nearing a low consumption condition. It is
+ represented as a percentage of full load."
+ ::= { sPDUMasterConfigVMEntry 6 }
+
+sPDUMasterConfigVMOverloadRestriction OBJECT-TYPE
+ SYNTAX INTEGER {
+ alwaysAllowTurnON (1),
+ restrictOnWarning (2),
+ restrictOnOverload (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID controls the behavior of the MasterSwitch VM
+ when an overload condition is possible and additional
+ outlets are requested to be turned on.
+
+ Setting this OID to alwaysAllowTurnON (1) will always allow
+ the outlets to turn on.
+
+ Setting this OID to restrictOnWarning (2) will not allow
+ outlets to turn on if the sPDUMasterConfigVMHighLoadWarningThreshold
+ OID is exceeded.
+
+ Setting this OID to restrictOnOverload (3) will not allow
+ outlets to turn on if the MasterSwitch Vm is in an
+ overload condition."
+ ::= { sPDUMasterConfigVMEntry 7 }
+
+-- the sPDUMasterStatusVM group
+
+sPDUMasterStatusVMTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch VMs at
+ this IP address."
+ ::= { sPDUMasterStatusVM 1 }
+
+
+sPDUMasterStatusVMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MasterStatusVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for gathering of status from the individual
+ MasterSwitch VMs. The number of entries is contained
+ in the sPDUMasterStatusVMTableSize OID."
+ ::= { sPDUMasterStatusVM 2 }
+
+sPDUMasterStatusVMEntry OBJECT-TYPE
+ SYNTAX MasterStatusVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch VMs to gather status from."
+ INDEX { sPDUMasterStatusVMIndex}
+ ::= { sPDUMasterStatusVMTable 1 }
+
+MasterStatusVMEntry ::=
+ SEQUENCE {
+ sPDUMasterStatusVMIndex INTEGER,
+ sPDUMasterStatusVMName DisplayString,
+ sPDUMasterStatusVMCommandPending INTEGER,
+ sPDUMasterStatusVMOverloadCondition INTEGER,
+ sPDUMasterStatusVMLowLoadCondition INTEGER,
+ sPDUMasterStatusVMCurrentLoad INTEGER,
+ sPDUMasterStatusVMMaxLoad INTEGER,
+ sPDUMasterStatusVMOutletCount INTEGER,
+ sPDUMasterStatusVMRebootDuration INTEGER
+ }
+
+sPDUMasterStatusVMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch VM entry."
+ ::= { sPDUMasterStatusVMEntry 1 }
+
+sPDUMasterStatusVMName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch VM. Maximum size is 23 characters."
+ ::= { sPDUMasterStatusVMEntry 2 }
+
+sPDUMasterStatusVMCommandPending OBJECT-TYPE
+ SYNTAX INTEGER {
+ commandPendingMasterTrueVM (1),
+ commandPendingMasterFalseVM (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return commandPendingMasterTrueVM (1)
+ if the MasterSwitch VM has a pending command on any of its
+ outlets.
+
+ commandPendingMasterFalseVM (2) will be returned if there are
+ no pending commands."
+ ::= { sPDUMasterStatusVMEntry 3 }
+
+sPDUMasterStatusVMOverloadCondition OBJECT-TYPE
+ SYNTAX INTEGER {
+ overloadConditionTrueVM (1),
+ overloadConditionFalseVM (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return overloadConditionTrueVM (1)
+ if the sPDUMasterConfigVMHighLoadWarningThreshold OID is
+ violated.
+
+ overloadConditionFalseVM (2) will be returned if the
+ sPDUMasterConfigVMHighLoadWarningThreshold OID is not
+ violated."
+ ::= { sPDUMasterStatusVMEntry 4 }
+
+sPDUMasterStatusVMLowLoadCondition OBJECT-TYPE
+ SYNTAX INTEGER {
+ lowLoadConditionTrueVM (1),
+ lowLoadConditionFalseVM (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return lowLoadConditionTrueVM (1)
+ if the sPDUMasterConfigVMLowLoadWarningThreshold OID is
+ violated.
+
+ lowLoadConditionFalseVM (2) will be returned if the
+ sPDUMasterConfigVMHighLoadWarningThreshold OID is not
+ violated. "
+ ::= { sPDUMasterStatusVMEntry 5 }
+
+sPDUMasterStatusVMCurrentLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the total amount of power
+ being consumed by the load. It is represented as a
+ percentage of full load."
+ ::= { sPDUMasterStatusVMEntry 6 }
+
+sPDUMasterStatusVMMaxLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the total amount of power
+ that this MasterSwitch VM can provide. It is represented
+ in Amps."
+ ::= { sPDUMasterStatusVMEntry 7 }
+
+sPDUMasterStatusVMOutletCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the number of controllable
+ outlets for this MasterSwitch VM."
+ ::= { sPDUMasterStatusVMEntry 8 }
+
+sPDUMasterStatusVMRebootDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the largest
+ sPDUOutletConfigVMRebootDuration OID time
+ for this MasterSwitch VM."
+ ::= { sPDUMasterStatusVMEntry 9 }
+
+-- the sPDUOutletControlVM group
+
+
+sPDUOutletControlVMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletControlVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of individual outlet switches. The number of
+ entries is contained in the sPDUMasterStatusOutletCount OID."
+ ::= { sPDUOutletControlVM 1 }
+
+sPDUOutletControlVMEntry OBJECT-TYPE
+ SYNTAX OutletControlVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to control."
+ INDEX { sPDUOutletControlVMIndex, sPDUOutletControlVMOutletIndex }
+ ::= { sPDUOutletControlVMTable 1 }
+
+OutletControlVMEntry ::=
+ SEQUENCE {
+ sPDUOutletControlVMIndex INTEGER,
+ sPDUOutletControlVMName DisplayString,
+ sPDUOutletControlVMOutletIndex INTEGER,
+ sPDUOutletControlVMOutletName DisplayString,
+ sPDUOutletControlVMOutletCommand INTEGER
+ }
+
+sPDUOutletControlVMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch VM."
+ ::= { sPDUOutletControlVMEntry 1 }
+
+sPDUOutletControlVMName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch VM. Maximum size is 23 characters.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletControlVMEntry 2 }
+
+sPDUOutletControlVMOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletControlVMEntry 3 }
+
+sPDUOutletControlVMOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is 23 characters.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletControlVMEntry 4 }
+
+sPDUOutletControlVMOutletCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ immediateOnVM (1),
+ immediateOffVM (2),
+ immediateRebootVM (3),
+ delayedOnVM (4),
+ delayedOffVM (5),
+ delayedRebootVM (6),
+ cancelPendingCommandVM (7)
+
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the immediateOnVM (1) value will be returned.
+ If the outlet is off, the immediateOffVM (2) value will be
+ returned.
+
+
+ Setting this variable to immediateOnVM (1) will immediately turn the outlet on.
+
+ Setting this variable to immediateOffVM (2) will immediately turn the outlet off.
+
+ Setting this variable to immediateRebootVM (3) will immediately reboot the outlet.
+
+ Setting this variable to delayedOnVM (4) will turn the outlet on
+ after the sPDUOutletConfigVMPowerOnTime OID time has elapsed.
+
+ Setting this variable to delayedOffVM (5) will turn the outlet off
+ after the sPDUOutletConfigVMPowerOffTime OID time has elapsed.
+
+ Setting this variable to delayedRebootVM (6) will cause the
+ MasterSwitch VM to perform a delayedOffVM command, wait the
+ sPDUOutletConfigVMRebootDuration OID time, and then perform the
+ immediateOnVM command.
+
+ Setting this variable to cancelPendingCommandVM (7) will cause any
+ pending command to this outlet to be canceled."
+ ::= { sPDUOutletControlVMEntry 5 }
+
+-- the sPDUOutletConfigVM group
+
+sPDUOutletConfigVMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletConfigVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual outlets. The number of
+ entries is contained in the sPDUMasterStatusOutletCount OID."
+ ::= { sPDUOutletConfigVM 1 }
+
+sPDUOutletConfigVMEntry OBJECT-TYPE
+ SYNTAX OutletConfigVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to configure."
+ INDEX { sPDUOutletConfigVMIndex, sPDUOutletConfigVMOutletIndex }
+ ::= { sPDUOutletConfigVMTable 1 }
+
+OutletConfigVMEntry ::=
+ SEQUENCE {
+ sPDUOutletConfigVMIndex INTEGER,
+ sPDUOutletConfigVMName DisplayString,
+ sPDUOutletConfigVMOutletIndex INTEGER,
+ sPDUOutletConfigVMOutletName DisplayString,
+ sPDUOutletConfigVMPowerOnTime INTEGER,
+ sPDUOutletConfigVMPowerOffTime INTEGER,
+ sPDUOutletConfigVMRebootDuration INTEGER
+ }
+
+sPDUOutletConfigVMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch VM."
+ ::= { sPDUOutletConfigVMEntry 1 }
+
+sPDUOutletConfigVMName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch VM. Maximum size is 23 characters."
+ ::= { sPDUOutletConfigVMEntry 2 }
+
+sPDUOutletConfigVMOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletConfigVMEntry 3 }
+
+
+sPDUOutletConfigVMOutletName OBJECT-TYPE
+ SYNTAX DisplayString ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is 23 characters."
+ ::= { sPDUOutletConfigVMEntry 4 }
+
+sPDUOutletConfigVMPowerOnTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet will delay
+ powering on at coldstart or when a command that requires
+ a turn-on delay is issued.
+
+ Allowed values are:
+
+ -1 never power on.
+ 0 power on immediately.
+ 15 power on 15 seconds after being commanded.
+ 30 power on 30 seconds after being commanded.
+ 45 power on 45 seconds after being commanded.
+ 60 power on 60 seconds (1 minute) after being commanded.
+ 120 power on 120 seconds (2 minutes) after being commanded.
+ 300 power on 300 seconds (5 minutes) after being commanded.
+
+ If a value other than a supported value is provided in a
+ set request, the MasterSwitch VM interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+ ::= { sPDUOutletConfigVMEntry 5 }
+
+
+sPDUOutletConfigVMPowerOffTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet will delay
+ powering off when a command that requires
+ a turn-off delay is issued.
+
+
+ Allowed values are:
+
+ -1 never power off automatically.
+ 0 power off immediately.
+ 15 power off 15 seconds after being commanded.
+ 30 power off 30 seconds after being commanded.
+ 45 power off 45 seconds after being commanded.
+ 60 power off 60 seconds (1 minute) after being commanded.
+ 120 power off 120 seconds (2 minutes) after being commanded.
+ 300 power off 300 seconds (5 minutes) after being commanded.
+
+ If a value other than a supported value is provided in a
+ set request, the MasterSwitch VM interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+ ::= { sPDUOutletConfigVMEntry 6 }
+
+sPDUOutletConfigVMRebootDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "During a reboot sequence, power is turned off and then
+ back on. This OID defines the amount of time to wait,
+ in seconds, after turning the power off, at the start
+ of the sequence, before turning power back on, at the
+ end of the reboot sequence.
+
+ Allowed values are:
+
+ 5 wait 5 seconds between off/on.
+ 10 wait 10 seconds between off/on.
+ 15 wait 15 seconds between off/on.
+ 20 wait 20 seconds between off/on.
+ 30 wait 30 seconds between off/on.
+ 45 wait 45 seconds between off/on.
+ 60 wait 60 seconds (1 minute) between off/on.
+
+ If a value other than a supported value is provided in a
+ set request, the MasterSwitch VM interprets it as the next lower
+ acceptable value. If the provided value is lower than
+ the lowest acceptable value, the lowest acceptable
+ value is used."
+ ::= { sPDUOutletConfigVMEntry 7 }
+
+-- the sPDUOutletStatusVM group
+
+sPDUOutletStatusVMTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletStatusVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting of status of individual outlets. The number of
+ entries is contained in the sPDUMasterStatusOutletCount OID."
+ ::= { sPDUOutletStatusVM 1 }
+
+sPDUOutletStatusVMEntry OBJECT-TYPE
+ SYNTAX OutletStatusVMEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to gather status from."
+ INDEX { sPDUOutletStatusVMIndex, sPDUOutletStatusVMOutletIndex }
+ ::= { sPDUOutletStatusVMTable 1 }
+
+OutletStatusVMEntry ::=
+ SEQUENCE {
+ sPDUOutletStatusVMIndex INTEGER,
+ sPDUOutletStatusVMName DisplayString,
+ sPDUOutletStatusVMOutletIndex INTEGER,
+ sPDUOutletStatusVMOutletName DisplayString,
+ sPDUOutletStatusVMOutletState INTEGER,
+ sPDUOutletStatusVMCommandPending INTEGER
+ }
+
+sPDUOutletStatusVMIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch VM."
+ ::= { sPDUOutletStatusVMEntry 1 }
+
+sPDUOutletStatusVMName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch VM. Maximum size is 23 characters."
+ ::= { sPDUOutletStatusVMEntry 2 }
+
+sPDUOutletStatusVMOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletStatusVMEntry 3 }
+
+sPDUOutletStatusVMOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is 23 characters."
+ ::= { sPDUOutletStatusVMEntry 4 }
+
+sPDUOutletStatusVMOutletState OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletStatusVMOn (1),
+ outletStatusVMOff (2)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the outletStatusOnVM (1) value will be returned.
+ If the outlet is off, the outletStatusOffVM (2) value will be
+ returned. "
+ ::= { sPDUOutletStatusVMEntry 5 }
+
+sPDUOutletStatusVMCommandPending OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletStatusVMCommandPending (1),
+ outletStatusVMNoCommandPending (2)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the command pending
+ state of the outlet. If a command is pending on the
+ outlet, the outletStatusVMCommandPending (1) value
+ will be returned. If there is not a command pending
+ on the outlet, the outletStatusVMNoCommandPending (2)
+ will be returned."
+ ::= { sPDUOutletStatusVMEntry 6 }
+
+-- the sPDUIdentMSP group
+
+sPDUIdentMSPTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch pluses controllable
+ by this IP address."
+ ::= { sPDUIdentMSP 1 }
+
+
+sPDUIdentMSPTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IdentMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for query of the individual MasterSwitch pluses.
+ The number of entries is contained in the
+ sPDUIdentMSPTableSize OID."
+ ::= { sPDUIdentMSP 2 }
+
+sPDUIdentMSPEntry OBJECT-TYPE
+ SYNTAX IdentMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch pluses to query."
+ INDEX { sPDUIdentMSPIndex}
+ ::= { sPDUIdentMSPTable 1 }
+
+IdentMSPEntry ::=
+ SEQUENCE {
+ sPDUIdentMSPIndex INTEGER,
+ sPDUIdentNameMSP DisplayString,
+ sPDUIdentHardwareRevMSP DisplayString,
+ sPDUIdentFirmwareRevMSP DisplayString,
+ sPDUIdentDateOfManufactureMSP DisplayString,
+ sPDUIdentModelNumberMSP DisplayString,
+ sPDUIdentSerialNumberMSP DisplayString
+ }
+
+sPDUIdentMSPIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus entry."
+ ::= { sPDUIdentMSPEntry 1 }
+
+sPDUIdentNameMSP OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUIdentMSPEntry 2 }
+
+sPDUIdentHardwareRevMSP OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware version of the MasterSwitch plus.
+ This value is set at the factory."
+ ::= { sPDUIdentMSPEntry 3 }
+
+sPDUIdentFirmwareRevMSP OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An 6-character ID string identifying the MasterSwitch plus
+ firmware version. This value is set at the factory."
+ ::= { sPDUIdentMSPEntry 4 }
+
+sPDUIdentDateOfManufactureMSP OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the MasterSwitch plus was manufactured in mm/dd/yyyy format.
+ This value is set at the factory. "
+ ::= { sPDUIdentMSPEntry 5 }
+
+sPDUIdentModelNumberMSP OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 17-character string identifying the model number of
+ the MasterSwitch plus. This value is set at the factory."
+ ::= { sPDUIdentMSPEntry 6 }
+
+sPDUIdentSerialNumberMSP OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 17-character string identifying the serial number of
+ the MasterSwitch plus. This value is set at the factory."
+ ::= { sPDUIdentMSPEntry 7 }
+
+
+-- the sPDUMasterControlMSP group
+
+sPDUMasterControlMSPTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch pluses controllable
+ by this IP address."
+ ::= { sPDUMasterControlMSP 1 }
+
+sPDUMasterControlMSPTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MasterControlMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of the individual MasterSwitch pluses.
+ The number of entries is contained in the
+ sPDUMasterControlMSPTableSize OID."
+ ::= { sPDUMasterControlMSP 2 }
+
+sPDUMasterControlMSPEntry OBJECT-TYPE
+ SYNTAX MasterControlMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch pluses to control."
+ INDEX { sPDUMasterControlMSPIndex}
+ ::= { sPDUMasterControlMSPTable 1 }
+
+MasterControlMSPEntry ::=
+ SEQUENCE {
+ sPDUMasterControlMSPIndex INTEGER,
+ sPDUMasterControlMSPName DisplayString,
+ sPDUMasterControlMSPCommand INTEGER
+ }
+
+sPDUMasterControlMSPIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus entry."
+ ::= { sPDUMasterControlMSPEntry 1 }
+
+sPDUMasterControlMSPName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUMasterControlMSPEntry 2 }
+
+sPDUMasterControlMSPCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ noCommandAllMSP (1),
+ immediateAllOnMSP (2),
+ sequencedAllOnMSP (3),
+ immediateAllOffMSP (4),
+ gracefulAllRebootMSP (5),
+ immediateAllRebootMSP (6),
+ gracefulAllShutdownMSP (7),
+ overrideAllBatCapThreshMSP (8),
+ cancelAllPendingCommandsMSP (9),
+ restoreFactoryDefaultsMSP (10)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to immediateAllOnMSP (2) will turn all outlets
+ on immediately.
+
+ Setting this OID to sequencedAllOnMSP (3) will turn all outlets
+ on as defined by each outlet's sPDUOutletConfigMSPPowerOnDelay OID value.
+
+ Setting this OID to immediateAllOffMSP (4) will turn all outlets
+ off immediately.
+
+ Setting this OID to gracefulAllRebootMSP (5) will reboot all outlets
+ (after the device running PowerChute confirms shutdown) as defined
+ by each outlet's sPDUOutletConfigMSPRebootDuration OID time value.
+
+ Setting this OID to immediateAllRebootMSP (6) will reboot all outlets
+ immediately.
+
+ Setting this OID to gracefulAllShutdownMSP (7) will shutdown all outlets
+ (after the device running PowerChute confirms shutdown) as defined
+ by each outlet's sPDUOutletConfigMSPPowerOffDelay OID time value. Each
+ outlet will then turn on after the sum of its
+ sPDUOutletConfigMSPRestartDelay and sPDUOutletConfigMSPPowerOnDelay OID
+ values.
+
+ Setting this OID to overrideAllBatCapThreshMSP (8) will cause the
+ outlet to ignore the Battery Capacity Threshold and proceed turning on
+ the outlets as defined by each outlet's sPDUOutletConfigMSPPowerOnDelay
+ OID value.
+
+ Setting this OID to cancelAllPendingCommandsMSP (9) will cause all pending
+ commands on the MasterSwitch plus to be canceled.
+
+ Setting this OID to restoreFactoryDefaultsMSP (10) will cause the settings of
+ the MasterSwitch plus to be restored to the factory defaults.
+
+ Getting this OID will return the noCommandAllMSP (1) value."
+ ::= { sPDUMasterControlMSPEntry 3 }
+
+
+-- the sPDUMasterConfigMSP group
+
+sPDUMasterConfigMSPTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch pluses configurable
+ by this IP address."
+ ::= { sPDUMasterConfigMSP 1 }
+
+sPDUMasterConfigMSPTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MasterConfigMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of the individual MasterSwitch pluses.
+ The number of entries is contained in the
+ sPDUMasterConfigMSPTableSize OID."
+ ::= { sPDUMasterConfigMSP 2 }
+
+sPDUMasterConfigMSPEntry OBJECT-TYPE
+ SYNTAX MasterConfigMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch pluses to configure."
+ INDEX { sPDUMasterConfigMSPIndex}
+ ::= { sPDUMasterConfigMSPTable 1 }
+
+MasterConfigMSPEntry ::=
+ SEQUENCE {
+ sPDUMasterConfigMSPIndex INTEGER,
+ sPDUMasterConfigMSPName DisplayString,
+ sPDUMasterConfigMSPPowerOnTimeDelay INTEGER,
+ sPDUMasterConfigMSPManualButton INTEGER
+ }
+
+sPDUMasterConfigMSPIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus entry."
+ ::= { sPDUMasterConfigMSPEntry 1 }
+
+sPDUMasterConfigMSPName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. Maximum size is 23 characters."
+ ::= { sPDUMasterConfigMSPEntry 2 }
+
+sPDUMasterConfigMSPPowerOnTimeDelay OBJECT-TYPE
+ SYNTAX INTEGER (0..9999)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in seconds, between when
+ power is provided to the MasterSwitch plus and
+ when the MasterSwitch plus provides basic master
+ power to the outlets.
+
+ Allowed values are:
+
+ 0 - 9999 seconds (0 - 2hrs, 46 mins, 39 secs).
+ 0 indicates to apply power immediately."
+ ::= { sPDUMasterConfigMSPEntry 3 }
+
+
+sPDUMasterConfigMSPManualButton OBJECT-TYPE
+ SYNTAX INTEGER {
+ manualButtonDisabled (1),
+ manualButtonEnabled (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to manualButtonDisabled (1) will disable
+ the manual button on the MasterSwitch plus.
+
+ Setting this OID to manualButtonEnabled (2) will enable
+ the manual button on the MasterSwitch plus."
+ ::= { sPDUMasterConfigMSPEntry 4 }
+
+-- the sPDUMasterStatusMSP group
+
+sPDUMasterStatusMSPTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of MasterSwitch pluses at
+ this IP address."
+ ::= { sPDUMasterStatusMSP 1 }
+
+
+sPDUMasterStatusMSPTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF MasterStatusMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for gathering of status from the individual
+ MasterSwitch pluses. The number of entries is contained
+ in the sPDUMasterStatusMSPTableSize OID."
+ ::= { sPDUMasterStatusMSP 2 }
+
+sPDUMasterStatusMSPEntry OBJECT-TYPE
+ SYNTAX MasterStatusMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The MasterSwitch pluses to gather status from."
+ INDEX { sPDUMasterStatusMSPIndex}
+ ::= { sPDUMasterStatusMSPTable 1 }
+
+MasterStatusMSPEntry ::=
+ SEQUENCE {
+ sPDUMasterStatusMSPIndex INTEGER,
+ sPDUMasterStatusMSPName DisplayString,
+ sPDUMasterStatusMSPOutletCount INTEGER
+ }
+
+sPDUMasterStatusMSPIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus entry."
+ ::= { sPDUMasterStatusMSPEntry 1 }
+
+sPDUMasterStatusMSPName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUMasterStatusMSPEntry 2 }
+
+sPDUMasterStatusMSPOutletCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the number of controllable
+ outlets for this MasterSwitch plus."
+ ::= { sPDUMasterStatusMSPEntry 3 }
+
+-- the sPDUOutletControlMSP group
+
+sPDUOutletControlMSPTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletControlMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of individual outlet switches. The number of
+ entries is contained in the sPDUMasterStatusMSPOutletCount OID."
+ ::= { sPDUOutletControlMSP 1 }
+
+sPDUOutletControlMSPEntry OBJECT-TYPE
+ SYNTAX OutletControlMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to control."
+ INDEX { sPDUOutletControlMSPIndex, sPDUOutletControlMSPOutletIndex }
+ ::= { sPDUOutletControlMSPTable 1 }
+
+OutletControlMSPEntry ::=
+ SEQUENCE {
+ sPDUOutletControlMSPIndex INTEGER,
+ sPDUOutletControlMSPName DisplayString,
+ sPDUOutletControlMSPOutletIndex INTEGER,
+ sPDUOutletControlMSPOutletName DisplayString,
+ sPDUOutletControlMSPOutletCommand INTEGER
+ }
+
+sPDUOutletControlMSPIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus."
+ ::= { sPDUOutletControlMSPEntry 1 }
+
+sPDUOutletControlMSPName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUOutletControlMSPEntry 2 }
+
+sPDUOutletControlMSPOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletControlMSPEntry 3 }
+
+sPDUOutletControlMSPOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. The maximum size is
+ 23 characters. The name is set by using the
+ sPDUOutletConfigMSPallOutletName OID.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletControlMSPEntry 4 }
+
+sPDUOutletControlMSPOutletCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ immediateOnMSP (1),
+ delayedOnMSP (2),
+ immediateOffMSP (3),
+ gracefulRebootMSP (4),
+ immediateRebootMSP (5),
+ gracefulshutdownMSP (6),
+ overrideBatCapThreshMSP (7),
+ cancelPendingCommandMSP (8)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the immediateOnMSP (1) value will be returned.
+ If the outlet is off, the immediateOffMSP (3) value will be
+ returned.
+
+ Setting this variable to immediateOnMSP (1) will immediately turn the outlet on.
+
+ Setting this variable to delayedOnMSP (2) will turn the outlet on
+ after the sPDUOutletConfigMSPPowerOnDelay OID time has elapsed.
+
+ Setting this variable to immediateOffMSP (3) will immediately turn the outlet off.
+
+ Setting this variable to gracefulRebootMSP (4) will cause the outlet to wait for
+ device confirmation (if applicable) and then turn the outlet off after the
+ sPDUOutletConfigMSPPowerOffDelay OID time has elapsed. The outlet will then turn
+ on after the sPDUOutletConfigMSPRebootDuration OID time has elapsed.
+
+ Setting this variable to immediateRebootMSP (5) will immediately reboot the outlet.
+
+ Setting this variable to gracefulshutdownMSP (6) will cause the outlet to wait for
+ device confirmation (if applicable) and then turn the outlet off after the
+ sPDUOutletConfigMSPPowerOffDelay OID time has elapsed. The outlet will then turn
+ on after the sum of the sPDUOutletConfigMSPRestartTime OID time and the
+ sPDUOutletConfigMSPPowerOnDelay OID time has elapsed.
+
+ Setting this variable to overrideBatCapThreshMSP (7) will cause the outlet to
+ ignore the Battery Capacity Threshold and proceed waiting on the
+ sPDUOutletConfigMSPPowerOnDelay OID time before turning the outlet on.
+
+ Setting this variable to cancelPendingCommandMSP (8) will cause any
+ pending command to this outlet to be canceled."
+ ::= { sPDUOutletControlMSPEntry 5 }
+
+-- the sPDUOutletConfigMSPall group
+
+sPDUOutletConfigMSPallTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletConfigMSPallEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual outlets. The number of
+ entries is contained in the sPDUMasterStatusMSPOutletCount OID."
+ ::= { sPDUOutletConfigMSPall 1 }
+
+sPDUOutletConfigMSPallEntry OBJECT-TYPE
+ SYNTAX OutletConfigMSPallEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to configure."
+ INDEX { sPDUOutletConfigMSPallIndex, sPDUOutletConfigMSPallOutletIndex }
+ ::= { sPDUOutletConfigMSPallTable 1 }
+
+OutletConfigMSPallEntry ::=
+ SEQUENCE {
+ sPDUOutletConfigMSPallIndex INTEGER,
+ sPDUOutletConfigMSPallName DisplayString,
+ sPDUOutletConfigMSPallOutletIndex INTEGER,
+ sPDUOutletConfigMSPallOutletName DisplayString,
+ sPDUOutletConfigMSPallOutletCtrlMode INTEGER
+ }
+
+sPDUOutletConfigMSPallIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus."
+ ::= { sPDUOutletConfigMSPallEntry 1 }
+
+sPDUOutletConfigMSPallName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUOutletConfigMSPallEntry 2 }
+
+sPDUOutletConfigMSPallOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletConfigMSPallEntry 3 }
+
+sPDUOutletConfigMSPallOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is 23 characters."
+ ::= { sPDUOutletConfigMSPallEntry 4 }
+
+sPDUOutletConfigMSPallOutletCtrlMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ modeGracefulShutdown (1),
+ modeAnnunciator (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to modeGracefulShutdown (1) will put this
+ outlet into the Graceful Shutdown control mode.
+
+ Setting this OID to modeAnnunciator (2) will put this outlet
+ into the Annunciator control mode."
+ ::= { sPDUOutletConfigMSPallEntry 5 }
+
+
+-- the sPDUOutConfigMSPgs group
+
+sPDUOutletConfigMSPgsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletConfigMSPgsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual outlets. The number of
+ entries is contained in the sPDUMasterStatusMSPOutletCount OID."
+ ::= { sPDUOutletConfigMSPgs 1 }
+
+sPDUOutletConfigMSPgsEntry OBJECT-TYPE
+ SYNTAX OutletConfigMSPgsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to configure."
+ INDEX { sPDUOutletConfigMSPgsIndex, sPDUOutletConfigMSPgsOutletIndex }
+ ::= { sPDUOutletConfigMSPgsTable 1 }
+
+OutletConfigMSPgsEntry ::=
+ SEQUENCE {
+ sPDUOutletConfigMSPgsIndex INTEGER,
+ sPDUOutletConfigMSPgsName DisplayString,
+ sPDUOutletConfigMSPgsOutletIndex INTEGER,
+ sPDUOutletConfigMSPgsOutletName DisplayString,
+ sPDUOutletConfigMSPgsOutletCtrlMode INTEGER,
+ sPDUOutletConfigMSPgsDeviceConfirm INTEGER,
+ sPDUOutletConfigMSPgsLowBattWarning INTEGER,
+ sPDUOutletConfigMSPgsLowBattMult INTEGER,
+ sPDUOutletConfigMSPgsRestartDelay INTEGER,
+ sPDUOutletConfigMSPgsPowerOnDelay INTEGER,
+ sPDUOutletConfigMSPgsPowerOffDelay INTEGER,
+ sPDUOutletConfigMSPgsBattCapThresh INTEGER,
+ sPDUOutletConfigMSPgsRebootDuration INTEGER
+ }
+
+sPDUOutletConfigMSPgsIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus."
+ ::= { sPDUOutletConfigMSPgsEntry 1 }
+
+sPDUOutletConfigMSPgsName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUOutletConfigMSPgsEntry 2 }
+
+sPDUOutletConfigMSPgsOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletConfigMSPgsEntry 3 }
+
+sPDUOutletConfigMSPgsOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. The maximum size is
+ 23 characters. The name is set by using the
+ sPDUOutletConfigMSPallOutletName OID.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletConfigMSPgsEntry 4 }
+
+sPDUOutletConfigMSPgsOutletCtrlMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ modeGracefulShutdown (1),
+ modeAnnunciator (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Control Mode of the outlet.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletConfigMSPgsEntry 5 }
+
+sPDUOutletConfigMSPgsDeviceConfirm OBJECT-TYPE
+ SYNTAX INTEGER {
+ deviceConfirmNo (1),
+ deviceConfirmYes (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to deviceConfirmNo (1) cause the outlet to
+ NOT wait for device confirmation while performing graceful
+ operations.
+
+ Setting this OID to deviceConfirmYes (2) cause the outlet to
+ wait for device confirmation while performing graceful
+ operations."
+ ::= { sPDUOutletConfigMSPgsEntry 6 }
+
+sPDUOutletConfigMSPgsLowBattWarning OBJECT-TYPE
+ SYNTAX INTEGER (-2..9999)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in 6 second intervals, between
+ when the UPS goes on battery and the power down sequence for
+ the outlet is initiated.
+
+ Allowed values are:
+
+ -2 - Never initiate the power down sequence on low battery warning.
+ -1 - Initiate power down sequence based on remaining runtime.
+ 1 - 9999 six second intervals (6 secs - 16hrs, 39 mins, 54 secs).
+ 0 indicates to immediately initiate power down sequence on low
+ battery warning."
+ ::= { sPDUOutletConfigMSPgsEntry 7 }
+
+sPDUOutletConfigMSPgsLowBattMult OBJECT-TYPE
+ SYNTAX INTEGER (1..7)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " Only applicable if sPDUOutletConfigMSPgsLowBattWarning OID is
+ set to -1 (On Runtime Remaining).
+
+ Allows you to set the value to stagger the shutdown sequence of the outlets.
+ 1 provides the longest delay (the outlet to shutoff first), and 7 would
+ provide the shortest delay (the outlet to shut off last).
+
+ Allowed values are:
+ 1 - 7."
+ ::= { sPDUOutletConfigMSPgsEntry 8 }
+
+sPDUOutletConfigMSPgsRestartDelay OBJECT-TYPE
+ SYNTAX INTEGER (-1..9999)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in 6 minute intervals, between
+ when the outlet is turned off and the outlet is turned back on
+ when performing a Graceful Shutdown.
+
+ Allowed values are:
+
+ -1 - Never turn outlet back on after a Graceful shutdown.
+ 0 - 9999 six minute intervals (0 - 999hrs, 54 mins)."
+ ::= { sPDUOutletConfigMSPgsEntry 9 }
+
+sPDUOutletConfigMSPgsPowerOnDelay OBJECT-TYPE
+ SYNTAX INTEGER (-1..9999)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in seconds, between the UPS entering
+ normal (on-line) state and the outlet being powered on.
+
+ Allowed values are:
+
+ -1 - Remain Off when the UPS enters the on-line state.
+ 0 - 9999 seconds (0 - 2 hrs, 46 mins, 39 secs)."
+ ::= { sPDUOutletConfigMSPgsEntry 10 }
+
+
+sPDUOutletConfigMSPgsPowerOffDelay OBJECT-TYPE
+ SYNTAX INTEGER (0..9999)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in seconds, between when the server
+ shuts down and the outlet is powered off.
+
+ Allowed values are:
+
+ 0 - 9999 seconds (0 - 2 hrs, 46 mins, 39 secs)."
+ ::= { sPDUOutletConfigMSPgsEntry 11 }
+
+sPDUOutletConfigMSPgsBattCapThresh OBJECT-TYPE
+ SYNTAX INTEGER (0..100)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The minimum battery capacity, as a percent (0-100%), required
+ of the UPS before an outlet will be allowed to power on.
+
+ Allowed values are:
+
+ 0 - 100 percent."
+ ::= { sPDUOutletConfigMSPgsEntry 12 }
+
+sPDUOutletConfigMSPgsRebootDuration OBJECT-TYPE
+ SYNTAX INTEGER (0..9999)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of delay, in seconds, from outlet off until
+ outlet on during a reboot.
+
+ Allowed values are:
+
+ 0 - 9999 seconds (0 - 2 hrs, 46 mins, 39 secs)."
+ ::= { sPDUOutletConfigMSPgsEntry 13 }
+
+
+-- the sPDUOutConfigMSPannun group
+
+sPDUOutletConfigMSPannunTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletConfigMSPannunEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual outlets. The number of
+ entries is contained in the sPDUMasterStatusMSPOutletCount OID."
+ ::= { sPDUOutletConfigMSPannun 1 }
+
+sPDUOutletConfigMSPannunEntry OBJECT-TYPE
+ SYNTAX OutletConfigMSPannunEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to configure."
+ INDEX { sPDUOutletConfigMSPannunIndex, sPDUOutletConfigMSPannunOutletIndex }
+ ::= { sPDUOutletConfigMSPannunTable 1 }
+
+OutletConfigMSPannunEntry ::=
+ SEQUENCE {
+ sPDUOutletConfigMSPannunIndex INTEGER,
+ sPDUOutletConfigMSPannunName DisplayString,
+ sPDUOutletConfigMSPannunOutletIndex INTEGER,
+ sPDUOutletConfigMSPannunOutletName DisplayString,
+ sPDUOutletConfigMSPannunOutletCtrlMode INTEGER,
+ sPDUOutletConfigMSPannunInitialState INTEGER,
+ sPDUOutletConfigMSPannunAlarmActionDly INTEGER
+ }
+
+sPDUOutletConfigMSPannunIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus."
+ ::= { sPDUOutletConfigMSPannunEntry 1 }
+
+sPDUOutletConfigMSPannunName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUOutletConfigMSPannunEntry 2 }
+
+sPDUOutletConfigMSPannunOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletConfigMSPannunEntry 3 }
+
+sPDUOutletConfigMSPannunOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. The maximum size is
+ 23 characters. The name is set by using the
+ sPDUOutletConfigMSPallOutletName OID.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletConfigMSPannunEntry 4 }
+
+sPDUOutletConfigMSPannunOutletCtrlMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ modeGracefulShutdown (1),
+ modeAnnunciator (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Control Mode of the outlet.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletConfigMSPannunEntry 5 }
+
+sPDUOutletConfigMSPannunInitialState OBJECT-TYPE
+ SYNTAX INTEGER {
+ initialStateOff (1),
+ initialStateOn (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to initialStateOff (1) causes the outlet
+ to default to off when in the non-alarmed condition.
+
+ Setting this OID to initialStateOn (2) causes the outlet
+ to default to on when in the non-alarmed condition."
+ ::= { sPDUOutletConfigMSPannunEntry 6 }
+
+sPDUOutletConfigMSPannunAlarmActionDly OBJECT-TYPE
+ SYNTAX INTEGER (0..9999)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ " The amount of time, in seconds, that an enabled Measure-UPS
+ alarm must be asserted before an alarm condition is recognized.
+
+ Allowed values are:
+
+ 0 - 9999 seconds (0 - 2 hrs, 46 mins, 39 secs)."
+ ::= { sPDUOutletConfigMSPannunEntry 7 }
+
+
+-- the sPDUOutConfigMSPmups group
+
+sPDUOutletConfigMSPmupsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletConfigMSPmupsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual outlets. The number of
+ entries is contained in the sPDUMasterStatusMSPOutletCount OID."
+ ::= { sPDUOutletConfigMSPmups 1 }
+
+sPDUOutletConfigMSPmupsEntry OBJECT-TYPE
+ SYNTAX OutletConfigMSPmupsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to configure."
+ INDEX { sPDUOutletConfigMSPmupsIndex, sPDUOutletConfigMSPmupsOutletIndex }
+ ::= { sPDUOutletConfigMSPmupsTable 1 }
+
+OutletConfigMSPmupsEntry ::=
+ SEQUENCE {
+ sPDUOutletConfigMSPmupsIndex INTEGER,
+ sPDUOutletConfigMSPmupsName DisplayString,
+ sPDUOutletConfigMSPmupsOutletIndex INTEGER,
+ sPDUOutletConfigMSPmupsOutletName DisplayString,
+ sPDUOutletConfigMSPmupsZone1 INTEGER,
+ sPDUOutletConfigMSPmupsZone2 INTEGER,
+ sPDUOutletConfigMSPmupsZone3 INTEGER,
+ sPDUOutletConfigMSPmupsZone4 INTEGER,
+ sPDUOutletConfigMSPmupsP1LowHum INTEGER,
+ sPDUOutletConfigMSPmupsP1HiHum INTEGER,
+ sPDUOutletConfigMSPmupsP1LowTemp INTEGER,
+ sPDUOutletConfigMSPmupsP1HiTemp INTEGER,
+ sPDUOutletConfigMSPmupsP2LowHum INTEGER,
+ sPDUOutletConfigMSPmupsP2HiHum INTEGER,
+ sPDUOutletConfigMSPmupsP2LowTemp INTEGER,
+ sPDUOutletConfigMSPmupsP2HiTemp INTEGER
+ }
+
+sPDUOutletConfigMSPmupsIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch plus."
+ ::= { sPDUOutletConfigMSPmupsEntry 1 }
+
+sPDUOutletConfigMSPmupsName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUOutletConfigMSPmupsEntry 2 }
+
+sPDUOutletConfigMSPmupsOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletConfigMSPmupsEntry 3 }
+
+sPDUOutletConfigMSPmupsOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. The maximum size is
+ 23 characters. The name is set by using the
+ sPDUOutletConfigMSPallOutletName OID.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletConfigMSPmupsEntry 4 }
+
+sPDUOutletConfigMSPmupsZone1 OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Zone 1 alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Zone 1 alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 5 }
+
+sPDUOutletConfigMSPmupsZone2 OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Zone 2 alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Zone 2 alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 6 }
+
+sPDUOutletConfigMSPmupsZone3 OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Zone 3 alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Zone 3 alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 7 }
+
+sPDUOutletConfigMSPmupsZone4 OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Zone 4 alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Zone 4 alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 8 }
+
+sPDUOutletConfigMSPmupsP1LowHum OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 1 low humidity alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 1 low humidity alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 9 }
+
+sPDUOutletConfigMSPmupsP1HiHum OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 1 high humidity alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 1 high humidity alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 10 }
+
+sPDUOutletConfigMSPmupsP1LowTemp OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 1 low temperature alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 1 low temperature alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 11 }
+
+sPDUOutletConfigMSPmupsP1HiTemp OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 1 high temperature alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 1 high temperature alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 12 }
+
+sPDUOutletConfigMSPmupsP2LowHum OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 2 low humidity alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 2 low humidity alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 13 }
+
+sPDUOutletConfigMSPmupsP2HiHum OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 2 high humidity alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 2 high humidity alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 14 }
+
+sPDUOutletConfigMSPmupsP2LowTemp OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 2 low temperature alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 2 low temperature alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 15 }
+
+sPDUOutletConfigMSPmupsP2HiTemp OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableAlarm (1),
+ enableAlarm (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to disableAlarm (1) disables the
+ Probe 2 high temperature alarm for this outlet.
+
+ Setting this OID to enableAlarm (2) enables the
+ Probe 2 high temperature alarm for this outlet."
+ ::= { sPDUOutletConfigMSPmupsEntry 16 }
+
+-- the sPDUOutletStatusMSP group
+
+sPDUOutletStatusMSPTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletStatusMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting of status of individual outlets. The number of
+ entries is contained in the sPDUMasterStatusOutletCount OID."
+ ::= { sPDUOutletStatusMSP 1 }
+
+sPDUOutletStatusMSPEntry OBJECT-TYPE
+ SYNTAX OutletStatusMSPEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to gather status from."
+ INDEX { sPDUOutletStatusMSPIndex, sPDUOutletStatusMSPOutletIndex }
+ ::= { sPDUOutletStatusMSPTable 1 }
+
+OutletStatusMSPEntry ::=
+ SEQUENCE {
+ sPDUOutletStatusMSPIndex INTEGER,
+ sPDUOutletStatusMSPName DisplayString,
+ sPDUOutletStatusMSPOutletIndex INTEGER,
+ sPDUOutletStatusMSPOutletName DisplayString,
+ sPDUOutletStatusMSPOutletState INTEGER,
+ sPDUOutletStatusMSPCommandPending INTEGER,
+ sPDUOutletStatusMSPOutletCtrlMode INTEGER
+ }
+
+sPDUOutletStatusMSPIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the MasterSwitch MSP."
+ ::= { sPDUOutletStatusMSPEntry 1 }
+
+sPDUOutletStatusMSPName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the MasterSwitch plus. The maximum
+ value is 23 characters. The name is set by
+ using the sPDUMasterConfigMSPName OID."
+ ::= { sPDUOutletStatusMSPEntry 2 }
+
+sPDUOutletStatusMSPOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { sPDUOutletStatusMSPEntry 3 }
+
+sPDUOutletStatusMSPOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. The maximum size is
+ 23 characters. The name is set by using the
+ sPDUOutletConfigMSPallOutletName OID.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletStatusMSPEntry 4 }
+
+sPDUOutletStatusMSPOutletState OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletStatusMSPOn (1),
+ outletStatusMSPOff (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the outletStatusMSPOn (1) value will be returned.
+ If the outlet is off, the outletStatusMSPOff (2) value will be
+ returned. "
+ ::= { sPDUOutletStatusMSPEntry 5 }
+
+sPDUOutletStatusMSPCommandPending OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletStatusMSPCommandPending (1),
+ outletStatusMSPNoCommandPending (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the command pending
+ state of the outlet. If a command is pending on the
+ outlet, the outletStatusMSPCommandPending (1) value
+ will be returned. If there is not a command pending
+ on the outlet, the outletStatusMSPNoCommandPending (2)
+ will be returned."
+ ::= { sPDUOutletStatusMSPEntry 6 }
+
+sPDUOutletStatusMSPOutletCtrlMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ modeGracefulShutdown (1),
+ modeAnnunciator (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Control Mode of the outlet.
+ This OID is provided for informational purposes only."
+ ::= { sPDUOutletStatusMSPEntry 7 }
+
+
+-- the rPDUIdent group
+
+rPDUIdentName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the Rack PDU.
+ The maximum string size is device dependent."
+ ::= { rPDUIdent 1 }
+
+rPDUIdentHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the Rack PDU.
+ This value is set at the factory."
+ ::= { rPDUIdent 2 }
+
+rPDUIdentFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An 8-byte ID string identifying the Rack PDU firmware revision.
+ This value is set at the factory."
+ ::= { rPDUIdent 3 }
+
+
+rPDUIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the Rack PDU was manufactured in mm/dd/yy format.
+ This value is set at the factory. The year 2000 will be
+ represented by 00."
+ ::= { rPDUIdent 4 }
+
+rPDUIdentModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 10-character string identifying the model number of
+ the Rack PDU. This value is set at the factory."
+ ::= { rPDUIdent 5 }
+
+rPDUIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 12-character string identifying the serial number of
+ the Rack PDU. This value is set at the factory."
+ ::= { rPDUIdent 6 }
+
+rPDUIdentDeviceRating OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the electrical rating of the device."
+
+ ::= { rPDUIdent 7 }
+
+rPDUIdentDeviceNumOutlets OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the number of outlets contained in the device."
+
+ ::= { rPDUIdent 8 }
+
+rPDUIdentDeviceNumPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the number of phases supported by the device."
+
+ ::= { rPDUIdent 9 }
+
+rPDUIdentDeviceNumBreakers OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the number of circuit breakers supported by the device.
+ This is the same as the number of banks of outlets."
+
+ ::= { rPDUIdent 10 }
+
+rPDUIdentDeviceBreakerRating OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return rating of the circuit breakers on the device if it has any."
+
+ ::= { rPDUIdent 11 }
+
+rPDUIdentDeviceOrientation OBJECT-TYPE
+ SYNTAX INTEGER {
+ orientHorizontal (1),
+ orientVertical (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the intended physical orientation of the device.
+
+ OrientHorizonatal(1) indicates Horizontal.
+ OrientVertical(2) indicates Vertical."
+
+ ::= { rPDUIdent 12 }
+
+rPDUIdentDeviceOutletLayout OBJECT-TYPE
+ SYNTAX INTEGER {
+ seqPhaseToNeutral (1),
+ seqPhaseToPhase (2),
+ seqPhToNeu21PhToPh (3),
+ seqPhToPhGrouped (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return outlet layout for the device.
+
+ SeqPhaseToNeutral(1) indicates outlet layout as follows:
+ 1:1-N,2:2-N,3:3-N,4:1-N,5:2-N,...
+
+ SeqPhaseToPhase(2) indicates outlet layout as follows:
+ 1:1-2,2:2-3,3:3-1,4:1-2,5:2-3,...
+
+ SeqPhToNeu21PhToPh(3) indicates outlet layout as follows:
+ 1:1-N,2:2-N...21:3-N,22:1-2,23:2-3,24:3-1,...
+
+ SeqPhToPhGrouped(4) indicates outlet layout as follows:
+ Otlts1-8::(3-1),Otlts9-16::(2-3),Otlts17-24::(1-2)."
+ ::= { rPDUIdent 13 }
+
+
+
+-- the rPDULoadDevice group
+
+rPDULoadDevMaxPhaseLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the maximum rated power
+ that each phase of the Rack PDU can provide. It is
+ represented in Amps."
+ ::= { rPDULoadDevice 1 }
+
+rPDULoadDevNumPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of phases available with this Rack PDU."
+ ::= { rPDULoadDevice 2 }
+
+rPDULoadDevMaxBankLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the maximum rated power
+ that each bank of the Rack PDU can provide. It is
+ represented in Amps.
+
+ 0 will be returned if the device does not have any banks."
+
+ ::= { rPDULoadDevice 3 }
+
+rPDULoadDevNumBanks OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of banks of outlets available with this Rack PDU.
+ A bank of outlets has a unique circuit breaker for a subset
+ of the total number of outlets on the rPDU."
+ ::= { rPDULoadDevice 4 }
+
+-- the rPDULoadPhaseConfig group
+
+rPDULoadPhaseConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF LoadPhaseConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of each Rack PDU phase.
+ The number of entries is contained in the
+ rPDULoadDevNumPhases OID."
+ ::= { rPDULoadPhaseConfig 1 }
+
+rPDULoadPhaseConfigEntry OBJECT-TYPE
+ SYNTAX LoadPhaseConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The Rack PDU phase to configure."
+ INDEX { rPDULoadPhaseConfigIndex}
+ ::= { rPDULoadPhaseConfigTable 1 }
+
+LoadPhaseConfigEntry ::=
+ SEQUENCE {
+ rPDULoadPhaseConfigIndex INTEGER,
+ rPDULoadPhaseConfigLowLoadThreshold INTEGER,
+ rPDULoadPhaseConfigNearOverloadThreshold INTEGER,
+ rPDULoadPhaseConfigOverloadThreshold INTEGER
+ }
+
+rPDULoadPhaseConfigIndex OBJECT-TYPE
+ SYNTAX INTEGER {
+ phase1 (1),
+ phase2 (2),
+ phase3 (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the Rack PDU phase entry."
+ ::= { rPDULoadPhaseConfigEntry 1 }
+
+rPDULoadPhaseConfigLowLoadThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load is nearing a low consumption condition. It is
+ represented in amps. A warning will be issued when the
+ load is less than the threshold value.
+
+ A threshold value of 0 amps effectively disables this
+ warning.
+
+ Maximum value must be less than the value returned
+ by the rPDULoadPhaseConfigNearOverloadThreshold OID."
+ ::= { rPDULoadPhaseConfigEntry 2 }
+
+rPDULoadPhaseConfigNearOverloadThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load is nearing an overload condition. It is
+ represented in amps. A warning will be issued when the
+ load is greater than or equal to the threshold value.
+
+ Minimum value must be greater than the value returned by
+ the rPDULoadPhaseConfigLowLoadThreshold OID.
+
+ Maximum value must be less than or equal to the value
+ returned by the rPDULoadPhaseConfigOverloadThreshold OID."
+ ::= { rPDULoadPhaseConfigEntry 3 }
+
+rPDULoadPhaseConfigOverloadThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load has entered an overload condition. It is
+ represented in amps. A warning will be issued when the
+ load is greater than or equal to the threshold value.
+
+ Minimum value must be greater than or equal to the value
+ returned by the rPDULoadPhaseConfigNearOverloadThreshold OID.
+
+ Maximum value must be less than or equal to the value
+ returned by the rPDULoadDevMaxPhaseLoad OID."
+ ::= { rPDULoadPhaseConfigEntry 4 }
+
+
+-- the rPDULoadStatus group
+
+rPDULoadStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF LoadStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting of status of each Rack PDU phase/bank.
+ The number of entries is calculated by adding
+ the number of phases (rPDULoadDevNumPhases OID) and
+ the number of banks of outlets (rPDULoadDevNumBanks)
+ Number of entries = #phases + #banks.
+ NOTE: If a device has phase and bank information, all phase information
+ shall preceed the bank information."
+ ::= { rPDULoadStatus 1 }
+
+rPDULoadStatusEntry OBJECT-TYPE
+ SYNTAX LoadStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The Rack PDU phase/bank to gather status from."
+ INDEX { rPDULoadStatusIndex}
+ ::= { rPDULoadStatusTable 1 }
+
+LoadStatusEntry ::=
+ SEQUENCE {
+ rPDULoadStatusIndex INTEGER,
+ rPDULoadStatusLoad Gauge,
+ rPDULoadStatusLoadState INTEGER,
+ rPDULoadStatusPhaseNumber INTEGER,
+ rPDULoadStatusBankNumber INTEGER
+ }
+
+rPDULoadStatusIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the Rack PDU phase/bank entry. All phase information will preceed
+ any bank information"
+ ::= { rPDULoadStatusEntry 1 }
+
+rPDULoadStatusLoad OBJECT-TYPE
+ SYNTAX Gauge
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the phase/bank load measured
+ in tenths of amps."
+ ::= { rPDULoadStatusEntry 2 }
+
+rPDULoadStatusLoadState OBJECT-TYPE
+ SYNTAX INTEGER {
+ phaseLoadNormal (1),
+ phaseLoadLow (2),
+ phaseLoadNearOverload (3),
+ phaseLoadOverload (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the phase/bank load state.
+
+ phaseLoadNormal(1) indicates that the phase/bank is
+ operating properly within the rPDULoadConfigLowLoadThreshold
+ and rPDULoadConfigNearOverloadThreshold OID values.
+
+ phaseLoadLow(2) indicates that the phase/bank load has
+ dropped below the rPDULoadConfigLowLoadThreshold OID value.
+ An SNMP trap will occur when this state is entered or cleared.
+
+ phaseLoadNearOverload(3) indicates that the phase/bank load
+ is greater than or equal to the
+ rPDULoadConfigNearOverloadThreshold OID value.
+ An SNMP trap will occur when this state is entered or cleared.
+
+ phaseLoadOverload(4) indicates that the phase/bank load is
+ greater than or equal to the rPDULoadConfigOverloadThreshold
+ OID value.
+ An SNMP trap will occur when this state is entered or cleared."
+ ::= { rPDULoadStatusEntry 3 }
+
+rPDULoadStatusPhaseNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The phase number to which this record refers. A value of 0 will be returned if
+ this is bank related information."
+ ::= { rPDULoadStatusEntry 4 }
+
+rPDULoadStatusBankNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The bank number to which this record refers. A value of 0 will be returned if
+ this is phase related information."
+ ::= { rPDULoadStatusEntry 5 }
+
+-- the rPDULoadBankConfig group
+
+rPDULoadBankConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF LoadBankConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of each Rack PDU bank.
+ The number of entries is contained in the
+ rPDULoadDevNumBanks OID."
+ ::= { rPDULoadBankConfig 1 }
+
+rPDULoadBankConfigEntry OBJECT-TYPE
+ SYNTAX LoadBankConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The Rack PDU bank to configure."
+ INDEX { rPDULoadBankConfigIndex}
+ ::= { rPDULoadBankConfigTable 1 }
+
+LoadBankConfigEntry ::=
+ SEQUENCE {
+ rPDULoadBankConfigIndex INTEGER,
+ rPDULoadBankConfigLowLoadThreshold INTEGER,
+ rPDULoadBankConfigNearOverloadThreshold INTEGER,
+ rPDULoadBankConfigOverloadThreshold INTEGER
+ }
+
+rPDULoadBankConfigIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the Rack PDU bank entry."
+ ::= { rPDULoadBankConfigEntry 1 }
+
+rPDULoadBankConfigLowLoadThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load is nearing a low consumption condition. It is
+ represented in amps. A warning will be issued when the
+ load is less than the threshold value.
+
+ A threshold value of 0 amps effectively disables this
+ warning.
+
+ Maximum value must be less than the value returned
+ by the rPDULoadBankConfigNearOverloadThreshold OID.
+
+ -1 will be returned if the device has no banks."
+
+ ::= { rPDULoadBankConfigEntry 2 }
+
+rPDULoadBankConfigNearOverloadThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load is nearing an overload condition. It is
+ represented in amps. A warning will be issued when the
+ load is greater than or equal to the threshold value.
+
+ Minimum value must be greater than the value returned by
+ the rPDULoadBankConfigLowLoadThreshold OID.
+
+ Maximum value must be less than or equal to the value
+ returned by the rPDULoadBankConfigOverloadThreshold OID.
+
+ -1 will be returned if the device has no banks."
+
+ ::= { rPDULoadBankConfigEntry 3 }
+
+rPDULoadBankConfigOverloadThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A threshold that indicates the power consumption of
+ the load has entered an overload condition. It is
+ represented in amps. A warning will be issued when the
+ load is greater than or equal to the threshold value.
+
+ Minimum value must be greater than or equal to the value
+ returned by the rPDULoadBankConfigNearOverloadThreshold OID.
+
+ Maximum value must be less than or equal to the value
+ returned by the rPDULoadDevMaxBankLoad OID.
+
+ -1 will be returned if the device has no banks."
+
+ ::= { rPDULoadBankConfigEntry 4 }
+
+
+-- the rPDUOutletDevice group
+
+rPDUOutletDevCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ noCommandAll (1),
+ immediateAllOn (2),
+ immediateAllOff (3),
+ immediateAllReboot (4),
+ delayedAllOn (5),
+ delayedAllOff (6),
+ delayedAllReboot (7),
+ cancelAllPendingCommands (8),
+ gracefulAllOff (9),
+ gracefulAllReboot (10)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this OID to immediateAllOn (2) will turn all outlets
+ on immediately.
+
+ Setting this OID to immediateAllOff (3) will turn all outlets
+ off immediately.
+
+ Setting this OID to immediateAllReboot (4) will reboot all outlets
+ immediately.
+
+ Setting this OID to delayedAllOn (5) will turn all outlets on as
+ defined by each outlet's rPDUOutletConfigPowerOnTime OID value.
+
+ Setting this OID to delayedAllOff (6) will turn all outlets
+ off as defined by each outlet's rPDUOutletConfigPowerOffTime OID value.
+
+ Setting this OID to delayedAllReboot (7) will cause a
+ delayedAllOff command to be performed. Once all outlets are off,
+ the Switched Rack PDU will then delay the largest
+ rPDUOutletConfigRebootDuration OID time, and then perform a
+ delayedAllOn command.
+
+ Setting this OID to cancelAllPendingCommands (8) will cause all pending
+ commands on the Switched Rack PDU to be canceled.
+
+ Setting this variable to gracefulAllOff (9) will cause the
+ Switched Rack PDU to shut all outlets off after it waits the
+ servers graceful shutdown time and each outlet's shutdown delay.
+
+ Setting this variable to gracefulAllReboot (10) will cause the
+ Switched Rack PDU to shut all outlets off after it waits the
+ servers graceful shutdown time and each outlet's shutdown delay.
+ Once all outlet are off, it will wait until the UPS reaches the
+ configured minimum return battery capacity, then each outlet's
+ return delay before it turns the outlet back on.
+
+ Getting this OID will return the noCommandAll (1) value."
+ ::= { rPDUOutletDevice 1 }
+
+rPDUOutletDevColdstartDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of delay, in seconds, between when
+ power is provided to the Switched Rack PDU and
+ when the Switched Rack PDU provides basic master
+ power to the outlets.
+
+ Allowed values are:
+
+ -1 - never apply power automatically.
+ 0 - apply power immediately.
+ 1 to 300 - delay up to 300 seconds (5 minutes)."
+ ::= { rPDUOutletDevice 2 }
+
+rPDUOutletDevNumCntrlOutlets OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of controlled outlets on this Switched Rack PDU."
+ ::= { rPDUOutletDevice 3 }
+
+rPDUOutletDevNumTotalOutlets OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of outlets on this Rack PDU."
+ ::= { rPDUOutletDevice 4 }
+
+
+-- the rPDUOutletPhase group
+
+rPDUOutletPhaseTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for management of outlets on a per phase basis."
+ ::= { rPDUOutletPhase 1 }
+
+rPDUOutletPhaseEntry OBJECT-TYPE
+ SYNTAX OutletPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The phase to manage."
+ INDEX { rPDUOutletPhaseIndex}
+ ::= { rPDUOutletPhaseTable 1 }
+
+OutletPhaseEntry ::=
+ SEQUENCE {
+ rPDUOutletPhaseIndex INTEGER,
+ rPDUOutletPhaseOverloadRestriction INTEGER
+ }
+
+rPDUOutletPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER {
+ phase1 (1),
+ phase2 (2),
+ phase3 (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the Switched Rack PDU phase entry."
+ ::= { rPDUOutletPhaseEntry 1 }
+
+rPDUOutletPhaseOverloadRestriction OBJECT-TYPE
+ SYNTAX INTEGER {
+ alwaysAllowTurnON (1),
+ restrictOnNearOverload (2),
+ restrictOnOverload (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID controls the behavior of a Switched Rack PDU
+ phase when an overload condition is possible and
+ additional outlets are requested to be turned on.
+
+ Setting this OID to alwaysAllowTurnON (1) will always allow
+ the outlets on the corresponding phase to turn on.
+
+ Setting this OID to restrictOnNearOverload (2) will not allow
+ outlets on the corresponding phase to turn on if the
+ rPDULoadConfigNearOverloadThreshold OID is exceeded.
+
+ Setting this OID to restrictOnOverload (3) will not allow
+ outlets on the corresponding phase to turn on if the
+ rPDULoadConfigOverloadThreshold OID is exceeded."
+ ::= { rPDUOutletPhaseEntry 2 }
+
+
+-- the rPDUOutletControl group
+
+rPDUOutletControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF RPDUOutletControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of the individual outlets.
+ The number of entries is contained in the
+ rPDUOutletDevNumCntrlOutlets OID."
+ ::= { rPDUOutletControl 1 }
+
+rPDUOutletControlEntry OBJECT-TYPE
+ SYNTAX RPDUOutletControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlet to control."
+ INDEX { rPDUOutletControlIndex}
+ ::= { rPDUOutletControlTable 1 }
+
+RPDUOutletControlEntry ::=
+ SEQUENCE {
+ rPDUOutletControlIndex INTEGER,
+ rPDUOutletControlOutletName DisplayString,
+ rPDUOutletControlOutletPhase INTEGER,
+ rPDUOutletControlOutletCommand INTEGER,
+ rPDUOutletControlOutletBank INTEGER
+ }
+
+rPDUOutletControlIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { rPDUOutletControlEntry 1 }
+
+rPDUOutletControlOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is dependent on device.
+ An error will be returned if the set request exceeds the max size.
+ This OID is provided for informational purposes only."
+ ::= { rPDUOutletControlEntry 2 }
+
+rPDUOutletControlOutletPhase OBJECT-TYPE
+ SYNTAX INTEGER {
+ phase1 (1),
+ phase2 (2),
+ phase3 (3),
+ phase1-2 (4),
+ phase2-3 (5),
+ phase3-1 (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The phase/s associated with this outlet.
+
+ For single phase devices, this object will always
+ return phase1(1).
+
+ For 3-phase devices, this object will return phase1 (1),
+ phase2 (2), or phase3 (3) for outlets tied to a single
+ phase. For outlets tied to two phases, this object will
+ return phase1-2 (4) for phases 1 and 2, phase2-3 (5) for
+ phases 2 and 3, and phase3-1 (6) for phases 3 and 1."
+ ::= { rPDUOutletControlEntry 3 }
+
+rPDUOutletControlOutletCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ immediateOn (1),
+ immediateOff (2),
+ immediateReboot (3),
+ delayedOn (4),
+ delayedOff (5),
+ delayedReboot (6),
+ cancelPendingCommand (7),
+ gracefulOff (8),
+ gracefulReboot (9)
+
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the immediateOn (1) value will be returned.
+ If the outlet is off, the immediateOff (2) value will be
+ returned.
+
+
+ Setting this variable to immediateOn (1) will immediately turn
+ the outlet on.
+
+ Setting this variable to immediateOff (2) will immediately turn
+ the outlet off.
+
+ Setting this variable to immediateReboot (3) will immediately
+ reboot the outlet.
+
+ Setting this variable to delayedOn (4) will turn the outlet on
+ after the rPDUOutletConfigPowerOnTime OID time has elapsed.
+
+ Setting this variable to delayedOff (5) will turn the outlet off
+ after the rPDUOutletConfigPowerOffTime OID time has elapsed.
+
+ Setting this variable to delayedReboot (6) will cause the
+ Switched Rack PDU to perform a delayedOff command, wait the
+ rPDUOutletConfigRebootDuration OID time, and then perform a
+ delayedOn command.
+
+ Setting this variable to cancelPendingCommand (7) will cause any
+ pending command to this outlet to be canceled.
+
+ Setting this variable to gracefulOff (8) will cause the
+ Switched Rack PDU to shut the outlet off after it waits the
+ servers graceful shutdown time and the outlets shutdown delay.
+
+ Setting this variable to gracefulReboot (9) will cause the
+ Switched Rack PDU to shut the outlet off after it waits the
+ servers graceful shutdown time and the outlets shutdown delay.
+ Once the outlet is off, it will wait until the UPS reaches the
+ configured minimum return battery capacity, then the outlets
+ return delay before it turns the outlet back on."
+
+ ::= { rPDUOutletControlEntry 4 }
+
+rPDUOutletControlOutletBank OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The bank associated with this outlet."
+ ::= { rPDUOutletControlEntry 5 }
+
+
+-- the rPDUOutletConfig group
+
+rPDUOutletConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF RPDUOutletConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual outlets. The number of
+ entries is contained in the rPDUOutletDevNumCntrlOutlets OID."
+ ::= { rPDUOutletConfig 1 }
+
+rPDUOutletConfigEntry OBJECT-TYPE
+ SYNTAX RPDUOutletConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlet to configure."
+ INDEX { rPDUOutletConfigIndex}
+ ::= { rPDUOutletConfigTable 1 }
+
+RPDUOutletConfigEntry ::=
+ SEQUENCE {
+ rPDUOutletConfigIndex INTEGER,
+ rPDUOutletConfigOutletName DisplayString,
+ rPDUOutletConfigOutletPhase INTEGER,
+ rPDUOutletConfigPowerOnTime INTEGER,
+ rPDUOutletConfigPowerOffTime INTEGER,
+ rPDUOutletConfigRebootDuration INTEGER,
+ rPDUOutletConfigOutletBank INTEGER
+ }
+
+rPDUOutletConfigIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { rPDUOutletConfigEntry 1 }
+
+rPDUOutletConfigOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is dependent on device.
+ An error will be returned if the set request exceeds the max size."
+ ::= { rPDUOutletConfigEntry 2 }
+
+rPDUOutletConfigOutletPhase OBJECT-TYPE
+ SYNTAX INTEGER {
+ phase1 (1),
+ phase2 (2),
+ phase3 (3),
+ phase1-2 (4),
+ phase2-3 (5),
+ phase3-1 (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The phase/s associated with this outlet.
+
+ For single phase devices, this object will always
+ return phase1(1).
+
+ For 3-phase devices, this object will return phase1 (1),
+ phase2 (2), or phase3 (3) for outlets tied to a single
+ phase. For outlets tied to two phases, this object will
+ return phase1-2 (4) for phases 1 and 2, phase2-3 (5) for
+ phases 2 and 3, and phase3-1 (6) for phases 3 and 1."
+ ::= { rPDUOutletConfigEntry 3 }
+
+rPDUOutletConfigPowerOnTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet will delay
+ powering on at coldstart or when a command that requires
+ a turn-on delay is issued.
+
+ Allowed values are:
+
+ -1 - never power on.
+ 0 - power on immediately.
+ 1 to 300 - power on up to 300 seconds (5 minutes) after being
+ commanded."
+ ::= { rPDUOutletConfigEntry 4 }
+
+rPDUOutletConfigPowerOffTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The amount of time (in seconds) the outlet will delay
+ powering off when a command that requires
+ a turn-off delay is issued.
+
+ Allowed values are:
+
+ -1 - never power off.
+ 0 - power off immediately.
+ 1 to 300 - power off up to 300 seconds (5 minutes) after being
+ commanded."
+ ::= { rPDUOutletConfigEntry 5 }
+
+rPDUOutletConfigRebootDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "During a reboot sequence, power is turned off and then
+ back on. This OID defines the amount of time to wait,
+ in seconds, after turning the power off, at the start
+ of the sequence, before turning power back on, at the
+ end of the reboot sequence.
+
+ Allowed range is any value between 5 and 60 seconds (1 minute)."
+ ::= { rPDUOutletConfigEntry 6 }
+
+rPDUOutletConfigOutletBank OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The bank associated with this outlet."
+ ::= { rPDUOutletConfigEntry 7 }
+
+
+-- the rPDUOutletStatus group
+
+rPDUOutletStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF RPDUOutletStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting of status of individual outlets. The number of
+ entries is contained in the rPDUOutletDevNumCntrlOutlets OID."
+ ::= { rPDUOutletStatus 1 }
+
+rPDUOutletStatusEntry OBJECT-TYPE
+ SYNTAX RPDUOutletStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlet to gather status from."
+ INDEX { rPDUOutletStatusIndex}
+ ::= { rPDUOutletStatusTable 1 }
+
+RPDUOutletStatusEntry ::=
+ SEQUENCE {
+ rPDUOutletStatusIndex INTEGER,
+ rPDUOutletStatusOutletName DisplayString,
+ rPDUOutletStatusOutletPhase INTEGER,
+ rPDUOutletStatusOutletState INTEGER,
+ rPDUOutletStatusCommandPending INTEGER,
+ rPDUOutletStatusOutletBank INTEGER
+ }
+
+rPDUOutletStatusIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { rPDUOutletStatusEntry 1 }
+
+rPDUOutletStatusOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet. Maximum size is dependent on device.
+ An error will be returned if the set request exceeds the max size.
+ This OID is provided for informational purposes only."
+ ::= { rPDUOutletStatusEntry 2 }
+
+rPDUOutletStatusOutletPhase OBJECT-TYPE
+ SYNTAX INTEGER {
+ phase1 (1),
+ phase2 (2),
+ phase3 (3),
+ phase1-2 (4),
+ phase2-3 (5),
+ phase3-1 (6)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The phase/s associated with this outlet.
+
+ For single phase devices, this object will always
+ return phase1(1).
+
+ For 3-phase devices, this object will return phase1 (1),
+ phase2 (2), or phase3 (3) for outlets tied to a single
+ phase. For outlets tied to two phases, this object will
+ return phase1-2 (4) for phases 1 and 2, phase2-3 (5) for
+ phases 2 and 3, and phase3-1 (6) for phases 3 and 1."
+ ::= { rPDUOutletStatusEntry 3 }
+
+rPDUOutletStatusOutletState OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletStatusOn (1),
+ outletStatusOff (2)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the outletStatusOn (1) value will be returned.
+ If the outlet is off, the outletStatusOff (2) value will be
+ returned. "
+ ::= { rPDUOutletStatusEntry 4 }
+
+rPDUOutletStatusCommandPending OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletStatusCommandPending (1),
+ outletStatusNoCommandPending (2)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the command pending
+ state of the outlet. If a command is pending on the
+ outlet, the outletStatusCommandPending (1) value
+ will be returned. If there is not a command pending
+ on the outlet, the outletStatusNoCommandPending (2)
+ will be returned."
+ ::= { rPDUOutletStatusEntry 5 }
+
+rPDUOutletStatusOutletBank OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The bank associated with this outlet."
+ ::= { rPDUOutletStatusEntry 6 }
+
+
+-- the rPDUOutletBank group
+
+rPDUOutletBankTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletBankEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for management of outlets on a per bank basis."
+ ::= { rPDUOutletBank 1 }
+
+rPDUOutletBankEntry OBJECT-TYPE
+ SYNTAX OutletBankEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The bank to manage."
+ INDEX { rPDUOutletBankIndex}
+ ::= { rPDUOutletBankTable 1 }
+
+OutletBankEntry ::=
+ SEQUENCE {
+ rPDUOutletBankIndex INTEGER,
+ rPDUOutletBankOverloadRestriction INTEGER
+ }
+
+rPDUOutletBankIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the Switched Rack PDU bank entry."
+ ::= { rPDUOutletBankEntry 1 }
+
+rPDUOutletBankOverloadRestriction OBJECT-TYPE
+ SYNTAX INTEGER {
+ alwaysAllowTurnON (1),
+ restrictOnNearOverload (2),
+ restrictOnOverload (3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID controls the behavior of a Switched Rack PDU
+ bank when an overload condition is possible and
+ additional outlets are requested to be turned on.
+
+ Setting this OID to alwaysAllowTurnON (1) will always allow
+ the outlets on the corresponding bank to turn on.
+
+ Setting this OID to restrictOnNearOverload (2) will not allow
+ outlets on the corresponding bank to turn on if the
+ rPDULoadConfigNearOverloadThreshold OID is exceeded.
+
+ Setting this OID to restrictOnOverload (3) will not allow
+ outlets on the corresponding bank to turn on if the
+ rPDULoadConfigOverloadThreshold OID is exceeded."
+ ::= { rPDUOutletBankEntry 2 }
+
+-- the rPDUPowerSupplyDevice group
+
+rPDUPowerSupply1Status OBJECT-TYPE
+ SYNTAX INTEGER {
+ powerSupply1Ok (1),
+ powerSupply1Failed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return powerSupply1Ok(1) if power
+ supply 1 is functioning normally. If not functioning normally,
+ this OID will return powerSupply1Failed(2)."
+ ::= { rPDUPowerSupplyDevice 1 }
+
+rPDUPowerSupply2Status OBJECT-TYPE
+ SYNTAX INTEGER {
+ powerSupply2Ok (1),
+ powerSupply2Failed (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return powerSupply2Ok(1) if power
+ supply 2 is functioning normally. If not functioning normally,
+ this OID will return powerSupply2Failed(2)."
+ ::= { rPDUPowerSupplyDevice 2 }
+
+
+
+-- the dm3IdentSystem group
+
+dm3IdentSysDescriptionTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC description records."
+ ::= { dm3IdentSystem 1 }
+
+dm3IdentSysDescriptionTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IdentSysDescriptionEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing description records of the powerplant. The number of
+ entries is contained in the dm3IdentSysDescriptionTableSize OID."
+ ::= { dm3IdentSystem 2 }
+
+dm3IdentSysDescriptionEntry OBJECT-TYPE
+ SYNTAX IdentSysDescriptionEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The powerplant description record to reference."
+ INDEX { dm3IdentSysDescriptionIndex }
+ ::= { dm3IdentSysDescriptionTable 1 }
+
+IdentSysDescriptionEntry ::=
+ SEQUENCE {
+ dm3IdentSysDescriptionIndex INTEGER,
+ dm3IdentSysDescriptionText DisplayString
+ }
+
+dm3IdentSysDescriptionIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant description record."
+ ::= { dm3IdentSysDescriptionEntry 1 }
+
+dm3IdentSysDescriptionText OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A 16 character text field describing the DC power plant device.
+ This field can be configured from the dm3ConfigSysDescriptionText OID."
+ ::= { dm3IdentSysDescriptionEntry 2 }
+
+dm3IdentSysModel OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Model type of the DC power plant."
+ ::= { dm3IdentSystem 3 }
+
+dm3IdentSysCntrlRev OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Integer representation of the hardware revision of the Master Controller board."
+ ::= { dm3IdentSystem 4 }
+
+dm3IdentSysFWVersion OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Integer representation of the power plant Master Controller firmware revision."
+ ::= { dm3IdentSystem 5 }
+
+-- the dm3ConfigSystem group
+
+dm3ConfigSysDescriptionTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC description records."
+ ::= { dm3ConfigSystem 1 }
+
+dm3ConfigSysDescriptionTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ConfigSysDescriptionEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing description records of the powerplant. The number of
+ entries is contained in the dm3ConfigSysDescriptionTableSize OID."
+ ::= { dm3ConfigSystem 2 }
+
+dm3ConfigSysDescriptionEntry OBJECT-TYPE
+ SYNTAX ConfigSysDescriptionEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The powerplant description record to reference."
+ INDEX { dm3ConfigSysDescriptionIndex }
+ ::= { dm3ConfigSysDescriptionTable 1 }
+
+ConfigSysDescriptionEntry ::=
+ SEQUENCE {
+ dm3ConfigSysDescriptionIndex INTEGER,
+ dm3ConfigSysDescriptionText DisplayString
+ }
+
+dm3ConfigSysDescriptionIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant description record."
+
+ ::= { dm3ConfigSysDescriptionEntry 1 }
+
+dm3ConfigSysDescriptionText OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "16 character text field describing the DC power plant device."
+
+ ::= { dm3ConfigSysDescriptionEntry 2 }
+
+dm3ConfigSysHighTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Ambient high temperature threshold. Temperature sensor located on Master
+ Controller board.
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dm3StatusSysTempUnits' OID (Celsius or Fahrenheit).
+
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigSystem 3 }
+
+dm3ConfigSysHighTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the System High Temperature Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+ ::= { dm3ConfigSystem 4 }
+
+dm3ConfigSysLowTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Ambient low temperature threshold. Temperature sensor located on Master
+ Controller board.
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dm3StatusSysTempUnits' OID (Celsius or Fahrenheit).
+
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigSystem 5 }
+
+dm3ConfigSysLowTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the System Low Temperature Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+ ::= { dm3ConfigSystem 6 }
+
+dm3ConfigSysHardwareTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the System Hardware Temperature Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+ ::= { dm3ConfigSystem 7 }
+
+dm3ConfigSysRemoteAccess OBJECT-TYPE
+ SYNTAX INTEGER {
+ accessEnabled (1),
+ accessDisabled (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "
+ This OID is used to disable remote write access to the power plant.
+ Setting this OID to accessEnabled (1) will have no affect.
+ Setting this OID to accessDisabled (2) will disable the ability to
+ remotely configure the DC powerplant.
+
+ Once remote access is disabled, it can only be restored from the front
+ panel of the DC power plant."
+ ::= { dm3ConfigSystem 8 }
+
+
+-- the dm3ConfigLVD group
+
+dm3ConfigLVDTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant LVDs controllable
+ by this IP address."
+ ::= { dm3ConfigLVD 1 }
+
+dm3ConfigLVDTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ConfigLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the LVDs. The number of
+ entries is contained in the dm3ConfigLVDTableSize OID."
+ ::= { dm3ConfigLVD 2 }
+
+dm3ConfigLVDEntry OBJECT-TYPE
+ SYNTAX ConfigLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The LVD to configure."
+ INDEX { dm3ConfigLVDIndex }
+ ::= { dm3ConfigLVDTable 1 }
+
+ConfigLVDEntry ::=
+ SEQUENCE {
+ dm3ConfigLVDIndex INTEGER,
+ dm3ConfigLVDName DisplayString,
+ dm3ConfigLVDEnable INTEGER,
+ dm3ConfigLVDTripThresh INTEGER,
+ dm3ConfigLVDResetThresh INTEGER,
+ dm3ConfigLVDOpenAlarm INTEGER,
+ dm3ConfigLVDHWAlarm INTEGER
+ }
+
+dm3ConfigLVDIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant LVD."
+ ::= { dm3ConfigLVDEntry 1 }
+
+dm3ConfigLVDName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the LVD. The maximum value is 16 characters."
+ ::= { dm3ConfigLVDEntry 2 }
+
+dm3ConfigLVDEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ enabledYes (1),
+ enabledNo (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID is used to control and indicate if the LVD is on or off.
+ Setting this OID to enabledYes (1) will enable (turn on) the LVD.
+ Setting this OID to enabledNo (2) will disable (turn off) the LVD."
+ ::= { dm3ConfigLVDEntry 3 }
+
+dm3ConfigLVDTripThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "LVD Trip threshold. If voltage exceeds threshold, the LVD will trip.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigLVDEntry 4 }
+
+dm3ConfigLVDResetThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "LVD Reset threshold. If voltage exceeds threshold, the LVD will reset.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigLVDEntry 5 }
+
+dm3ConfigLVDOpenAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the LVD Open Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+ ::= { dm3ConfigLVDEntry 6 }
+
+dm3ConfigLVDHWAlarm OBJECT-TYPE
+SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the LVD Hardware Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+ ::= { dm3ConfigLVDEntry 7 }
+
+
+-- the dm3ConfigBattery group
+
+dm3ConfigBattFloatVolt OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Float Voltage. This setting controls the power plant voltage.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 1 }
+
+dm3ConfigBattMaxRecharge OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Maximum Recharge Rate. This setting controls the battery max
+ recharge rate. The value is based on C/20 for 240 AHr battery string.
+
+ Values are represented in thousandths of Amps (mA).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 2 }
+
+dm3ConfigBattDischargeThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery discharge threshold. If battery output current exceeds threshold
+ a battery discharge alarm will occur.
+
+ Values are represented in thousandths of Amps (mA).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 3 }
+
+dm3ConfigBattDischargeAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Battery Discharge Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBattery 4 }
+
+dm3ConfigBattHighVoltThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery high voltage threshold. If system battery voltage exceeds threshold
+ a battery high voltage alarm will occur.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 5 }
+
+dm3ConfigBattHighVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Battery High Voltage Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBattery 6 }
+
+dm3ConfigBattLowVoltThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery low voltage threshold. If system battery voltage is under threshold
+ a battery low voltage alarm will occur.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 7 }
+
+dm3ConfigBattLowVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Battery Low Voltage Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBattery 8 }
+
+dm3ConfigBattHighTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery high temperature threshold. If system battery temperature exceeds threshold
+ a battery high temperature alarm will occur.
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dm3StatusSysTempUnits' OID (Celsius or Fahrenheit).
+
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+
+ ::= { dm3ConfigBattery 9 }
+
+dm3ConfigBattHighTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Battery High Temperature Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBattery 10 }
+
+dm3ConfigBattLowTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery low temperature threshold. If system battery temperature is under threshold
+ a battery low temperature alarm will occur.
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dm3StatusSysTempUnits' OID (Celsius or Fahrenheit).
+
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+
+ ::= { dm3ConfigBattery 11 }
+
+dm3ConfigBattLowTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Battery Low Temperature Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBattery 12 }
+
+dm3ConfigBattAmpHour OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Amp-Hour Size. Units are thousandths of Amp hours (mAHr).
+
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 13 }
+
+dm3ConfigCompMethod OBJECT-TYPE
+ SYNTAX INTEGER {
+ tempcompOn (1),
+ tempcompOff (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID is used to configure and get the state of the battery
+ temperature compensation.
+
+ Setting this OID to tempcompOn (1) will enable/turn on the battery temperature compensation.
+ Setting this OID to tempcompOff (2) will disable/turn off the battery temperature compensation."
+ ::= { dm3ConfigBattery 14 }
+
+dm3ConfigCompTempCoeff OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Compensation Temperature Coefficient. (uV/degC/cell).
+
+ Units are presented in microvolts.
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 15 }
+
+dm3ConfigHighKneeTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "High Knee for temperature compensation: Compensation temperature coefficient
+ becomes 0mV/degC/cell.
+
+ Values are represented in thousandths of degrees Celcius.
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 16 }
+
+dm3ConfigLowKneeTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Low Knee for temperature compensation: Compensation temperature coefficient
+ becomes 0mV/degC/cell.
+
+ Values are represented in thousandths of degrees Celcius.
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigBattery 17 }
+
+dm3ConfigBattHwCurrentAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Battery Current Hardware Alarm (indicating current is outside realistic
+ limits, or a possible measurement fault;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBattery 18 }
+
+dm3ConfigBattHwTempAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Battery Temperature Hardware Alarm (indicating temperature is outside realistic
+ limits, or a possible measurement fault;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBattery 19 }
+
+
+-- the dm3ConfigRectThresh group
+dm3ConfigRectHighVoltThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Rectifier high voltage threshold. If rectifier voltage exceeds threshold
+ a rectifier high voltage alarm will occur.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigRectThresh 1 }
+
+
+dm3ConfigRectLowVoltThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Rectifier low voltage threshold. If rectifier voltage is under threshold
+ a rectifier low voltage alarm will occur.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigRectThresh 2 }
+
+dm3ConfigRectFailSafe OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Rectifier Fail Safe point. This OID represents the value sent to rectifier controllers
+ to use in the event of communications loss with the Master Controller or Master Controller
+ board failure.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigRectThresh 3 }
+
+dm3ConfigRectFailComm OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Rectifier Communication Fail timeout. This OID represents the time interval in which there is no
+ communication between the rectifier and the master controller at which the rectifier will reset
+ all its values to default.
+
+ Values are represented in hundredths of Seconds.
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigRectThresh 4 }
+
+-- the dm3ConfigRectAlarms group
+
+dm3ConfigRectHighVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier High Voltage Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigRectAlarms 1 }
+
+dm3ConfigRectLowVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Low Voltage Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigRectAlarms 2 }
+
+dm3ConfigRectConfigAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This alarm is activated when a new rectifier is detected;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigRectAlarms 3 }
+
+dm3ConfigRect1ofNAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This setting indicates the action if ONE rectifier of a N+1 system has failed;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigRectAlarms 4 }
+
+dm3ConfigRect2ofNAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This setting indicates the action if TWO OR MORE rectifiers of a N+1 system have failed;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigRectAlarms 5 }
+
+dm3ConfigRectDiagAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Controller Diagnostics Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigRect1ofNAlarm OID
+ to be activated if ONE rectifier fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigRect2ofNAlarm OID to be activated if TWO OR MORE rectifiers fail in an N+1 system."
+
+ ::= { dm3ConfigRectAlarms 6 }
+
+dm3ConfigRectImbalanceAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Imbalance Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigRectAlarms 7 }
+
+dm3ConfigRectCurrLimitAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Current Limit Alarm (indicating rectifier in the Current Limit state);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigRect1ofNAlarm OID
+ to be activated if ONE rectifier fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigRect2ofNAlarm OID to be activated if TWO OR MORE rectifiers fail in an N+1 system."
+
+ ::= { dm3ConfigRectAlarms 8 }
+
+dm3ConfigRectStandbyAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Standby Alarm (indicating output DC has been turned off);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigRect1ofNAlarm OID
+ to be activated if ONE rectifier fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigRect2ofNAlarm OID to be activated if TWO OR MORE rectifiers fail in an N+1 system."
+
+ ::= { dm3ConfigRectAlarms 9 }
+
+dm3ConfigRectFanFailAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Fan Fail Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigRect1ofNAlarm OID
+ to be activated if ONE rectifier fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigRect2ofNAlarm OID to be activated if TWO OR MORE rectifiers fail in an N+1 system."
+
+ ::= { dm3ConfigRectAlarms 10 }
+
+dm3ConfigRectFailAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Fail Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigRect1ofNAlarm OID
+ to be activated if ONE rectifier fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigRect2ofNAlarm OID to be activated if TWO OR MORE rectifiers fail in an N+1 system."
+
+ ::= { dm3ConfigRectAlarms 11 }
+
+dm3ConfigRectHwVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Rectifier Hardware Voltage Alarm (indicating voltage outside realistic limits,
+ or a possible measurement fault);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigRectAlarms 12 }
+
+
+-- the dm3ConfigConvThresh group
+
+dm3ConfigConvHighVoltThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Converter high voltage threshold. If converter voltage exceeds threshold
+ a converter high voltage alarm will occur.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+
+ ::= { dm3ConfigConvThresh 1 }
+
+dm3ConfigConvLowVoltThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Converter low voltage threshold. If converter voltage exceeds threshold
+ a converter low voltage alarm will occur.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigConvThresh 2 }
+
+dm3ConfigConvFailSafe OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Converter Fail Safe point. This OID represents the value sent to converter controllers
+ to use in the event of communications loss with the Master Controller or Master Controller
+ board failure.
+
+ Values are represented in thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigConvThresh 3 }
+
+dm3ConfigConvSetPoint OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Converter Set point. This OID represents the initial set point used in the
+ voltage control loop.
+
+ Units are thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigConvThresh 4 }
+
+dm3ConfigConvFailMax OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Converter Fail Maximum limit. This OID represents the value sent to the converter
+ controllers to define the maximum set point allowed.
+
+ Units are thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigConvThresh 5 }
+
+dm3ConfigConvFailMin OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Converter Fail Minimum limit. This OID represents the value sent to the converter
+ controllers to define the minimum set point allowed.
+
+ Units are thousandths of Volts (mV).
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigConvThresh 6 }
+
+dm3ConfigConvFailComm OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Converter Communication Fail timeout. This OID represents the time interval in which there is no
+ communication between the converter and the master controller at which the converter will reset
+ all its values to default.
+
+ Values are represented in hundredths of Seconds.
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigConvThresh 7 }
+
+-- the dm3ConfigConvAlarms group
+dm3ConfigConvHighVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter High Voltage Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigConvAlarms 1 }
+
+dm3ConfigConvLowVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Low Voltage Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigConvAlarms 2 }
+
+dm3ConfigConvConfigAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Configuration Alarm (indicating a new converter has been detected);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigConvAlarms 3 }
+
+dm3ConfigConv1ofNAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter 1ofN Alarm (indicating action if ONE converter of a N+1 system has failed);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigConvAlarms 4 }
+
+dm3ConfigConv2ofNAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter 2ofN Alarm (indicating action if TWO OR MORE converters of a N+1 system has failed);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigConvAlarms 5 }
+
+dm3ConfigConvDiagAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Diagnostics Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigConv1ofNAlarm OID
+ to be activated if ONE converter fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigConv2ofNAlarm OID to be activated if TWO OR MORE converters fail in an N+1 system."
+
+ ::= { dm3ConfigConvAlarms 6 }
+
+dm3ConfigConvImbalanceAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Imbalance Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigConv1ofNAlarm OID
+ to be activated if ONE converter fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigConv2ofNAlarm OID to be activated if TWO OR MORE converters fail in an N+1 system."
+
+ ::= { dm3ConfigConvAlarms 7 }
+
+dm3ConfigConvCurrLimitAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Current Limit Alarm (indicating the converter is in the Current Limit state);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigConv1ofNAlarm OID
+ to be activated if ONE converter fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigConv2ofNAlarm OID to be activated if TWO OR MORE converters fail in an N+1 system."
+
+ ::= { dm3ConfigConvAlarms 8 }
+
+dm3ConfigConvStandbyAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Standby Alarm (indicating the converter is in the Standby state);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigConv1ofNAlarm OID
+ to be activated if ONE converter fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigConv2ofNAlarm OID to be activated if TWO OR MORE converters fail in an N+1 system."
+
+ ::= { dm3ConfigConvAlarms 9 }
+
+dm3ConfigConvFanFailAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Fan Fail Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigConv1ofNAlarm OID
+ to be activated if ONE converter fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigConv2ofNAlarm OID to be activated if TWO OR MORE converters fail in an N+1 system."
+
+ ::= { dm3ConfigConvAlarms 10 }
+
+dm3ConfigConvFailAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Fail Alarm;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigConv1ofNAlarm OID
+ to be activated if ONE converter fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigConv2ofNAlarm OID to be activated if TWO OR MORE converters fail in an N+1 system."
+
+ ::= { dm3ConfigConvAlarms 11 }
+
+dm3ConfigConvHwVoltAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9),
+ alarmNofN (10)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "For the Converter Voltage Alarm (indicating voltage outside realistic limits, or a
+ possible measurement fault);
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmNofN (10) causes the alarm specified in the dm3ConfigConv1ofNAlarm OID
+ to be activated if ONE converter fails in an N+1 system. It causes the alarm specified in the
+ dm3ConfigConv2ofNAlarm OID to be activated if TWO OR MORE converters fail in an N+1 system."
+
+ ::= { dm3ConfigConvAlarms 12 }
+
+
+-- the dm3ConfigOutputRelays group
+
+dm3ConfigOutRlyTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant Output Relays controllable
+ by this IP address."
+ ::= { dm3ConfigOutputRelays 1 }
+
+dm3ConfigOutRlyTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ConfigOutRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the Output Relays. The number of
+ entries is contained in the dm3ConfigOutRlyTableSize OID."
+ ::= { dm3ConfigOutputRelays 2 }
+
+dm3ConfigOutRlyEntry OBJECT-TYPE
+ SYNTAX ConfigOutRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The output relay to configure."
+ INDEX { dm3ConfigOutRlyIndex }
+ ::= { dm3ConfigOutRlyTable 1 }
+
+ConfigOutRlyEntry ::=
+ SEQUENCE {
+ dm3ConfigOutRlyIndex INTEGER,
+ dm3ConfigOutRlyName DisplayString,
+ dm3ConfigOutRlyDelay INTEGER,
+ dm3ConfigOutRlyAlarm INTEGER
+ }
+
+dm3ConfigOutRlyIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant output relay."
+ ::= { dm3ConfigOutRlyEntry 1 }
+
+dm3ConfigOutRlyName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the output relay. The maximum value is 16 characters."
+ ::= { dm3ConfigOutRlyEntry 2 }
+
+dm3ConfigOutRlyDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Output Relay Delay. This OID represents the time delay from the initiation of an
+ output relay action to when the output relay action does occur. If the alarm condition
+ disappears before the end of the delay, no action will occur. Delay for Major
+ and Minor alarms is not configurable and is always set to 0.
+
+ Values are represented in hundredths of seconds.
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigOutRlyEntry 3 }
+
+dm3ConfigOutRlyAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Output Relay Alarm. This setting indicates what action to perform in the event of
+ an output relay alarm condition;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition.
+
+ Relay Alarm for Major and Minor alarms is not configurable and is always set to
+ alarmMajor and alarmMinor respectively."
+
+ ::= { dm3ConfigOutRlyEntry 4 }
+
+
+-- the dm3ConfigInputRelays group
+
+dm3ConfigInRlyTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant Input Relays controllable
+ by this IP address."
+ ::= { dm3ConfigInputRelays 1 }
+
+dm3ConfigInRlyTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ConfigInRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the Input Relays. The number of
+ entries is contained in the dm3ConfigInRlyTableSize OID."
+ ::= { dm3ConfigInputRelays 2 }
+
+dm3ConfigInRlyEntry OBJECT-TYPE
+ SYNTAX ConfigInRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The input relay to configure."
+ INDEX { dm3ConfigInRlyIndex }
+ ::= { dm3ConfigInRlyTable 1 }
+
+ConfigInRlyEntry ::=
+ SEQUENCE {
+ dm3ConfigInRlyIndex INTEGER,
+ dm3ConfigInRlyName DisplayString,
+ dm3ConfigInRlyDelay INTEGER,
+ dm3ConfigInRlyAlarm INTEGER
+ }
+
+dm3ConfigInRlyIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant input relay."
+ ::= { dm3ConfigInRlyEntry 1 }
+
+dm3ConfigInRlyName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the input relay. The maximum value is 16 characters."
+
+ ::= { dm3ConfigInRlyEntry 2 }
+
+dm3ConfigInRlyDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Input Relay Delay. This OID represents the time delay from the initiation of an
+ input relay action to when the input relay action does occur. If the alarm condition
+ disappears before the end of the delay, no action will occur.
+
+ Values are represented in hundredths of seconds.
+
+ Attempts to set the value above or below the acceptable range of the powerplant
+ will cause the value to be set at the high or low point of the range respectively."
+ ::= { dm3ConfigInRlyEntry 3 }
+
+dm3ConfigInRlyAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Input Relay Alarm. This setting indicates what action to perform in the event of
+ an input relay alarm condition;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigInRlyEntry 4 }
+
+-- the dm3ConfigBreakers group
+
+dm3ConfigBreakersTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant circuit breakers controllable
+ by this IP address."
+ ::= { dm3ConfigBreakers 1 }
+
+dm3ConfigBreakersTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ConfigBreakersEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the circuit breakers. The number of
+ entries is contained in the dm3ConfigBreakersTableSize OID."
+ ::= { dm3ConfigBreakers 2 }
+
+dm3ConfigBreakersEntry OBJECT-TYPE
+ SYNTAX ConfigBreakersEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The circuit breaker to configure."
+ INDEX { dm3ConfigBreakersIndex }
+ ::= { dm3ConfigBreakersTable 1 }
+
+ConfigBreakersEntry ::=
+ SEQUENCE {
+ dm3ConfigBreakersIndex INTEGER,
+ dm3ConfigBreakersName DisplayString,
+ dm3ConfigBreakersAlarm INTEGER
+ }
+
+dm3ConfigBreakersIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant circuit breaker."
+ ::= { dm3ConfigBreakersEntry 1 }
+
+dm3ConfigBreakersName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the circuit breaker. The maximum value is 16 characters."
+ ::= { dm3ConfigBreakersEntry 2 }
+
+dm3ConfigBreakersAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Circuit Breaker Alarm. This setting indicates what action to perform in the event of
+ a circuit breaker alarm condition;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigBreakersEntry 3 }
+
+-- the dm3ConfigFuses group
+
+dm3ConfigFusesTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant Fuses controllable
+ by this IP address."
+ ::= { dm3ConfigFuses 1 }
+
+dm3ConfigFusesTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ConfigFusesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the Fuses. The number of
+ entries is contained in the dm3ConfigFusesTableSize OID."
+ ::= { dm3ConfigFuses 2 }
+
+dm3ConfigFusesEntry OBJECT-TYPE
+ SYNTAX ConfigFusesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The fuse to configure."
+ INDEX { dm3ConfigFusesIndex }
+ ::= { dm3ConfigFusesTable 1 }
+
+ConfigFusesEntry ::=
+ SEQUENCE {
+ dm3ConfigFusesIndex INTEGER,
+ dm3ConfigFusesName DisplayString,
+ dm3ConfigFusesAlarm INTEGER
+ }
+
+dm3ConfigFusesIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant fuse."
+ ::= { dm3ConfigFusesEntry 1 }
+
+dm3ConfigFusesName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the fuse. The maximum value is 16 characters."
+ ::= { dm3ConfigFusesEntry 2 }
+
+dm3ConfigFusesAlarm OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmIgnore (1),
+ alarmRelay1 (2),
+ alarmRelay2 (3),
+ alarmRelay3 (4),
+ alarmRelay4 (5),
+ alarmRelay5 (6),
+ alarmRelay6 (7),
+ alarmMinor (8),
+ alarmMajor (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Fuses Alarm. This setting indicates what action to perform in the event of
+ a Fuse alarm condition;
+ Setting this OID to alarmIgnore (1) results in the alarm condition being ignored.
+ Setting this OID to alarmRelay1 (2) causes relay 1 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay2 (3) causes relay 2 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay3 (4) causes relay 3 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay4 (5) causes relay 4 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay5 (6) causes relay 5 to be activated for an
+ alarm condition.
+ Setting this OID to alarmRelay6 (7) causes relay 6 to be activated for an
+ alarm condition.
+ Setting this OID to alarmMinor (8) causes the Minor relay to be activated for an
+ alarm condition.
+ Setting this OID to alarmMajor (9) causes the Major relay to be activated for an
+ alarm condition."
+
+ ::= { dm3ConfigFusesEntry 3 }
+
+-- the dm3StatusSystem group
+
+dm3StatusSystemTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System temperature based on sensor on Master Controller PCB.
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dm3StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+
+ ::= { dm3StatusSystem 1 }
+
+dm3StatusSystemStart OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Time stamp at DC powerplant initialization.
+ The time is represented as MMM,DD,YYYY,HH:MM:SS."
+ ::= { dm3StatusSystem 2 }
+
+dm3StatusSysRemoteAccess OBJECT-TYPE
+ SYNTAX INTEGER {
+ accessEnabled (1),
+ accessDisabled (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Remote Access indicator
+ This setting indicates if configuration (write) access to the powerplant is enabled or
+ disabled at the powerplant level.
+ This value will be accessEnabled (1) if remote configuration is enabled, and
+ accessDisabled (2) if remote configuration is disabled."
+ ::= { dm3StatusSystem 3 }
+
+dm3StatusSysSecurityLevel OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This variable shows the current active security access level of controller. This
+ can only be changed directly from the front panel."
+ ::= { dm3StatusSystem 4 }
+
+dm3StatusSysTempSanity OBJECT-TYPE
+ SYNTAX INTEGER{
+ saneYES (1),
+ saneNO (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System temperature sanity indicator. Indicates if the system temperature is
+ reasonable. Reasonable is defined based on powerplant type. A value of saneYes (1)
+ indicates temperature is reasonable, a value of saneNo (2) indicates it is not."
+ ::= { dm3StatusSystem 5 }
+
+dm3StatusSysAlarmState OBJECT-TYPE
+ SYNTAX INTEGER{
+ alarmMinor (1),
+ alarmMajor (2),
+ alarmBoth (3),
+ alarmNone (4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System Alarm State. Reflects the alarm status of the overall DC system.
+ If a minor alarm is present, the value will be alarmMinor(1).
+ If a major alarm is present, the value will be alarmMajor(2).
+ If both minor and a major alarm is present, the value will be alarmBoth(3).
+ If no alarm is present, the value will be alarmNone(4)."
+ ::= { dm3StatusSystem 6 }
+
+dm3StatusSysTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ in the DC system, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { dm3StatusSystem 7 }
+
+
+-- the dm3StatusAlarms group
+
+dm3StatusAlarmsTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant alarms viewable
+ by this IP address."
+ ::= { dm3StatusAlarms 1 }
+
+dm3StatusAlarmsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusAlarmsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing system alarms. The number of
+ entries is contained in the dm3StatusAlarmsTableSize OID."
+ ::= { dm3StatusAlarms 2 }
+
+dm3StatusAlarmsEntry OBJECT-TYPE
+ SYNTAX StatusAlarmsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The alarm to display."
+ INDEX { dm3StatusAlarmsIndex }
+ ::= { dm3StatusAlarmsTable 1 }
+
+StatusAlarmsEntry ::=
+ SEQUENCE {
+ dm3StatusAlarmsIndex INTEGER,
+ dm3StatusAlarmsText DisplayString
+ }
+
+dm3StatusAlarmsIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the system alarm."
+ ::= { dm3StatusAlarmsEntry 1 }
+
+dm3StatusAlarmsText OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The 16 character text describing the active alarm condition."
+ ::= { dm3StatusAlarmsEntry 2 }
+
+-- the dm3StatusBattery group
+
+dm3StatusBattCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Current: This OID shows the battery current in thousandths of Amps (mA)."
+ ::= { dm3StatusBattery 1 }
+
+dm3StatusBattTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Temperature:
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dm3StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+
+ ::= { dm3StatusBattery 2 }
+
+dm3StatusBattCurrentSanity OBJECT-TYPE
+ SYNTAX INTEGER{
+ saneYES (1),
+ saneNO (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery current sanity indicator. Indicates if the battery current is
+ reasonable. Reasonable is defined based on powerplant type. A value of saneYes (1)
+ indicates current is reasonable, a value of saneNo (2) indicates it is not."
+ ::= { dm3StatusBattery 3 }
+
+dm3StatusBattTempSanity OBJECT-TYPE
+ SYNTAX INTEGER{
+ saneYES (1),
+ saneNO (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery temperature sanity indicator. Indicates if the battery temperature is
+ reasonable. Reasonable is defined based on powerplant type. A value of saneYes (1)
+ indicates temperature is reasonable, a value of saneNo (2) indicates it is not."
+ ::= { dm3StatusBattery 4 }
+
+-- the dm3StatusOEM group
+
+dm3StatusOEMrectOffset OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier offset value in thousandths of Volts (mV)."
+ ::= { dm3StatusOEM 1 }
+
+dm3StatusOEMrectGain OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier gain value in thousandths of Volts (mV/V)."
+ ::= { dm3StatusOEM 2 }
+
+dm3StatusOEMconvOffset OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter offset value in thousandths of Volts (mV)."
+ ::= { dm3StatusOEM 3 }
+
+dm3StatusOEMconvGain OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter gain value in thousandths of Volts (mV/V)."
+ ::= { dm3StatusOEM 4 }
+
+dm3StatusOEMshuntOffset OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the shunt offset value in thousandths of Amps (mA)."
+ ::= { dm3StatusOEM 5 }
+
+dm3StatusOEMshuntGain OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the shunt gain value in thousandths of Amps (mA/A)."
+ ::= { dm3StatusOEM 6 }
+
+-- the dm3StatusLVD group
+
+dm3StatusLVDTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant LVDs viewable
+ by this IP address."
+ ::= { dm3StatusLVD 1 }
+
+dm3StatusLVDTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the LVDs. The number of
+ entries is contained in the dm3StatusLVDTableSize OID."
+ ::= { dm3StatusLVD 2 }
+
+dm3StatusLVDEntry OBJECT-TYPE
+ SYNTAX StatusLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The LVD to gather status from."
+ INDEX { dm3StatusLVDIndex }
+ ::= { dm3StatusLVDTable 1 }
+
+StatusLVDEntry ::=
+ SEQUENCE {
+ dm3StatusLVDIndex INTEGER,
+ dm3StatusLVDName DisplayString,
+ dm3StatusLVDState INTEGER,
+ dm3StatusLVDHwFault INTEGER
+ }
+
+dm3StatusLVDIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant LVD."
+ ::= { dm3StatusLVDEntry 1 }
+
+dm3StatusLVDName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the LVD. The maximum size is
+ 16 characters. The name is set by using the
+ dm3ConfigLVDName OID.
+ This OID is provided for informational purposes only."
+ ::= { dm3StatusLVDEntry 2 }
+
+dm3StatusLVDState OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusClosed (1),
+ statusOpened (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusClosed (1) if the LVD is closed.
+ statusOpened (2) will be returned if the LVD is opened."
+ ::= { dm3StatusLVDEntry 3 }
+
+dm3StatusLVDHwFault OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusFault (1),
+ statusNofault (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusFault (1) if the LVD is faulted.
+ statusNofault (2) will be returned if the LVD is not faulted."
+ ::= { dm3StatusLVDEntry 4 }
+
+-- the dm3StatusRectifier group
+
+dm3StatusRectTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant rectifiers viewable
+ by this IP address."
+ ::= { dm3StatusRectifier 1 }
+
+dm3StatusRectTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusRectEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the rectifiers. The number of
+ entries is contained in the dm3StatusRectTableSize OID."
+ ::= { dm3StatusRectifier 2 }
+
+dm3StatusRectEntry OBJECT-TYPE
+ SYNTAX StatusRectEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The rectifier to gather status from."
+ INDEX { dm3StatusRectIndex }
+ ::= { dm3StatusRectTable 1 }
+
+StatusRectEntry ::=
+ SEQUENCE {
+ dm3StatusRectIndex INTEGER,
+ dm3StatusRectID INTEGER,
+ dm3StatusRectDesc DisplayString,
+ dm3StatusRectCurrent INTEGER,
+ dm3StatusRectCurrentLimit INTEGER,
+ dm3StatusRectStandby INTEGER,
+ dm3StatusRectFanFail INTEGER,
+ dm3StatusRectFail INTEGER,
+ dm3StatusRectDevType INTEGER,
+ dm3StatusRectPhyAddr INTEGER,
+ dm3StatusRectCfg INTEGER,
+ dm3StatusRectPcbRev INTEGER,
+ dm3StatusRectFwVer INTEGER,
+ dm3StatusRectPresent INTEGER,
+ dm3StatusRectDiagPass INTEGER,
+ dm3StatusRectState INTEGER
+ }
+
+dm3StatusRectIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant rectifier."
+ ::= { dm3StatusRectEntry 1 }
+
+dm3StatusRectID OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier ID. This enumerates the number of the rectifier within
+ a group of rectifiers."
+ ::= { dm3StatusRectEntry 2 }
+
+dm3StatusRectDesc OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the 16-character rectifier description."
+ ::= { dm3StatusRectEntry 3 }
+
+dm3StatusRectCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier current in thousandths of Amps (mA)."
+ ::= { dm3StatusRectEntry 4 }
+
+dm3StatusRectCurrentLimit OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier is in the Current Limit state.
+ statusFalse (2) will be returned if the rectifier is not in the Current Limit state."
+ ::= { dm3StatusRectEntry 5 }
+
+dm3StatusRectStandby OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier is in the Standby state.
+ statusFalse (2) will be returned if the rectifier is not in the Standby state."
+ ::= { dm3StatusRectEntry 6 }
+
+dm3StatusRectFanFail OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier Fan has failed.
+ statusFalse (2) will be returned if the rectifier Fan has not failed."
+ ::= { dm3StatusRectEntry 7 }
+
+dm3StatusRectFail OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier has failed.
+ statusFalse (2) will be returned if the rectifier has not failed."
+ ::= { dm3StatusRectEntry 8 }
+
+dm3StatusRectDevType OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier device type."
+ ::= { dm3StatusRectEntry 9 }
+
+dm3StatusRectPhyAddr OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier physical address (the address on the bus)."
+ ::= { dm3StatusRectEntry 10 }
+
+dm3StatusRectCfg OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier is present after
+ power-up or set-configuration.
+ statusFalse (2) will be returned if the rectifier is not configured."
+ ::= { dm3StatusRectEntry 11 }
+
+dm3StatusRectPcbRev OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier device PCB serial number."
+ ::= { dm3StatusRectEntry 12 }
+
+dm3StatusRectFwVer OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier device firmware revision."
+ ::= { dm3StatusRectEntry 13 }
+
+dm3StatusRectPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier is present.
+ statusFalse (2) will be returned if the rectifier is not present."
+ ::= { dm3StatusRectEntry 14 }
+
+dm3StatusRectDiagPass OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier diagnostics have passed.
+ statusFalse (2) will be returned if the rectifier diagnostics have not passed."
+ ::= { dm3StatusRectEntry 15 }
+
+dm3StatusRectState OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier device state as defined by the device status register."
+ ::= { dm3StatusRectEntry 16 }
+
+dm3StatusSysRectVoltSanity OBJECT-TYPE
+ SYNTAX INTEGER {
+ saneYES (1),
+ saneNO (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Rectifier voltage sanity indicator. Indicates if the rectifier voltage is
+ reasonable. Reasonable is defined based on powerplant type. A value of saneYes (1)
+ indicates voltage is reasonable, a value of saneNo (2) indicates it is not."
+ ::= { dm3StatusRectifier 3 }
+
+dm3StatusSysRectAvailable OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier is available.
+ statusFalse (2) will be returned if the rectifier is not available."
+ ::= { dm3StatusRectifier 4 }
+
+dm3StatusSysRectType OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the type of rectifier the system has. There can only be a single type of
+ rectifier in the power plant"
+ ::= { dm3StatusRectifier 5 }
+
+dm3StatusSysRectVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the system level rectifier voltage in thousandths of Volts (mV)."
+ ::= { dm3StatusRectifier 6 }
+
+dm3StatusSysRectCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the system level rectifier current in thousandths of Amps (mA)."
+ ::= { dm3StatusRectifier 7 }
+
+
+-- the dm3StatusConverter group
+
+dm3StatusConvTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant converters viewable
+ by this IP address."
+ ::= { dm3StatusConverter 1 }
+
+dm3StatusConvTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusConvEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for viewing status of the converters. The number of
+ entries is contained in the dm3StatusConvTableSize OID."
+ ::= { dm3StatusConverter 2 }
+
+dm3StatusConvEntry OBJECT-TYPE
+ SYNTAX StatusConvEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The converter to gather status from."
+ INDEX { dm3StatusConvIndex }
+ ::= { dm3StatusConvTable 1 }
+
+StatusConvEntry ::=
+ SEQUENCE {
+ dm3StatusConvIndex INTEGER,
+ dm3StatusConvID INTEGER,
+ dm3StatusConvDesc DisplayString,
+ dm3StatusConvCurrent INTEGER,
+ dm3StatusConvCurrentLimit INTEGER,
+ dm3StatusConvStandby INTEGER,
+ dm3StatusConvFanFail INTEGER,
+ dm3StatusConvFail INTEGER,
+ dm3StatusConvDevType INTEGER,
+ dm3StatusConvPhyAddr INTEGER,
+ dm3StatusConvCfg INTEGER,
+ dm3StatusConvPcbRev INTEGER,
+ dm3StatusConvFwVer INTEGER,
+ dm3StatusConvPresent INTEGER,
+ dm3StatusConvDiagPass INTEGER,
+ dm3StatusConvState INTEGER
+ }
+
+dm3StatusConvIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant converter."
+ ::= { dm3StatusConvEntry 1 }
+
+dm3StatusConvID OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter ID. This enumerates the number of the converter within
+ a group of converters."
+ ::= { dm3StatusConvEntry 2 }
+
+dm3StatusConvDesc OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the 16 character converter description."
+ ::= { dm3StatusConvEntry 3 }
+
+dm3StatusConvCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter current in thousandths of Amps (mA)."
+ ::= { dm3StatusConvEntry 4 }
+
+dm3StatusConvCurrentLimit OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter is in the Current Limit state.
+ statusFalse (2) will be returned if the converter is not in the Current Limit state."
+ ::= { dm3StatusConvEntry 5 }
+
+dm3StatusConvStandby OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter is in the Standby state.
+ statusFalse (2) will be returned if the converter is not in the Standby state."
+ ::= { dm3StatusConvEntry 6 }
+
+dm3StatusConvFanFail OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter Fan has failed.
+ statusFalse (2) will be returned if the converter Fan has not failed."
+ ::= { dm3StatusConvEntry 7 }
+
+dm3StatusConvFail OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter has failed.
+ statusFalse (2) will be returned if the converter has not failed."
+ ::= { dm3StatusConvEntry 8 }
+
+dm3StatusConvDevType OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter device type."
+ ::= { dm3StatusConvEntry 9 }
+
+dm3StatusConvPhyAddr OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter physical address (the address on the bus)."
+ ::= { dm3StatusConvEntry 10 }
+
+dm3StatusConvCfg OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter is present after
+ power-up or set-configuration.
+ statusFalse (2) will be returned if the converter is not configured."
+ ::= { dm3StatusConvEntry 11 }
+
+dm3StatusConvPcbRev OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter device PCB serial number."
+ ::= { dm3StatusConvEntry 12 }
+
+dm3StatusConvFwVer OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter device firmware version."
+ ::= { dm3StatusConvEntry 13 }
+
+dm3StatusConvPresent OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter is present.
+ statusFalse (2) will be returned if the converter is not present."
+ ::= { dm3StatusConvEntry 14 }
+
+dm3StatusConvDiagPass OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter diagnostics have passed.
+ statusFalse (2) will be returned if the converter diagnostics have not passed."
+ ::= { dm3StatusConvEntry 15 }
+
+dm3StatusConvState OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter state as defined by the device status register."
+ ::= { dm3StatusConvEntry 16 }
+
+dm3StatusSysConvVoltSanity OBJECT-TYPE
+ SYNTAX INTEGER{
+ saneYES (1),
+ saneNO (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Converter voltage sanity indicator. Indicates if the converter voltage is
+ reasonable. Reasonable is defined based on powerplant type. A value of saneYes (1)
+ indicates voltage is reasonable, a value of saneNo (2) indicates it is not."
+ ::= { dm3StatusConverter 3 }
+
+dm3StatusSysConvAvailable OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the converter is available.
+ statusFalse (2) will be returned if the converter is not available."
+ ::= { dm3StatusConverter 4 }
+
+dm3StatusSysConvType OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the converter type."
+ ::= { dm3StatusConverter 5 }
+
+dm3StatusSysConvVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the system level converter voltage in thousandths of volts (mV)."
+ ::= { dm3StatusConverter 6 }
+
+dm3StatusSysConvCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the system level converter current in thousandths of Amps (mA)."
+ ::= { dm3StatusConverter 7 }
+
+-- the dm3StatusOutputRelays group
+
+dm3StatusOutRlyTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant output relays viewable
+ by this IP address."
+ ::= { dm3StatusOutputRelays 1 }
+
+dm3StatusOutRlyTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusOutRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for viewing status of the output relays. The number of
+ entries is contained in the dm3StatusOutRlyTableSize OID."
+ ::= { dm3StatusOutputRelays 2 }
+
+dm3StatusOutRlyEntry OBJECT-TYPE
+ SYNTAX StatusOutRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The output relay to gather status from."
+ INDEX { dm3StatusOutRlyIndex }
+ ::= { dm3StatusOutRlyTable 1 }
+
+StatusOutRlyEntry ::=
+ SEQUENCE {
+ dm3StatusOutRlyIndex INTEGER,
+ dm3StatusOutRlyName DisplayString,
+ dm3StatusOutRlyStatus INTEGER
+ }
+
+dm3StatusOutRlyIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant output relay."
+ ::= { dm3StatusOutRlyEntry 1 }
+
+dm3StatusOutRlyName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the output relay. The maximum size is
+ 16 characters. The name is set by using the
+ dm3ConfigOutRlyName OID.
+ This OID is provided for informational purposes only."
+ ::= { dm3StatusOutRlyEntry 2 }
+
+dm3StatusOutRlyStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusOn (1),
+ statusOff (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusOn (1) if the output relay is enabled/on.
+ statusOff (2) will be returned if the output relay is disabled/off."
+ ::= { dm3StatusOutRlyEntry 3 }
+
+
+-- the dm3StatusInputRelays group
+
+dm3StatusInRlyTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant input relays viewable
+ by this IP address."
+ ::= { dm3StatusInputRelays 1 }
+
+dm3StatusInRlyTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusInRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for viewing status of the input relays. The number of
+ entries is contained in the dm3StatusInRlyTableSize OID."
+ ::= { dm3StatusInputRelays 2 }
+
+
+dm3StatusInRlyEntry OBJECT-TYPE
+ SYNTAX StatusInRlyEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The input relays to gather status from."
+ INDEX { dm3StatusInRlyIndex }
+ ::= { dm3StatusInRlyTable 1 }
+
+StatusInRlyEntry ::=
+ SEQUENCE {
+ dm3StatusInRlyIndex INTEGER,
+ dm3StatusInRlyName DisplayString,
+ dm3StatusInRlyStatus INTEGER
+ }
+
+dm3StatusInRlyIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant input relay."
+ ::= { dm3StatusInRlyEntry 1 }
+
+dm3StatusInRlyName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the input relay. The maximum size is
+ 16 characters. The name is set by using the
+ dm3ConfigInRlyName OID.
+ This OID is provided for informational purposes only."
+ ::= { dm3StatusInRlyEntry 2 }
+
+dm3StatusInRlyStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusOn (1),
+ statusOff (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusOn (1) if the input relay is enabled/on.
+ statusOff (2) will be returned if the input relay is disabled/off."
+ ::= { dm3StatusInRlyEntry 3 }
+
+-- the dm3StatusBreakers group
+
+dm3StatusBreakersTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant circuit breakers viewable
+ by this IP address."
+ ::= { dm3StatusBreakers 1 }
+
+dm3StatusBreakersTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusBreakersEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for viewing status of the circuit breakers. The number of
+ entries is contained in the dm3StatusBreakersTableSize OID."
+ ::= { dm3StatusBreakers 2 }
+
+dm3StatusBreakersEntry OBJECT-TYPE
+ SYNTAX StatusBreakersEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The circuit breaker to gather status from."
+ INDEX { dm3StatusBreakersIndex }
+ ::= { dm3StatusBreakersTable 1 }
+
+StatusBreakersEntry ::=
+ SEQUENCE {
+ dm3StatusBreakersIndex INTEGER,
+ dm3StatusBreakersName DisplayString,
+ dm3StatusBreakersStatus INTEGER
+ }
+
+dm3StatusBreakersIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant circuit breaker."
+ ::= { dm3StatusBreakersEntry 1 }
+
+dm3StatusBreakersName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the circuit breaker. The maximum size is
+ 16 characters. The name is set by using the
+ dm3ConfigBreakersName OID.
+ This OID is provided for informational purposes only."
+ ::= { dm3StatusBreakersEntry 2 }
+
+dm3StatusBreakersStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusClosed (1),
+ statusOpen (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusClosed (1) if the circuit breaker is closed.
+ statusOpen (2) will be returned if the circuit breaker is open."
+ ::= { dm3StatusBreakersEntry 3 }
+
+-- the dm3StatusFuses group
+
+dm3StatusFusesTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant fuses controllable
+ by this IP address."
+ ::= { dm3StatusFuses 1 }
+
+dm3StatusFusesTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusFusesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for viewing status of the fuses. The number of
+ entries is contained in the dm3StatusFusesTableSize OID."
+ ::= { dm3StatusFuses 2 }
+
+dm3StatusFusesEntry OBJECT-TYPE
+ SYNTAX StatusFusesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The fuse to gather status from."
+ INDEX { dm3StatusFusesIndex }
+ ::= { dm3StatusFusesTable 1 }
+
+StatusFusesEntry ::=
+ SEQUENCE {
+ dm3StatusFusesIndex INTEGER,
+ dm3StatusFusesName DisplayString,
+ dm3StatusFusesStatus INTEGER
+ }
+
+dm3StatusFusesIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant fuse."
+ ::= { dm3StatusFusesEntry 1 }
+
+dm3StatusFusesName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the fuse. The maximum size is
+ 16 characters. The name is set by using the
+ dm3ConfigFuseName OID.
+ This OID is provided for informational purposes only."
+ ::= { dm3StatusFusesEntry 2 }
+
+dm3StatusFusesStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusClosed (1),
+ statusOpen (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusClosed (1) if the fuse is closed.
+ statusOpen (2) will be returned if the fuse is open."
+ ::= { dm3StatusFusesEntry 3 }
+
+-- the atsIdent group
+
+atsIdentHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware version of the Automatic Transfer Switch.
+ This value is set at the factory."
+ ::= { atsIdent 1 }
+
+atsIdentFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A string identifying the Automatic Transfer Switch
+ firmware version."
+ ::= { atsIdent 2 }
+
+atsIdentFirmwareDate OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date of release for this Automatic Transfer Switch
+ firmware version. "
+ ::= { atsIdent 3 }
+
+atsIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the Automatic Transfer Switch was manufactured in mm/dd/yyyy format.
+ This value is set at the factory. "
+ ::= { atsIdent 4 }
+
+atsIdentModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A string identifying the model number of the Automatic Transfer Switch.
+ This value is set at the factory."
+ ::= { atsIdent 5 }
+
+atsIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A string identifying the serial number of
+ the Automatic Transfer Switch. This value is set at the factory."
+ ::= { atsIdent 6 }
+
+atsIdentNominalLineVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "RMS Utility Voltage measured in V."
+ ::= { atsIdent 7 }
+
+atsIdentNominalLineFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Utility Power Frequency measured in Hz."
+ ::= { atsIdent 8 }
+
+-- the atsCalibration group
+
+-- Input Voltage Calibration Factor table
+
+ atsCalibrationNumInputs OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of inputs to this device."
+ ::= { atsCalibrationInput 1 }
+
+ atsCalibrationNumInputPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of phases per input for this device."
+ ::= { atsCalibrationInput 2 }
+
+ atsCalibrationInputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ATSCalibrationInputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The number of phases per input line to this device."
+ ::= { atsCalibrationInput 3 }
+
+ atsCalibrationInputPhaseEntry OBJECT-TYPE
+ SYNTAX ATSCalibrationInputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing calibration information applicable to a
+ particular input phase."
+ INDEX { atsCalibrationInputTableIndex, atsCalibrationInputPhaseTableIndex }
+ ::= { atsCalibrationInputTable 1 }
+
+ ATSCalibrationInputPhaseEntry ::= SEQUENCE {
+ atsCalibrationInputTableIndex INTEGER,
+ atsCalibrationInputPhaseTableIndex INTEGER,
+ atsLineVoltageCalibrationFactor INTEGER
+ }
+
+ atsCalibrationInputTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input identifier."
+ ::= { atsCalibrationInputPhaseEntry 1 }
+
+ atsCalibrationInputPhaseTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input phase identifier."
+ ::= { atsCalibrationInputPhaseEntry 2 }
+
+ atsLineVoltageCalibrationFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Line Voltage Calibration factor.
+ This value is set at the factory."
+ ::= { atsCalibrationInputPhaseEntry 3 }
+
+-- Power Supply Voltage Calibration table
+
+ atsCalibrationPowerSupplyVoltages OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of power supply voltages supported by this device.
+ This variable indicates the number of rows in the
+ atsCalibrationPowerSupplyTable. There is one entry per
+ supported voltage: 24V, 12V and 5V"
+ ::= { atsCalibrationPowerSupply 1 }
+
+ atsCalibrationPowerSupplyVoltageTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ATSCalibrationPowerSupplyVoltageEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of Power Supply table entries."
+ ::= { atsCalibrationPowerSupply 2 }
+
+ atsCalibrationPowerSupplyVoltageEntry OBJECT-TYPE
+ SYNTAX ATSCalibrationPowerSupplyVoltageEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular Power Supply Voltage."
+ INDEX { atsCalibrationPowerSupplyVoltageTableIndex }
+ ::= { atsCalibrationPowerSupplyVoltageTable 1 }
+
+ ATSCalibrationPowerSupplyVoltageEntry ::= SEQUENCE {
+ atsCalibrationPowerSupplyVoltageTableIndex INTEGER,
+ atsCalibrationPowerSupplyVoltage INTEGER,
+ atsPowerSupplyVoltageCalibrationFactor INTEGER
+ }
+
+ atsCalibrationPowerSupplyVoltageTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The power supply voltage identifier.
+ Three power supply voltages are supported by the ATS:
+ 24V , 12V and 5V .
+ The value of this index indicates the power supply voltage:
+ 1 = 24V
+ 2 = 12V
+ 3 = 5V"
+ ::= { atsCalibrationPowerSupplyVoltageEntry 1 }
+
+ atsCalibrationPowerSupplyVoltage OBJECT-TYPE
+ SYNTAX INTEGER {
+ powerSupply24V(1),
+ powerSupply12V(2),
+ powerSupply(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This value describes the power supply voltage."
+ ::= { atsCalibrationPowerSupplyVoltageEntry 2 }
+
+ atsPowerSupplyVoltageCalibrationFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The Line Voltage Calibration factor.
+ This value is set at the factory."
+ ::= { atsCalibrationPowerSupplyVoltageEntry 3 }
+
+-- Output Current Calibration table
+
+ atsCalibrationNumOutputs OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output lines from this device.
+ This variable indicates the number of rows in the
+ atsCalibrationOutputTable."
+ ::= { atsCalibrationOutput 1 }
+
+ atsCalibrationNumOutputPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output phases utilized in this
+ device."
+ ::= { atsCalibrationOutput 2 }
+
+ atsCalibrationOutputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ATSCalibrationOutputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output table entries."
+ ::= { atsCalibrationOutput 3 }
+
+ atsCalibrationOutputEntry OBJECT-TYPE
+ SYNTAX ATSCalibrationOutputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular output."
+ INDEX { atsCalibrationOutputTableIndex, atsCalibrationOutputPhasesTableIndex }
+ ::= { atsCalibrationOutputTable 1 }
+
+ ATSCalibrationOutputEntry ::= SEQUENCE {
+ atsCalibrationOutputTableIndex INTEGER,
+ atsCalibrationOutputPhasesTableIndex INTEGER,
+ atsOutputCurrentCalibrationFactor INTEGER
+ }
+
+ atsCalibrationOutputTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output identifier."
+ ::= { atsCalibrationOutputEntry 1 }
+
+ atsCalibrationOutputPhasesTableIndex OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3),
+ neutral(4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each calibration factor for each
+ output phase utilized in this device and one for neutral. "
+ ::= { atsCalibrationOutputEntry 2 }
+
+ atsOutputCurrentCalibrationFactor OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output current calibration factor measured in Amps."
+ ::= { atsCalibrationOutputEntry 3 }
+
+
+-- the atsControl group
+
+atsControlResetATS OBJECT-TYPE
+ SYNTAX INTEGER {
+ none(1),
+ reset(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable will cause the Automatic Transfer Switch to
+ perform a power-on reset."
+ ::= { atsControl 1 }
+
+atsControlClearAllAlarms OBJECT-TYPE
+ SYNTAX INTEGER {
+ none(1),
+ clear(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable will clear all alarms in the Automatic Transfer Switch."
+ ::= { atsControl 2 }
+
+-- the atsConfig group
+
+atsConfigProductName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A configurable character string."
+ ::= { atsConfig 1 }
+
+atsConfigPreferredSource OBJECT-TYPE
+ SYNTAX INTEGER {
+ sourceA(1),
+ sourceB(2),
+ none(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This variable returns the preferred source of power when both sources are OK."
+ ::= { atsConfig 2 }
+
+atsConfigFrontPanelLockout OBJECT-TYPE
+ SYNTAX INTEGER {
+ disableFrontPanel(1),
+ enableFrontPanel(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Setting this variable to disableFrontPanel(1) will disallow source
+ preference configuration of the Automatic Transfer Switch via the
+ Front Panel. Once this value is set, it can only be re-enabled through
+ the serial interface of the ATS.
+ When this variable is set to enableFrontPanel(2), source preference
+ configuration of the Automatic Transfer Switch via the Front Panel
+ is allowed."
+ ::= { atsConfig 3 }
+
+atsConfigVoltageSensitivity OBJECT-TYPE
+ SYNTAX INTEGER {
+ high(1),
+ low(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This variable defines the sensitivity to changes in voltage:
+ high(1) for best protection, low(2) for frequent small line
+ voltage changes."
+ ::= { atsConfig 4 }
+
+atsConfigTransferVoltageRange OBJECT-TYPE
+ SYNTAX INTEGER {
+ wide(1),
+ medium(2),
+ narrow(3)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This variable defines the range of acceptable voltage from a power source.
+ If the voltage measured from the selected input source is not within this
+ range, the Automatic Transfer Switch will switch over (transfer) to the
+ alternate power source."
+
+ ::= { atsConfig 5 }
+
+atsConfigCurrentLimit OBJECT-TYPE
+ SYNTAX INTEGER (0..20)
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The threshold (in Amps) at which an Over Current Alarm will be generated."
+
+ ::= { atsConfig 6 }
+
+
+atsConfigResetValues OBJECT-TYPE
+ SYNTAX INTEGER {
+ none(1),
+ reset(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Resets the ATS configuration to its default values."
+
+ ::= { atsConfig 7 }
+
+-- the atsStatus group
+
+ atsStatusCommStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ atsNeverDiscovered(1),
+ atsCommEstablished(2),
+ atsCommLost(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This variable returns the current communication status
+ of the Automatic Transfer Switch. "
+ ::= { atsStatusDeviceStatus 1 }
+
+ atsStatusSelectedSource OBJECT-TYPE
+ SYNTAX INTEGER {
+ sourceA(1),
+ sourceB(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This variable returns the current source of power. "
+ ::= { atsStatusDeviceStatus 2 }
+
+ atsStatusRedundancyState OBJECT-TYPE
+ SYNTAX INTEGER {
+ atsRedundancyLost(1),
+ atsFullyRedundant(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This variable returns the current redundancy state of the ATS.
+ atsRedundancyLost(1) indicates that the ATS is unable to
+ switch over to the alternate power source if the current source fails.
+ atsFullyRedundant(2) indicates that the ATS will switch over to
+ the alternate power source if the current source fails."
+ ::= { atsStatusDeviceStatus 3 }
+
+ atsStatusOverCurrentState OBJECT-TYPE
+ SYNTAX INTEGER {
+ atsOverCurrent(1),
+ atsCurrentOK(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This variable returns the output current state of the ATS.
+ atsOverCurrent(1) indicates that the ATS has exceeded the output
+ current threshold and will not allow a switch over to the alternate power
+ source if the current source fails.
+ atsCurrentOK(2) indicates that the output current is below the
+ output current threshold."
+ ::= { atsStatusDeviceStatus 4 }
+
+ atsStatus5VPowerSupply OBJECT-TYPE
+ SYNTAX INTEGER {
+ atsPowerSupplyFailure(1),
+ atsPowerSupplyOK(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This variable returns the current state of the ATS 5-volt power supply.
+ atsPowerSupplyFailure(1) indicates the 5-volt power supply has failed
+ and that the ATS serial port Configuration Menu is not accessible .
+ atsPowerSupplyOK(2) indicates that the ATS 5-volt power supply
+ is operating within tolerance."
+ ::= { atsStatusDeviceStatus 5 }
+
+ atsStatus24VPowerSupply OBJECT-TYPE
+ SYNTAX INTEGER {
+ atsPowerSupplyFailure(1),
+ atsPowerSupplyOK(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This variable returns the current state of the ATS 24-volt power supply.
+ atsPowerSupplyFailure(1) indicates the 24-volt power supply has failed
+ and the ATS is unable to switch over to the alternate power source if
+ the current source fails.
+ atsPowerSupplyOK(2) indicates that the ATS 24-volt power supply
+ is operating within tolerance."
+ ::= { atsStatusDeviceStatus 6 }
+
+ atsStatusResetMaxMinValues OBJECT-TYPE
+ SYNTAX INTEGER {
+ none(1),
+ reset(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Resets the maximum and minimum ATS values:
+ atsInputMaxVoltage, atsInputMinVoltage,
+ atsInputMaxCurrent, atsInputMinCurrent,
+ atsInputMaxPower, atsInputMinPower,
+ atsOutputMaxCurrent, atsOutputMinCurrent,
+ atsOutputMaxLoad, atsOutputMinLoad,
+ atsOutputMaxPercentLoad, atsOutputMinPercentLoad,
+ atsOutputMaxPower, atsOutputMinPower,
+ atsOutputMaxPercentPower, atsOutputMinPercentPower.
+ These variables represent the maximum and minimum ATS values
+ since the last time they were read or reset by this OID.
+ Values unsupported by this ATS will return (-1)."
+ ::= { atsStatusResetValues 1 }
+
+--
+-- Input Group
+--
+
+-- Number of Inputs
+
+ atsNumInputs OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input feeds to this device.
+ This variable indicates the number of rows in the
+ input table."
+ ::= { atsStatusInput 1 }
+
+-- Input Table
+
+ atsInputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ATSPhaseInputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of input table entries. The number of entries
+ is given by the value of atsNumInputs."
+ ::= { atsStatusInput 2 }
+
+ atsInputEntry OBJECT-TYPE
+ SYNTAX ATSPhaseInputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular input."
+ INDEX { atsInputTableIndex }
+ ::= { atsInputTable 1 }
+
+ ATSPhaseInputEntry ::= SEQUENCE {
+ atsInputTableIndex INTEGER,
+ atsNumInputPhases INTEGER,
+ atsInputVoltageOrientation INTEGER,
+ atsInputFrequency INTEGER,
+ atsInputType INTEGER,
+ atsInputName DisplayString
+ }
+
+ atsInputTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input identifier."
+ ::= { atsInputEntry 1 }
+
+ atsNumInputPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of input phases utilized in this
+ device. The sum of all the atsNumInputPhases
+ variable indicates the number of rows in the
+ input phase table."
+ ::= { atsInputEntry 2 }
+
+ atsInputVoltageOrientation OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ singlePhase(2),
+ splitPhase(3),
+ threePhasePhaseToNeutral(4),
+ threePhasePhaseToPhase(5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input voltage orientation:
+ 1: unknown for this Source
+ 2: singlePhase - phase 1 voltage is between Phase 1
+ and Neutral.
+ 3: splitPhase - phase 1 voltage is between Phase 1 and
+ Neutral; phase 2 voltage is between Phase 2 and Neutral;
+ phase 3 voltage is between Phase 1 and Phase2.
+ 4: threePhasePhaseToNeutral - phase 1 voltage is between
+ Phase 1 and Neutral; phase 2 voltage is between Phase 2
+ and Neutral; phase 3 voltage is between Phase3 and
+ Neutral.
+ 5: threePhasePhaseToPhase - phase 1 voltage is between
+ Phase 1 and Phase 2; phase 2 voltage is between Phase 2
+ and Phase 3; phase 3 voltage is between Phase 3 and
+ Phase 1."
+ ::= { atsInputEntry 3 }
+
+ atsInputFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input frequency in Hertz, or -1 if it's unsupported
+ by this Source."
+ ::= { atsInputEntry 4 }
+
+ atsInputType OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ main(2),
+ bypass(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input type."
+ ::= { atsInputEntry 5 }
+
+ atsInputName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A name given to a particular input."
+ ::= { atsInputEntry 6 }
+
+-- Input Phase Table
+
+ atsInputPhaseTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ATSPhaseInputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of input table entries. The number of entries
+ is given by the sum of the atsNumInputPhases."
+ ::= { atsStatusInput 3 }
+
+ atsInputPhaseEntry OBJECT-TYPE
+ SYNTAX ATSPhaseInputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular input phase."
+ INDEX { atsInputPhaseTableIndex, atsInputPhaseIndex }
+ ::= { atsInputPhaseTable 1 }
+
+ ATSPhaseInputPhaseEntry ::= SEQUENCE {
+ atsInputPhaseTableIndex INTEGER,
+ atsInputPhaseIndex INTEGER,
+ atsInputVoltage INTEGER,
+ atsInputMaxVoltage INTEGER,
+ atsInputMinVoltage INTEGER,
+ atsInputCurrent INTEGER,
+ atsInputMaxCurrent INTEGER,
+ atsInputMinCurrent INTEGER,
+ atsInputPower INTEGER,
+ atsInputMaxPower INTEGER,
+ atsInputMinPower INTEGER
+ }
+
+ atsInputPhaseTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input identifier."
+ ::= { atsInputPhaseEntry 1 }
+
+ atsInputPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input phase identifier."
+ ::= { atsInputPhaseEntry 2 }
+
+ atsInputVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input voltage in VAC, or -1 if it's unsupported
+ by this Source."
+ ::= { atsInputPhaseEntry 3 }
+
+ atsInputMaxVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum input voltage in VAC measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsInputPhaseEntry 4 }
+
+ atsInputMinVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum input voltage in VAC measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsInputPhaseEntry 5 }
+
+ atsInputCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input current in amperes, or -1 if it's
+ unsupported by this Source."
+ ::= { atsInputPhaseEntry 6 }
+
+ atsInputMaxCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum input current in amperes measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsInputPhaseEntry 7 }
+
+ atsInputMinCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum input current in amperes measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsInputPhaseEntry 8 }
+
+ atsInputPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The input power in Watts, or -1 if it's unsupported
+ by this Source."
+ ::= { atsInputPhaseEntry 9 }
+
+ atsInputMaxPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum input power in Watts measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsInputPhaseEntry 10 }
+
+ atsInputMinPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum input power in Watts measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsInputPhaseEntry 11 }
+
+ --
+ -- The Output group.
+ --
+
+ -- Number of Outputs
+
+ atsNumOutputs OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output feeds to this device.
+ This variable indicates the number of rows in the
+ output table."
+ ::= { atsStatusOutput 1 }
+
+ -- Output Table
+
+ atsOutputTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ATSPhaseOutputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output table entries. The number of entries
+ is given by the value of atsOutputNumPhases."
+ ::= { atsStatusOutput 2 }
+
+ atsOutputEntry OBJECT-TYPE
+ SYNTAX ATSPhaseOutputEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular output."
+ INDEX { atsOutputTableIndex }
+ ::= { atsOutputTable 1 }
+
+ ATSPhaseOutputEntry ::= SEQUENCE {
+ atsOutputTableIndex INTEGER,
+ atsNumOutputPhases INTEGER,
+ atsOutputVoltageOrientation INTEGER,
+ atsOutputFrequency INTEGER
+ }
+
+ atsOutputTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output identifier."
+ ::= { atsOutputEntry 1 }
+
+ atsNumOutputPhases OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output phases utilized in this
+ device. The sum of all the atsNumOutputPhases
+ variable indicates the number of rows in the
+ output phase table."
+ ::= { atsOutputEntry 2 }
+
+ atsOutputVoltageOrientation OBJECT-TYPE
+ SYNTAX INTEGER {
+ unknown(1),
+ singlePhase(2),
+ splitPhase(3),
+ threePhasePhaseToNeutral(4),
+ threePhasePhaseToPhase(5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output voltage orientation:
+ 1: unknown for this ATS
+ 2: singlePhase - phase 1 voltage is between Phase 1
+ and Neutral.
+ 3: splitPhase - phase 1 voltage is between Phase 1 and
+ Neutral; phase 2 voltage is between Phase 2 and Neutral;
+ phase 3 voltage is between Phase 1 and Phase2.
+ 4: threePhasePhaseToNeutral - phase 1 voltage is between
+ Phase 1 and Neutral; phase 2 voltage is between Phase 2
+ and Neutral; phase 3 voltage is between Phase3 and
+ Neutral.
+ 5: threePhasePhaseToPhase - phase 1 voltage is between
+ Phase 1 and Phase 2; phase 2 voltage is between Phase 2
+ and Phase 3; phase 3 voltage is between Phase 3 and
+ Phase 1."
+ ::= { atsOutputEntry 3 }
+
+ atsOutputFrequency OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output frequency in Hertz, or -1 if it's
+ unsupported by this ATS."
+ ::= { atsOutputEntry 4 }
+
+ -- Output Phase Table
+
+ atsOutputPhaseTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ATSPhaseOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output table entries. The number of
+ entries is given by the sum of the atsNumOutputPhases."
+ ::= { atsStatusOutput 3 }
+
+ atsOutputPhaseEntry OBJECT-TYPE
+ SYNTAX ATSPhaseOutputPhaseEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "An entry containing information applicable to a
+ particular output phase."
+ INDEX { atsOutputPhaseTableIndex, atsOutputPhaseIndex }
+ ::= { atsOutputPhaseTable 1 }
+
+ ATSPhaseOutputPhaseEntry ::= SEQUENCE {
+ atsOutputPhaseTableIndex INTEGER,
+ atsOutputPhaseIndex INTEGER,
+ atsOutputVoltage INTEGER,
+ atsOutputCurrent INTEGER,
+ atsOutputMaxCurrent INTEGER,
+ atsOutputMinCurrent INTEGER,
+ atsOutputLoad INTEGER,
+ atsOutputMaxLoad INTEGER,
+ atsOutputMinLoad INTEGER,
+ atsOutputPercentLoad INTEGER,
+ atsOutputMaxPercentLoad INTEGER,
+ atsOutputMinPercentLoad INTEGER,
+ atsOutputPower INTEGER,
+ atsOutputMaxPower INTEGER,
+ atsOutputMinPower INTEGER,
+ atsOutputPercentPower INTEGER,
+ atsOutputMaxPercentPower INTEGER,
+ atsOutputMinPercentPower INTEGER
+ }
+
+ atsOutputPhaseTableIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output identifier."
+ ::= { atsOutputPhaseEntry 1 }
+
+ atsOutputPhaseIndex OBJECT-TYPE
+ SYNTAX INTEGER{
+ phase1(1),
+ phase2(2),
+ phase3(3),
+ neutral(4)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Description of each output phase utilized in
+ this device and one for neutral. "
+ ::= { atsOutputPhaseEntry 2 }
+
+ atsOutputVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output voltage in VAC, or -1 if it's unsupported
+ by this ATS."
+ ::= { atsOutputPhaseEntry 3 }
+
+ atsOutputCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output current in 0.1 amperes drawn
+ by the load on the ATS, or -1 if it's unsupported
+ by this ATS."
+ ::= { atsOutputPhaseEntry 4 }
+
+ atsOutputMaxCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum output current in 0.1 amperes measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 5 }
+
+ atsOutputMinCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum output current in 0.1 amperes measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 6 }
+
+ atsOutputLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output load in VA, or -1 if it's unsupported
+ by this ATS."
+ ::= { atsOutputPhaseEntry 7 }
+
+ atsOutputMaxLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum output load in VA measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 8 }
+
+ atsOutputMinLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum output load in VA measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 9 }
+
+ atsOutputPercentLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The percentage of the ATS load capacity in VA at
+ redundancy @ (n + x) presently being used on this
+ output phase, or -1 if it's unsupported by this ATS."
+ ::= { atsOutputPhaseEntry 10 }
+
+ atsOutputMaxPercentLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum percentage of the ATS load capacity in
+ VA measured at redundancy @ (n + x) presently
+ being used on this output phase since the last time
+ this variable was read or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 11 }
+
+ atsOutputMinPercentLoad OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum percentage of the ATS load capacity in
+ VA measured at redundancy @ (n + x) presently
+ being used on this output phase since the last time
+ this variable was read or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 12 }
+
+ atsOutputPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The output power in Watts, or -1 if it's
+ unsupported by this ATS."
+ ::= { atsOutputPhaseEntry 13 }
+
+ atsOutputMaxPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum output power in Watts measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 14 }
+
+ atsOutputMinPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum output power in Watts measured
+ since the last time this variable was read
+ or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 15 }
+
+ atsOutputPercentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The percentage of the ATSpower capacity in Watts at
+ redundancy @ (n + x) presently being used on this
+ output phase, or -1 if it's unsupported by this ATS."
+ ::= { atsOutputPhaseEntry 16 }
+
+ atsOutputMaxPercentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The maximum percentage of the ATSpower capacity
+ in Watts measured at redundancy @ (n + x) presently
+ being used on this output phase since the last time
+ this variable was read or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 17 }
+
+ atsOutputMinPercentPower OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The minimum percentage of the ATSpower capacity
+ in Watts measured at redundancy @ (n + x) presently
+ being used on this output phase since the last time
+ this variable was read or reset (atsStatusResetMaxMinValues).
+ Returns (-1) if unsupported."
+ ::= { atsOutputPhaseEntry 18 }
+
+-- the dcmim2IdentSystem group
+
+dcmim2IdentSysFWVersion OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Integer representation of the power plant Master Controller firmware revision."
+ ::= { dcmim2IdentSystem 1 }
+
+
+-- the dcmim2ControlSystem group
+
+dcmim2ControlRunFunctBatteryTest OBJECT-TYPE
+ SYNTAX INTEGER {
+ battTestOff (1),
+ battTestOn (2)
+}
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the battery functional test state. If
+ the test is off, the battTestOff (1) value will be returned.
+ If the test is on, the battTestOn (2) value will be
+ returned.
+
+ Setting this OID to battTestOff (1) will turn the battery functional test off.
+ Setting this OID to battTestOn (2) will turn the battery functional test on."
+
+ ::= { dcmim2ControlSystem 1 }
+
+dcmim2ControlRunCapacityBatteryTest OBJECT-TYPE
+ SYNTAX INTEGER {
+ battTestOff (1),
+ battTestOn (2)
+}
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return the battery capacity test state. If
+ the test is off, the battTestOff (1) value will be returned.
+ If the test is on, the battTestOn (2) value will be
+ returned.
+
+ Setting this OID to battTestOff (1) will turn the battery capacity test off.
+ Setting this OID to battTestOn (2) will turn the battery capacity test on."
+
+ ::= { dcmim2ControlSystem 2 }
+
+
+-- the dcmim2ConfigSystem group
+
+dcmim2ConfigSysHighTempTrip OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Trip level (threshold) at which System High Temp alarm condition is created.
+ Range 28 to 100 (degC).
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dcmim2StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+
+
+ ::= { dcmim2ConfigSystem 1 }
+
+dcmim2ConfigSysHighTempReset OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Level at which System High Temp alarm condition is reset (cleared).
+ Range 25 to (upper temp - 3) (degC).
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dcmim2StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+
+ ::= { dcmim2ConfigSystem 2 }
+
+dcmim2ConfigSysLowTempTrip OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Trip level (threshold) at which System Low Temp alarm condition is created.
+ Range -100 to 10 (degC).
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dcmim2StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+
+ ::= { dcmim2ConfigSystem 3 }
+
+dcmim2ConfigSysLowTempReset OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Level at which System Low Temp alarm condition is reset (cleared).
+ Range (lower temp + 3) to 13 (degC).
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dcmim2StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+
+ ::= { dcmim2ConfigSystem 4 }
+
+-- the dcmim2ConfigBattery group
+
+dcmim2ConfigBattFloatVolt OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Float Voltage defined at 25 degrees Celsius.
+
+ Values are represented in thousandths of Volts (mV)."
+
+ ::= { dcmim2ConfigBattery 1 }
+
+dcmim2ConfigBattMaxRecharge OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Maximum Recharge Rate. This is the maximum current used
+ during battery charging.
+
+ Values are represented in thousandths of Amps (mA)."
+
+ ::= { dcmim2ConfigBattery 2 }
+
+dcmim2ConfigBattMfgCapacity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Battery capacity (Amp-Hour Size) as specified by the battery manufacturer.
+
+ Values are represented in thousandths of Amp hours (mAHr)."
+
+ ::= { dcmim2ConfigBattery 3 }
+
+dcmim2ConfigBattType OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Type of battery in the powerplant
+
+ Valid values range from 0 to 254."
+
+ ::= { dcmim2ConfigBattery 4 }
+
+dcmim2ConfigBattFunctTestDuration OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Duration of the battery functional test.
+
+ Values are represented in thousandths of seconds (mSecs)."
+
+ ::= { dcmim2ConfigBattery 5 }
+
+dcmim2ConfigBattFunctTestThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold the battery voltage of the system must remain above
+ in order to pass the battery functional test.
+
+ Values are represented in thousandths of Volts (mV)."
+
+ ::= { dcmim2ConfigBattery 6 }
+
+dcmim2ConfigBattCapacityTestPercent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Threshold for good battery capacity test results.
+
+ Values range from 0 to 100 percent."
+
+ ::= { dcmim2ConfigBattery 7 }
+
+dcmim2ConfigBattCapacityTestEndThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Safeguard voltage at which battery capacity test will end
+ if there is a battery problem.
+
+ Values are represented in thousandths of Volts (mV)."
+
+ ::= { dcmim2ConfigBattery 8 }
+
+dcmim2ConfigBattCapacityTestCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Constant current value used during battery capacity testing.
+
+ Values are represented in thousandths of Amps (mA)."
+
+ ::= { dcmim2ConfigBattery 9 }
+
+
+-- the dcmim2ConfigLVD group
+
+dcmim2ConfigLVDTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant LVDs controllable
+ by this IP address."
+ ::= { dcmim2ConfigLVD 1 }
+
+dcmim2ConfigLVDTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DC2ConfigLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the LVDs. The number of
+ entries is contained in the dcmim2ConfigLVDTableSize OID."
+ ::= { dcmim2ConfigLVD 2 }
+
+dcmim2ConfigLVDEntry OBJECT-TYPE
+ SYNTAX DC2ConfigLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The LVD to configure."
+ INDEX { dcmim2ConfigLVDIndex }
+ ::= { dcmim2ConfigLVDTable 1 }
+
+DC2ConfigLVDEntry ::=
+ SEQUENCE {
+ dcmim2ConfigLVDIndex INTEGER,
+ dcmim2ConfigLVDTrip INTEGER,
+ dcmim2ConfigLVDReset INTEGER,
+ dcmim2ConfigLVDState INTEGER
+ }
+
+dcmim2ConfigLVDIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant LVD."
+ ::= { dcmim2ConfigLVDEntry 1 }
+
+dcmim2ConfigLVDTrip OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "LVD Trip threshold. System bus voltage at which LVD will trip (open)
+ during a battery backup operation.
+
+ Values are represented in thousandths of Volts (mV)."
+ ::= { dcmim2ConfigLVDEntry 2 }
+
+dcmim2ConfigLVDReset OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "LVD Reset threshold. System bus voltage at which LVD will reset (close)
+ after AC power has been restored.
+
+ Values are represented in thousandths of Volts (mV)."
+ ::= { dcmim2ConfigLVDEntry 3 }
+
+dcmim2ConfigLVDState OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusClosed (1),
+ statusOpened (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusClosed (1) if the LVD is closed.
+ statusOpened (2) will be returned if the LVD is opened."
+ ::= { dcmim2ConfigLVDEntry 4 }
+
+
+-- the dcmim2StatusSystem group
+
+dcmim2StatusSysRectCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System (Total Rectifier) current in thousandths of Amps (mA)."
+ ::= { dcmim2StatusSystem 1 }
+
+dcmim2StatusSysLoadCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Load current in thousandths of Amps (mA)."
+ ::= { dcmim2StatusSystem 2 }
+
+dcmim2StatusSysBusVoltage OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System bus voltage in thousandths of Volts (mV)."
+ ::= { dcmim2StatusSystem 3 }
+
+dcmim2StatusSysAmbientTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "System temperature based on sensor on Master Controller PCB.
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dcmim2StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+ ::= { dcmim2StatusSystem 4 }
+
+dcmim2StatusSysUpTime OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Length of time since the DC Powerplant controller has been powered up."
+ ::= { dcmim2StatusSystem 5 }
+
+dcmim2StatusSysTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ in the DC system, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { dcmim2StatusSystem 6 }
+
+
+-- the dcmim2StatusRectifier group
+
+dcmim2StatusRectTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant rectifiers viewable
+ by this IP address."
+ ::= { dcmim2StatusRectifier 1 }
+
+dcmim2StatusRectTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DC2StatusRectEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing settings of the rectifiers. The number of
+ entries is contained in the dcmim2StatusRectTableSize OID."
+ ::= { dcmim2StatusRectifier 2 }
+
+dcmim2StatusRectEntry OBJECT-TYPE
+ SYNTAX DC2StatusRectEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The rectifier to gather status from."
+ INDEX { dcmim2StatusRectIndex }
+ ::= { dcmim2StatusRectTable 1 }
+
+DC2StatusRectEntry ::=
+ SEQUENCE {
+ dcmim2StatusRectIndex INTEGER,
+ dcmim2StatusRectDevType INTEGER,
+ dcmim2StatusRectID INTEGER,
+ dcmim2StatusRectPhyAddr INTEGER,
+ dcmim2StatusRectFail INTEGER,
+ dcmim2StatusRectCurrent INTEGER
+ }
+
+dcmim2StatusRectIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant rectifier."
+ ::= { dcmim2StatusRectEntry 1 }
+
+dcmim2StatusRectDevType OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier device type."
+ ::= { dcmim2StatusRectEntry 2 }
+
+dcmim2StatusRectID OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier ID. This enumerates the number of the rectifier within
+ a group of rectifiers."
+ ::= { dcmim2StatusRectEntry 3 }
+
+dcmim2StatusRectPhyAddr OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the rectifier physical address (the address on the bus)."
+ ::= { dcmim2StatusRectEntry 4 }
+
+dcmim2StatusRectFail OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusTrue (1),
+ statusFalse (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusTrue (1) if the rectifier has failed.
+ statusFalse (2) will be returned if the rectifier has not failed."
+ ::= { dcmim2StatusRectEntry 5 }
+
+dcmim2StatusRectCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID shows the individual rectifier current in thousandths of Amps (mA)."
+ ::= { dcmim2StatusRectEntry 6 }
+
+
+-- the dcmim2StatusBattery group
+
+dcmim2StatusBattFloatVolt OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Float Voltage represented in thousandths of Volts (mV)."
+ ::= { dcmim2StatusBattery 1 }
+
+dcmim2StatusBattCurrent OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Current: This OID shows the battery current in thousandths of Amps (mA)."
+ ::= { dcmim2StatusBattery 2 }
+
+dcmim2StatusBattTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery Temperature:
+
+ Values are represented in thousandths of a degree.
+ Units are displayed in the scale shown in
+ the 'dcmim2StatusSysTempUnits' OID (Celsius or Fahrenheit)."
+ ::= { dcmim2StatusBattery 3 }
+
+dcmim2StatusBattMfgCapacity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery capacity (Amp-Hour Size) as specified by the battery manufacturer.
+ Values are represented in thousandths of Amp hours (mAHr)."
+ ::= { dcmim2StatusBattery 4 }
+
+dcmim2StatusBattTestCapacity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Battery capacity (Amp-Hour Size) as determined by the battery capacity test.
+ Values are represented in thousandths of Amp hours (mAHr)."
+ ::= { dcmim2StatusBattery 5 }
+
+dcmim2StatusBattFunctTestResult OBJECT-TYPE
+ SYNTAX INTEGER{
+ functTestNotPerformed (1),
+ functTestInProcess (2),
+ functTestInterrupted (3),
+ functTestPass (4),
+ functTestFail (5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Results of the last battery functional test that was run."
+ ::= { dcmim2StatusBattery 6 }
+
+dcmim2StatusBattCapacityTestResult OBJECT-TYPE
+ SYNTAX INTEGER{
+ capacityTestNotPerformed (1),
+ capacityTestInProcess (2),
+ capacityTestInterrupted (3),
+ capacityTestPass (4),
+ capacityTestFail (5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Results of the last battery capacity test that was run."
+ ::= { dcmim2StatusBattery 7 }
+
+
+-- the dcmim2StatusLVD group
+
+dcmim2StatusLVDTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant LVDs accessible
+ by this IP address."
+ ::= { dcmim2StatusLVD 1 }
+
+dcmim2StatusLVDTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DC2StatusLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing the LVDs. The number of
+ entries is contained in the dcmim2StatusLVDTableSize OID."
+ ::= { dcmim2StatusLVD 2 }
+
+dcmim2StatusLVDEntry OBJECT-TYPE
+ SYNTAX DC2StatusLVDEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The LVD to access."
+ INDEX { dcmim2StatusLVDIndex }
+ ::= { dcmim2StatusLVDTable 1 }
+
+DC2StatusLVDEntry ::=
+ SEQUENCE {
+ dcmim2StatusLVDIndex INTEGER,
+ dcmim2StatusLVDState INTEGER
+ }
+
+dcmim2StatusLVDIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the DC powerplant LVD."
+ ::= { dcmim2StatusLVDEntry 1 }
+
+dcmim2StatusLVDState OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusClosed (1),
+ statusOpened (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this OID will return statusClosed (1) if the LVD is closed.
+ statusOpened (2) will be returned if the LVD is opened."
+ ::= { dcmim2StatusLVDEntry 2 }
+
+
+-- the dcmim2StatusAlarms group
+
+dcmim2StatusAlarmsTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of DC powerplant alarms viewable
+ by this IP address."
+ ::= { dcmim2StatusAlarms 1 }
+
+dcmim2StatusAlarmsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DC2StatusAlarmsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for accessing system alarms. The number of
+ entries is contained in the dcmim2StatusAlarmsTableSize OID."
+ ::= { dcmim2StatusAlarms 2 }
+
+dcmim2StatusAlarmsEntry OBJECT-TYPE
+ SYNTAX DC2StatusAlarmsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The alarm to display."
+ INDEX { dcmim2StatusAlarmsIndex }
+ ::= { dcmim2StatusAlarmsTable 1 }
+
+DC2StatusAlarmsEntry ::=
+ SEQUENCE {
+ dcmim2StatusAlarmsIndex INTEGER,
+ dcmim2StatusAlarmsText DisplayString
+ }
+
+dcmim2StatusAlarmsIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the system alarm."
+ ::= { dcmim2StatusAlarmsEntry 1 }
+
+dcmim2StatusAlarmsText OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The 16 character text describing the active alarm condition."
+ ::= { dcmim2StatusAlarmsEntry 2 }
+
+-- External Environmental Monitor
+
+emIdentFirmwareRevision OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the Environmental Monitor."
+ ::= { emIdent 1 }
+
+emConfigProbesNumProbes OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of temperature and humidity probes available."
+ ::= { emConfig 1 }
+
+emConfigProbesTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EmConfigProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of probes supported by the Environmental Monitor
+ and their configurations."
+ ::= { emConfig 2 }
+
+emConfigProbesEntry OBJECT-TYPE
+ SYNTAX EmConfigProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The Environmental Monitor probe configurations."
+ INDEX { emConfigProbeNumber }
+ ::= { emConfigProbesTable 1 }
+
+EmConfigProbesEntry ::=
+ SEQUENCE {
+ emConfigProbeNumber
+ INTEGER,
+ emConfigProbeName
+ DisplayString,
+ emConfigProbeHighTempThreshold
+ INTEGER,
+ emConfigProbeLowTempThreshold
+ INTEGER,
+ emConfigProbeTempUnits
+ INTEGER,
+ emConfigProbeHighHumidThreshold
+ INTEGER,
+ emConfigProbeLowHumidThreshold
+ INTEGER,
+ emConfigProbeHighTempEnable
+ INTEGER,
+ emConfigProbeLowTempEnable
+ INTEGER,
+ emConfigProbeHighHumidEnable
+ INTEGER,
+ emConfigProbeLowHumidEnable
+ INTEGER
+ }
+
+emConfigProbeNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index into an Environmental Monitor probe entry."
+ ::= { emConfigProbesEntry 1 }
+
+emConfigProbeName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name of the probe set by the user,
+ possibly denoting its location or purpose."
+ ::= { emConfigProbesEntry 2 }
+
+emConfigProbeHighTempThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature alarm threshold for the probe.
+ Units are displayed in the scale selected in
+ the 'emConfigProbeTempUnits' OID (Celsius or Fahrenheit)."
+ ::= { emConfigProbesEntry 3 }
+
+emConfigProbeLowTempThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low temperature alarm threshold for the probe.
+ Units are displayed in the scale selected in
+ the 'emConfigProbeTempUnits' OID (Celsius or Fahrenheit)."
+ ::= { emConfigProbesEntry 4 }
+
+emConfigProbeTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ thresholds of the probe, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { emConfigProbesEntry 5 }
+
+emConfigProbeHighHumidThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high humidity alarm threshold for the probe in
+ percent relative humidity."
+ ::= { emConfigProbesEntry 6 }
+
+emConfigProbeLowHumidThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low humidity alarm threshold for the probe in
+ percent relative humidity."
+ ::= { emConfigProbesEntry 7 }
+
+emConfigProbeHighTempEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { emConfigProbesEntry 8 }
+
+emConfigProbeLowTempEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low temperature alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { emConfigProbesEntry 9 }
+
+emConfigProbeHighHumidEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high humidity alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { emConfigProbesEntry 10 }
+
+emConfigProbeLowHumidEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low humidity alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { emConfigProbesEntry 11 }
+
+emConfigContactsNumContacts OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of contacts supported by the Environmental
+ Monitor."
+ ::= { emConfig 3 }
+
+emConfigContactsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EmConfigContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of contacts supported by the Environmental Monitor
+ and their configurations."
+ ::= { emConfig 4 }
+
+emConfigContactsEntry OBJECT-TYPE
+ SYNTAX EmConfigContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The Environmental Monitor contact configurations."
+ INDEX { emConfigContactNumber }
+ ::= { emConfigContactsTable 1 }
+
+EmConfigContactsEntry ::=
+ SEQUENCE {
+ emConfigContactNumber
+ INTEGER,
+ emConfigContactName
+ DisplayString,
+ emConfigContactEnable
+ INTEGER
+ }
+
+emConfigContactNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of an Environmental Monitor contact."
+ ::= { emConfigContactsEntry 1 }
+
+emConfigContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for an Environmental Monitor
+ contact set by the user, possibly denoting its
+ location or purpose."
+ ::= { emConfigContactsEntry 2 }
+
+emConfigContactEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "An Environmental Monitor contact alarm enable/disable.
+ No alarm will be generated if the contact is disabled(1).
+ An alarm will be generated if the contact is enabled(2)
+ and the contact has been faulted."
+ ::= { emConfigContactsEntry 3 }
+
+emStatusCommStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ noComm(1),
+ comm(2),
+ commLost(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The communication status between the agent
+ and the Environmental Monitor.
+
+ noComm(1), Communication has never been established.
+ comm(2), Communication has been established.
+ commLost(3), Communication was established, but was lost."
+ ::= { emStatus 1 }
+
+emStatusProbesNumProbes OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of available probes on the Environmental
+ Monitor."
+ ::= { emStatus 2 }
+
+emStatusProbesTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EmStatusProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of probes supported by the Environmental Monitor
+ and their status."
+ ::= { emStatus 3 }
+
+emStatusProbesEntry OBJECT-TYPE
+ SYNTAX EmStatusProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the probe."
+ INDEX { emStatusProbeNumber }
+ ::= { emStatusProbesTable 1 }
+
+EmStatusProbesEntry ::=
+ SEQUENCE {
+ emStatusProbeNumber
+ INTEGER,
+ emStatusProbeName
+ DisplayString,
+ emStatusProbeStatus
+ INTEGER,
+ emStatusProbeCurrentTemp
+ INTEGER,
+ emStatusProbeTempUnits
+ INTEGER,
+ emStatusProbeCurrentHumid
+ INTEGER,
+ emStatusProbeHighTempViolation
+ INTEGER,
+ emStatusProbeLowTempViolation
+ INTEGER,
+ emStatusProbeHighHumidViolation
+ INTEGER,
+ emStatusProbeLowHumidViolation
+ INTEGER
+ }
+
+emStatusProbeNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the probe."
+ ::= { emStatusProbesEntry 1 }
+
+emStatusProbeName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for the probe set by the user,
+ possibly denoting its location or purpose."
+ ::= { emStatusProbesEntry 2 }
+
+emStatusProbeStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ disconnected(1),
+ connected(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The connected status of the probe, either
+ disconnected(1) or connected(2)."
+ ::= { emStatusProbesEntry 3 }
+
+emStatusProbeCurrentTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current temperature reading from the probe displayed
+ in the units shown in the 'emStatusProbeTempUnits' OID
+ (Celsius or Fahrenheit)."
+ ::= { emStatusProbesEntry 4 }
+
+emStatusProbeTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ thresholds of the probe, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { emStatusProbesEntry 5 }
+
+emStatusProbeCurrentHumid OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current humidity reading from the probe in
+ percent relative humidity."
+ ::= { emStatusProbesEntry 6 }
+
+emStatusProbeHighTempViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ highTempViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature violation status of the probe
+ temperature reading. This OID will show a highTempViolation(2)
+ if the current temperature reading shown in the
+ 'emStatusProbeCurrentTemp' OID is greater than or equal to
+ the high temperature threshold value, the
+ 'emConfigProbeHighTempThreshold' OID, and the value of the
+ 'emConfigProbeHighTempEnable' OID is enabled. Otherwise it will show
+ noViolation(1). If the 'emConfigProbeHighTempEnable' OID is disabled,
+ this OID will show disabled(3)."
+ ::= { emStatusProbesEntry 7 }
+
+emStatusProbeLowTempViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ lowTempViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature violation status of the probe
+ temperature reading. This OID will show a lowTempViolation(2)
+ if the current temperature reading shown in the
+ 'emStatusProbeCurrentTemp' OID is less than or equal to
+ the low temperature threshold value, the
+ 'emConfigProbeLowTempThreshold' OID, and the value of the
+ 'emConfigProbeLowTempEnable' OID is enabled. Otherwise it will show
+ noViolation(1). If the 'emConfigProbeLowTempEnable' OID is disabled,
+ this OID will show disabled(3)."
+ ::= { emStatusProbesEntry 8 }
+
+emStatusProbeHighHumidViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ highHumidViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The high humidity violation status of the probe humidity
+ reading. This OID will show a highTempViolation(2)
+ if the current humidity reading shown in the
+ 'emStatusProbeCurrentHumid' OID is greater than or equal to
+ the high humidity threshold value, the
+ 'emConfigProbeHighHumidThreshold' OID, and the value of the
+ 'emConfigProbeHighHumidEnable' OID is enabled. Otherwise it will
+ show noViolation(1). If the 'emConfigProbeHighHumidEnable' OID is
+ disabled, this OID will show disabled(3)"
+ ::= { emStatusProbesEntry 9 }
+
+emStatusProbeLowHumidViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ lowHumidViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The low humidity violation status of the probe humidity
+ reading. This OID will show a lowTempViolation(2)
+ if the current humidity reading shown in the
+ 'emStatusProbeCurrentHumid' OID is less than or equal to
+ the low humidity threshold value, the
+ 'emConfigProbeLowHumidThreshold' OID, and the value of the
+ 'emConfigProbeLowHumidEnable' OID is enabled. Otherwise it will
+ show noViolation(1). If the 'emConfigProbeLowHumidEnable' OID is
+ disabled, this OID will show disabled(3)."
+ ::= { emStatusProbesEntry 10 }
+
+emStatusContactsNumContacts OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of contacts supported by the
+ Environmental Monitor."
+ ::= { emStatus 4 }
+
+emStatusContactsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EmStatusContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of contacts supported by the Environmental Monitor
+ and their status."
+ ::= { emStatus 5 }
+
+emStatusContactsEntry OBJECT-TYPE
+ SYNTAX EmStatusContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the contact."
+ INDEX { emStatusContactNumber }
+ ::= { emStatusContactsTable 1 }
+
+EmStatusContactsEntry ::=
+ SEQUENCE {
+ emStatusContactNumber
+ INTEGER,
+ emStatusContactName
+ DisplayString,
+ emStatusContactStatus
+ INTEGER
+ }
+
+emStatusContactNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the Environmental Monitor contact."
+ ::= { emStatusContactsEntry 1 }
+
+emStatusContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for the Environmental Monitor contact
+ set by the user, possibly denoting its location or purpose."
+ ::= { emStatusContactsEntry 2 }
+
+emStatusContactStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ noFault(1),
+ fault(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Environmental Monitor contact. The status
+ will show noFault(1) if the contact is in the normal state
+ and the 'emConfigContactEnable' OID is enabled. The status will
+ show a fault(2) if the contact is faulted and the
+ 'emContactEnable' OID is enabled. If the 'emConfigContactEnable'
+ OID is disabled, the status will show disabled(3)."
+ ::= { emStatusContactsEntry 3 }
+
+-- Integrated Environmental Monitor (IEM)
+
+iemIdentHardwareRevision OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the Integrated Environmental
+ Monitor."
+ ::= { iemIdent 1 }
+
+iemConfigProbesNumProbes OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of temperature and humidity probes available."
+ ::= { iemConfig 1 }
+
+iemConfigProbesTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IemConfigProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of probes supported by the Environmental Monitor
+ and their configurations."
+ ::= { iemConfig 2 }
+
+iemConfigProbesEntry OBJECT-TYPE
+ SYNTAX IemConfigProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The Environmental Monitor probe configurations."
+ INDEX { iemConfigProbeNumber }
+ ::= { iemConfigProbesTable 1 }
+
+IemConfigProbesEntry ::=
+ SEQUENCE {
+ iemConfigProbeNumber
+ INTEGER,
+ iemConfigProbeName
+ DisplayString,
+ iemConfigProbeHighTempThreshold
+ INTEGER,
+ iemConfigProbeLowTempThreshold
+ INTEGER,
+ iemConfigProbeTempUnits
+ INTEGER,
+ iemConfigProbeHighHumidThreshold
+ INTEGER,
+ iemConfigProbeLowHumidThreshold
+ INTEGER,
+ iemConfigProbeHighTempEnable
+ INTEGER,
+ iemConfigProbeLowTempEnable
+ INTEGER,
+ iemConfigProbeHighHumidEnable
+ INTEGER,
+ iemConfigProbeLowHumidEnable
+ INTEGER
+ }
+
+iemConfigProbeNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to a Environmental Monitor probe entry."
+ ::= { iemConfigProbesEntry 1 }
+
+iemConfigProbeName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for the probe set by the user,
+ possibly denoting its location or purpose."
+ ::= { iemConfigProbesEntry 2 }
+
+iemConfigProbeHighTempThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature alarm threshold for the probe.
+ Units are displayed in the scale selected in the
+ 'iemConfigProbeTempUnits' OID (Celsius or Fahrenheit)."
+ ::= { iemConfigProbesEntry 3 }
+
+iemConfigProbeLowTempThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low temperature alarm threshold for the probe.
+ Units are displayed in the scale selected in the
+ 'iemConfigProbeTempUnits' OID (Celsius or Fahrenheit)."
+ ::= { iemConfigProbesEntry 4 }
+
+iemConfigProbeTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ thresholds of the probe, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { iemConfigProbesEntry 5 }
+
+iemConfigProbeHighHumidThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high humidity alarm threshold for the probe in
+ percent relative humidity."
+ ::= { iemConfigProbesEntry 6 }
+
+iemConfigProbeLowHumidThreshold OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low humidity alarm threshold for the probe in
+ percent relative humidity."
+ ::= { iemConfigProbesEntry 7 }
+
+iemConfigProbeHighTempEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { iemConfigProbesEntry 8 }
+
+iemConfigProbeLowTempEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low temperature alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { iemConfigProbesEntry 9 }
+
+iemConfigProbeHighHumidEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The high humidity alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { iemConfigProbesEntry 10 }
+
+iemConfigProbeLowHumidEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The low humidity alarm enable/disable for the
+ probe. No alarm will be generated if this value
+ is set to disabled(1). The alarm will be
+ generated if this value is set to enabled(2) and
+ the threshold has been violated."
+ ::= { iemConfigProbesEntry 11 }
+
+iemConfigContactsNumContacts OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of contacts available on the Environmental
+ Monitor."
+ ::= { iemConfig 3 }
+
+iemConfigContactsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IemConfigContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of contacts supported by the Environmental Monitor
+ and their configurations."
+ ::= { iemConfig 4 }
+
+iemConfigContactsEntry OBJECT-TYPE
+ SYNTAX IemConfigContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The Environmental Monitor contact configurations."
+ INDEX { iemConfigContactNumber }
+ ::= { iemConfigContactsTable 1 }
+
+IemConfigContactsEntry ::=
+ SEQUENCE {
+ iemConfigContactNumber
+ INTEGER,
+ iemConfigContactName
+ DisplayString,
+ iemConfigContactEnable
+ INTEGER
+ }
+
+iemConfigContactNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of an Environmental Monitor contact."
+ ::= { iemConfigContactsEntry 1 }
+
+iemConfigContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for the Environmental Monitor contact
+ set by the user, possibly denoting its location or purpose."
+ ::= { iemConfigContactsEntry 2 }
+
+iemConfigContactEnable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "An Environmental Monitor contact alarm enable/disable."
+ ::= { iemConfigContactsEntry 3 }
+
+
+iemStatusProbesNumProbes OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of available probes on the Environmental
+ Monitor."
+ ::= { iemStatus 1 }
+
+iemStatusProbesTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IemStatusProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of probes supported by the Environmental Monitor
+ and their status."
+ ::= { iemStatus 2 }
+
+iemStatusProbesEntry OBJECT-TYPE
+ SYNTAX IemStatusProbesEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the probe."
+ INDEX { iemStatusProbeNumber }
+ ::= { iemStatusProbesTable 1 }
+
+IemStatusProbesEntry ::=
+ SEQUENCE {
+ iemStatusProbeNumber
+ INTEGER,
+ iemStatusProbeName
+ DisplayString,
+ iemStatusProbeStatus
+ INTEGER,
+ iemStatusProbeCurrentTemp
+ INTEGER,
+ iemStatusProbeTempUnits
+ INTEGER,
+ iemStatusProbeCurrentHumid
+ INTEGER,
+ iemStatusProbeHighTempViolation
+ INTEGER,
+ iemStatusProbeLowTempViolation
+ INTEGER,
+ iemStatusProbeHighHumidViolation
+ INTEGER,
+ iemStatusProbeLowHumidViolation
+ INTEGER
+ }
+
+iemStatusProbeNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the probe."
+ ::= { iemStatusProbesEntry 1 }
+
+iemStatusProbeName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for the probe set by the user,
+ denoting its location or purpose."
+ ::= { iemStatusProbesEntry 2 }
+
+iemStatusProbeStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ disconnected(1),
+ connected(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The connected status of the probe, either
+ disconnected(1) or connected(2)."
+ ::= { iemStatusProbesEntry 3 }
+
+iemStatusProbeCurrentTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current temperature reading from the probe displayed
+ in the units shown in the 'iemStatusProbeTempUnits' OID
+ (Celsius or Fahrenheit)."
+ ::= { iemStatusProbesEntry 4 }
+
+iemStatusProbeTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ thresholds of the probe, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { iemStatusProbesEntry 5 }
+
+iemStatusProbeCurrentHumid OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current humidity reading from the probe in percent
+ relative humidity."
+ ::= { iemStatusProbesEntry 6 }
+
+iemStatusProbeHighTempViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ highTempViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature violation status of the probe
+ temperature reading. This OID will show a highTempViolation(2)
+ if the current temperature reading shown in the
+ 'iemStatusProbeCurrentTemp' OID is greater than or equal to
+ the high temperature threshold value, the
+ 'iemConfigProbeHighTempThreshold' OID, and the value of the
+ 'iemConfigProbeHighTempEnable' OID is enabled. Otherwise it will show
+ noViolation(1). If the 'iemConfigProbeHighTempEnable' OID is disabled,
+ this OID will show disabled(3)."
+ ::= { iemStatusProbesEntry 7 }
+
+iemStatusProbeLowTempViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ lowTempViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The high temperature violation status of the probe
+ temperature reading. This OID will show a lowTempViolation(2)
+ if the current temperature reading shown in the
+ 'iemStatusProbeCurrentTemp' OID is less than or equal to
+ the low temperature threshold value, the
+ 'iemConfigProbeLowTempThreshold' OID, and the value of the
+ 'iemPConfigrobeLowTempEnable' OID is enabled. Otherwise it will show
+ noViolation(1). If the 'iemConfigProbeLowTempEnable' OID is disabled,
+ this OID will show disabled(3)."
+ ::= { iemStatusProbesEntry 8 }
+
+iemStatusProbeHighHumidViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ highHumidViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The high humidity violation status of the probe humidity
+ reading. This OID will show a highTempViolation(2)
+ if the current humidity reading shown in the
+ 'iemStatusProbeCurrentHumid' OID is greater than or equal to
+ the high humidity threshold value, the
+ 'iemConfigProbeHighHumidThreshold' OID, and the value of the
+ 'iemConfigProbeHighHumidEnable' OID is enabled. Otherwise it will
+ show noViolation(1). If the 'iemConfigProbeHighHumidEnable' OID is
+ disabled, this OID will show disabled(3)."
+ ::= { iemStatusProbesEntry 9 }
+
+iemStatusProbeLowHumidViolation OBJECT-TYPE
+ SYNTAX INTEGER {
+ noViolation(1),
+ lowHumidViolation(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The low humidity violation status of the probe humidity
+ reading. This OID will show a lowTempViolation(2)
+ if the current humidity reading shown in the
+ 'iemStatusProbeCurrentHumid' OID is less than or equal to
+ the low humidity threshold value, the
+ 'iemConfigProbeLowHumidThreshold' OID, and the value of the
+ 'iemConfigProbeLowHumidEnable' OID is enabled. Otherwise it will
+ show noViolation(1). If the 'iemConfigProbeLowHumidEnable' OID is
+ disabled, this OID will show disabled(3)."
+ ::= { iemStatusProbesEntry 10 }
+
+iemStatusContactsNumContacts OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of contacts supported on the
+ Environmental Monitor."
+ ::= { iemStatus 3 }
+
+iemStatusContactsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IemStatusContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of contacts supported by the Environmental Monitor
+ and their status."
+ ::= { iemStatus 4 }
+
+iemStatusContactsEntry OBJECT-TYPE
+ SYNTAX IemStatusContactsEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the contact."
+ INDEX { iemStatusContactNumber }
+ ::= { iemStatusContactsTable 1 }
+
+IemStatusContactsEntry ::=
+ SEQUENCE {
+ iemStatusContactNumber
+ INTEGER,
+ iemStatusContactName
+ DisplayString,
+ iemStatusContactStatus
+ INTEGER
+ }
+
+iemStatusContactNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the Environmental Monitor contact."
+ ::= { iemStatusContactsEntry 1 }
+
+iemStatusContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for the Environmental Monitor contact
+ set by the user, denoting its location or purpose."
+ ::= { iemStatusContactsEntry 2 }
+
+iemStatusContactStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ noFault(1),
+ fault(2),
+ disabled(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the Environmental Monitor contact. The status
+ will show noFault(1) if the contact is in the normal state
+ and the 'iemConfigContactEnable' OID is enabled. The status will
+ show a fault(2) if the contact is faulted and the
+ 'iemConfigContactEnable' OID is enabled. If the
+ 'iemConfigContactEnable' OID is disabled, the status will show
+ disabled(3)."
+ ::= { iemStatusContactsEntry 3 }
+
+iemStatusRelaysNumRelays OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of output relays supported on the
+ Environmental Monitor."
+ ::= { iemStatus 6 }
+
+iemStatusRelaysTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IemStatusRelaysEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "A list of output relays supported by the
+ Environmental Monitor and their status."
+ ::= { iemStatus 7 }
+
+iemStatusRelaysEntry OBJECT-TYPE
+ SYNTAX IemStatusRelaysEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the relay."
+ INDEX { iemStatusRelayNumber }
+ ::= { iemStatusRelaysTable 1 }
+
+IemStatusRelaysEntry ::=
+ SEQUENCE {
+ iemStatusRelayNumber
+ INTEGER,
+ iemStatusRelayName
+ DisplayString,
+ iemStatusRelayStatus
+ INTEGER
+ }
+
+iemStatusRelayNumber OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the output relay."
+ ::= { iemStatusRelaysEntry 1 }
+
+iemStatusRelayName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A descriptive name for the output relay set by the
+ user, denoting its location or purpose."
+ ::= { iemStatusRelaysEntry 2 }
+
+iemStatusRelayStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ faultState(1),
+ normalState(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the output relay, either faultState(1) or
+ normalState(2)."
+ ::= { iemStatusRelaysEntry 3 }
+
+-- Environmental Management System (EMS)
+
+-- EMS IDENT
+
+emsIdentEMSName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ device. "
+ ::= { emsIdent 1 }
+
+emsIdentProductNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the model number of
+ the device. This value is set at the factory."
+ ::= { emsIdent 2 }
+
+emsIdentFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The firmware revision of the device."
+ ::= { emsIdent 3 }
+
+emsIdentHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The hardware revision of the device.
+ This value is set at the factory."
+ ::= { emsIdent 4 }
+
+emsIdentDateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The date when the device was manufactured in mm/dd/yyyy format.
+ This value is set at the factory. "
+ ::= { emsIdent 5 }
+
+emsIdentSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the serial number of
+ the device. This value is set at the factory."
+ ::= { emsIdent 6 }
+
+-- EMS CONTROL
+
+-- EMS OUTPUT RELAY CONTROL STATUS TABLE
+
+emsOutputRelayControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutputRelayControlEMSEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of individual output relays. The number of
+ entries is contained in the emsStatusOutputRelayCount OID."
+ ::= { emsOutputRelayControl 1 }
+
+emsOutputRelayControlEntry OBJECT-TYPE
+ SYNTAX OutputRelayControlEMSEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The output relays to control."
+ INDEX { emsOutputRelayControlOutputRelayIndex }
+ ::= { emsOutputRelayControlTable 1 }
+
+OutputRelayControlEMSEntry ::=
+ SEQUENCE {
+ emsOutputRelayControlOutputRelayIndex INTEGER,
+ emsOutputRelayControlOutputRelayName DisplayString,
+ emsOutputRelayControlOutputRelayCommand INTEGER
+ }
+
+emsOutputRelayControlOutputRelayIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the output relay entry."
+ ::= { emsOutputRelayControlEntry 1 }
+
+emsOutputRelayControlOutputRelayName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the output relay.
+ This OID is provided for informational purposes only."
+ ::= { emsOutputRelayControlEntry 2 }
+
+emsOutputRelayControlOutputRelayCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ immediateCloseEMS (1),
+ immediateOpenEMS (2)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the output relay state. If
+ the output relay is closed, the immediateCloseEMS (1) value will be returned.
+ If the output relay is open, the immediateOpenEMS (2) value will be
+ returned.
+
+ Setting this variable to immediateCloseEMS (1) will immediately close the relay.
+
+ Setting this variable to immediateOpenEMS (2) will immediately open the relay."
+ ::= { emsOutputRelayControlEntry 3 }
+
+-- EMS OUTLET CONTROL TABLE
+
+emsOutletControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF OutletControlEMSEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of individual outlet switches. The number of
+ entries is contained in the emsStatusOutletCount OID."
+ ::= { emsOutletControl 1 }
+
+emsOutletControlEntry OBJECT-TYPE
+ SYNTAX OutletControlEMSEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to control."
+ INDEX { emsOutletControlOutletIndex }
+ ::= { emsOutletControlTable 1 }
+
+OutletControlEMSEntry ::=
+ SEQUENCE {
+ emsOutletControlOutletIndex INTEGER,
+ emsOutletControlOutletName DisplayString,
+ emsOutletControlOutletCommand INTEGER
+ }
+
+emsOutletControlOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { emsOutletControlEntry 1 }
+
+emsOutletControlOutletName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet.
+ This OID is provided for informational purposes only."
+ ::= { emsOutletControlEntry 2 }
+
+emsOutletControlOutletCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ immediateOnEMS (1),
+ immediateOffEMS (2)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the outlet state. If
+ the outlet is on, the immediateOnEMS (1) value will be returned.
+ If the outlet is off, the immediateOffEMS (2) value will be
+ returned.
+
+ Setting this variable to immediateOnEMS (1) will immediately turn the outlet on.
+
+ Setting this variable to immediateOffEMS (2) will immediately turn the outlet off."
+ ::= { emsOutletControlEntry 3 }
+
+-- EMS SENSOR CONTROL TABLE
+
+emsSensorControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSSensorControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control/reset of individual sensors. The number of
+ entries is contained in the emsStatusSensorCount OID."
+ ::= { emsSensorControl 1 }
+
+emsSensorControlEntry OBJECT-TYPE
+ SYNTAX EMSSensorControlEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The sensors to control/reset."
+ INDEX { emsSensorControlSensorIndex }
+ ::= { emsSensorControlTable 1 }
+
+EMSSensorControlEntry ::=
+ SEQUENCE {
+ emsSensorControlSensorIndex INTEGER,
+ emsSensorControlSensorSystemName DisplayString,
+ emsSensorControlSensorUserName DisplayString,
+ emsSensorControlSensorCommand INTEGER
+ }
+
+emsSensorControlSensorIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the sensor entry."
+ ::= { emsSensorControlEntry 1 }
+
+emsSensorControlSensorSystemName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system name of the sensor. This describes the hardware system
+ intent of this sensor."
+ ::= { emsSensorControlEntry 2 }
+
+emsSensorControlSensorUserName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the sensor as given by the system user."
+ ::= { emsSensorControlEntry 3 }
+
+emsSensorControlSensorCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ noCommandEMS (1),
+ resetCommandEMS (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return noCommandEMS(1).
+
+ Setting this variable to resetCommandEMS(2) will issue a reset command to the
+ sensor. Some sensors cannot be manually reset and will not be affected
+ by this command."
+ ::= { emsSensorControlEntry 4 }
+
+-- EMS ALARM DEVICE CONTROL TABLE
+
+emsAlarmDeviceControlTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AlarmDeviceControlEMSEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for control of individual alarm devices.
+ Note: Some alarm devices are not controllable. The number of
+ entries is contained in the emsStatusAlarmDeviceCount OID."
+ ::= { emsAlarmDeviceControl 1 }
+
+emsAlarmDeviceControlEntry OBJECT-TYPE
+ SYNTAX AlarmDeviceControlEMSEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The alarm devices to control."
+ INDEX { emsAlarmDeviceControlDeviceIndex }
+ ::= { emsAlarmDeviceControlTable 1 }
+
+AlarmDeviceControlEMSEntry ::=
+ SEQUENCE {
+ emsAlarmDeviceControlDeviceIndex INTEGER,
+ emsAlarmDeviceControlDeviceName DisplayString,
+ emsAlarmDeviceControlDeviceCommand INTEGER
+ }
+
+emsAlarmDeviceControlDeviceIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the alarm device entry."
+ ::= { emsAlarmDeviceControlEntry 1 }
+
+emsAlarmDeviceControlDeviceName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the alarm device.
+ This OID is provided for informational purposes only."
+ ::= { emsAlarmDeviceControlEntry 2 }
+
+emsAlarmDeviceControlDeviceCommand OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmDeviceOnEMS (1),
+ alarmDeviceOffEMS (2),
+ alarmDeviceNotInstalledEMS (3)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the device state. If
+ the device is active, the alarmDeviceOnEMS (1) value will be returned.
+ If the device is inactive, the alarmDeviceOffEMS (2) value will be
+ returned. If the device is not installed, the
+ alarmDeviceNotInstalledEMS (3) value will be returned.
+
+ Actions resulting from setting this variable are device-dependent.
+
+ Setting this variable to alarmDeviceOnEMS (1) will turn that device (ex. Beacon) on.
+ Setting this variable to alarmDeviceOffEMS (2) will turn that device off."
+
+ ::= { emsAlarmDeviceControlEntry 3 }
+
+
+-- EMS CONFIG
+
+emsConfigName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the device."
+ ::= { emsConfig 1 }
+
+emsConfigCheckLogLight OBJECT-TYPE
+ SYNTAX INTEGER {
+ lightDisabled (1),
+ lightOnInformational (2),
+ lightOnWarning (3),
+ lightOnSevere (4)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The setting of this OID determines the level of event that will
+ trigger the check-log light on the EMS. This is not available on the EMU2.
+
+ lightDisabled (1) disables the check-log light.
+ lightOnInformational (2) lights check-log for any event of
+ informational severity or above.
+ lightOnWarning (3) lights check-log for any event of
+ warning severity or above.
+ lightOnSevere (4) lights check-log for any event of severe severity."
+
+ ::= { emsConfig 2 }
+
+-- EMS PROBE CONFIG TABLE
+
+emsProbeConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSProbeConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual probes. The number of
+ entries is contained in the emsStatusProbeCount OID."
+ ::= { emsProbeConfig 1 }
+
+emsProbeConfigEntry OBJECT-TYPE
+ SYNTAX EMSProbeConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The probes to configure."
+ INDEX { emsProbeConfigProbeIndex }
+ ::= { emsProbeConfigTable 1 }
+
+EMSProbeConfigEntry ::=
+ SEQUENCE {
+ emsProbeConfigProbeIndex INTEGER,
+ emsProbeConfigProbeName DisplayString,
+ emsProbeConfigProbeHighTempThresh INTEGER,
+ emsProbeConfigProbeLowTempThresh INTEGER,
+ emsProbeConfigProbeHighHumidityThresh INTEGER,
+ emsProbeConfigProbeLowHumidityThresh INTEGER,
+ emsProbeConfigProbeMaxTempThresh INTEGER,
+ emsProbeConfigProbeMinTempThresh INTEGER,
+ emsProbeConfigProbeDeltaTemp INTEGER,
+ emsProbeConfigProbeMaxHumidityThresh INTEGER,
+ emsProbeConfigProbeMinHumidityThresh INTEGER,
+ emsProbeConfigProbeDeltaHumidity INTEGER,
+ emsProbeConfigProbeSTIncTempVariance INTEGER,
+ emsProbeConfigProbeSTIncTempTime INTEGER,
+ emsProbeConfigProbeSTDecTempVariance INTEGER,
+ emsProbeConfigProbeSTDecTempTime INTEGER,
+ emsProbeConfigProbeLTIncTempVariance INTEGER,
+ emsProbeConfigProbeLTIncTempTime INTEGER,
+ emsProbeConfigProbeLTDecTempVariance INTEGER,
+ emsProbeConfigProbeLTDecTempTime INTEGER
+ }
+
+emsProbeConfigProbeIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the probe entry."
+ ::= { emsProbeConfigEntry 1 }
+
+emsProbeConfigProbeName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the probe."
+ ::= { emsProbeConfigEntry 2 }
+
+emsProbeConfigProbeHighTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe high temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 3 }
+
+emsProbeConfigProbeLowTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe low temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 4 }
+
+emsProbeConfigProbeHighHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe high humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeConfigEntry 5 }
+
+emsProbeConfigProbeLowHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe low humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeConfigEntry 6 }
+
+emsProbeConfigProbeMaxTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe maximum temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 7 }
+
+emsProbeConfigProbeMinTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe minimum temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 8 }
+
+emsProbeConfigProbeDeltaTemp OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe delta temperature.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 9 }
+
+emsProbeConfigProbeMaxHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe maximum humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeConfigEntry 10 }
+
+emsProbeConfigProbeMinHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe minimum humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeConfigEntry 11 }
+
+emsProbeConfigProbeDeltaHumidity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe delta humidity.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeConfigEntry 12 }
+
+emsProbeConfigProbeSTIncTempVariance OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe short-term increasing temperature variance used for rate of change alarms.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 13 }
+
+emsProbeConfigProbeSTIncTempTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe short-term increasing temperature time used for rate of change alarms.
+
+ Values are represented in whole number minutes."
+ ::= { emsProbeConfigEntry 14 }
+
+emsProbeConfigProbeSTDecTempVariance OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe short-term decreasing temperature variance used for rate of change alarms.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 15 }
+
+emsProbeConfigProbeSTDecTempTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe short-term decreasing temperature time used for rate of change alarms.
+
+ Values are represented in whole number minutes."
+ ::= { emsProbeConfigEntry 16 }
+
+emsProbeConfigProbeLTIncTempVariance OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe long-term increasing temperature variance used for rate of change alarms.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 17 }
+
+emsProbeConfigProbeLTIncTempTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe long-term increasing temperature time used for rate of change alarms.
+
+ Values are represented in whole number hours."
+ ::= { emsProbeConfigEntry 18 }
+
+emsProbeConfigProbeLTDecTempVariance OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe long-term decreasing temperature variance used for rate of change alarms.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeConfigEntry 19 }
+
+emsProbeConfigProbeLTDecTempTime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Probe long-term decreasing temperature time used for rate of change alarms.
+
+ Values are represented in whole number hours."
+ ::= { emsProbeConfigEntry 20 }
+
+
+-- EMS INPUT CONTACT CONFIG STATUS TABLE
+
+emsInputContactConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSInputContactConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual input contacts. The number of
+ entries is contained in the emsStatusInputContactCount OID."
+ ::= { emsInputContactConfig 1 }
+
+emsInputContactConfigEntry OBJECT-TYPE
+ SYNTAX EMSInputContactConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The input contacts to configure."
+ INDEX { emsInputContactConfigInputContactIndex }
+ ::= { emsInputContactConfigTable 1 }
+
+EMSInputContactConfigEntry ::=
+ SEQUENCE {
+ emsInputContactConfigInputContactIndex INTEGER,
+ emsInputContactConfigInputContactName DisplayString,
+ emsInputContactConfigInputContactNormalState INTEGER
+ }
+
+emsInputContactConfigInputContactIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the input contact entry."
+ ::= { emsInputContactConfigEntry 1 }
+
+emsInputContactConfigInputContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the input contact."
+ ::= { emsInputContactConfigEntry 2 }
+
+emsInputContactConfigInputContactNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyClosedEMS (1),
+ normallyOpenEMS (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the input contact. If
+ the normal state is closed, the normallyClosedEMS (1) value will be returned.
+ If the normal state is closed, the normallyOpenEMS (2) value will be
+ returned.
+
+ Setting this variable will change the normal state of the input contact"
+ ::= { emsInputContactConfigEntry 3 }
+
+-- EMS OUTPUT RELAY CONFIG STATUS TABLE
+
+emsOutputRelayConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSOutputRelayConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual output relays. The number of
+ entries is contained in the emsStatusOutputRelayCount OID."
+ ::= { emsOutputRelayConfig 1 }
+
+emsOutputRelayConfigEntry OBJECT-TYPE
+ SYNTAX EMSOutputRelayConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The output relays to configure."
+ INDEX { emsOutputRelayConfigOutputRelayIndex }
+ ::= { emsOutputRelayConfigTable 1 }
+
+EMSOutputRelayConfigEntry ::=
+ SEQUENCE {
+ emsOutputRelayConfigOutputRelayIndex INTEGER,
+ emsOutputRelayConfigOutputRelayName DisplayString,
+ emsOutputRelayConfigOutputRelayNormalState INTEGER
+ }
+
+emsOutputRelayConfigOutputRelayIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the output relay entry."
+ ::= { emsOutputRelayConfigEntry 1 }
+
+emsOutputRelayConfigOutputRelayName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the output relay."
+ ::= { emsOutputRelayConfigEntry 2 }
+
+emsOutputRelayConfigOutputRelayNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyClosedEMS (1),
+ normallyOpenEMS (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the output relay. If
+ the normal state is closed, the normallyClosedEMS (1) value will be returned.
+ If the normal state is closed, the normallyOpenEMS (2) value will be
+ returned.
+
+ Setting this variable will change the normal state of the output relay"
+ ::= { emsOutputRelayConfigEntry 3 }
+
+-- EMS OUTLET CONFIG TABLE
+
+emsOutletConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSOutletConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual outlets. The number of
+ entries is contained in the emsStatusOutletCount OID."
+ ::= { emsOutletConfig 1 }
+
+emsOutletConfigEntry OBJECT-TYPE
+ SYNTAX EMSOutletConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to configure."
+ INDEX { emsOutletConfigOutletIndex }
+ ::= { emsOutletConfigTable 1 }
+
+EMSOutletConfigEntry ::=
+ SEQUENCE {
+ emsOutletConfigOutletIndex INTEGER,
+ emsOutletConfigOutletName DisplayString,
+ emsOutletConfigOutletNormalState INTEGER
+ }
+
+emsOutletConfigOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { emsOutletConfigEntry 1 }
+
+emsOutletConfigOutletName OBJECT-TYPE
+ SYNTAX DisplayString ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet."
+ ::= { emsOutletConfigEntry 2 }
+
+emsOutletConfigOutletNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyOnEMS (1),
+ normallyOffEMS (2)
+ }
+
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the outlet. If
+ the normal state is on, the normallyOnEMS (1) value will be returned.
+ If the normal state is off, the normallyOffEMS (2) value will be
+ returned.
+
+ Setting this variable will change the normal state of the outlet"
+ ::= { emsOutletConfigEntry 3 }
+
+-- EMS SENSOR CONFIG TABLE
+
+emsSensorConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSSensorConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual sensors. The number of
+ entries is contained in the emsStatusSensorCount OID."
+ ::= { emsSensorConfig 1 }
+
+emsSensorConfigEntry OBJECT-TYPE
+ SYNTAX EMSSensorConfigEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The sensors to configure."
+ INDEX { emsSensorConfigSensorIndex }
+ ::= { emsSensorConfigTable 1 }
+
+EMSSensorConfigEntry ::=
+ SEQUENCE {
+ emsSensorConfigSensorIndex INTEGER,
+ emsSensorConfigSensorSystemName DisplayString,
+ emsSensorConfigSensorUserName DisplayString,
+ emsSensorConfigSensorNormalState INTEGER,
+ emsSensorConfigSensorAlarmDelay INTEGER
+ }
+
+emsSensorConfigSensorIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the sensor entry."
+ ::= { emsSensorConfigEntry 1 }
+
+emsSensorConfigSensorSystemName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system name of the sensor. This describes the hardware system
+ intent of this sensor."
+ ::= { emsSensorConfigEntry 2 }
+
+emsSensorConfigSensorUserName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the sensor as given by the system user."
+ ::= { emsSensorConfigEntry 3 }
+
+emsSensorConfigSensorNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyClosedEMS (1),
+ normallyOpenEMS (2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the sensor. If
+ the normal state is closed, the normallyClosedEMS (1) value will be returned.
+ If the normal state is closed, the normallyOpenEMS (2) value will be
+ returned.
+
+ Setting this variable will change the normal state of the sensor. Note:
+ Only the AUX sensor in the EMS has a configurable Normal State"
+ ::= { emsSensorConfigEntry 4 }
+
+emsSensorConfigSensorAlarmDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The delay (in seconds) after a sensor detects an alarm condition before the
+ condition is reported."
+ ::= { emsSensorConfigEntry 5 }
+
+-- EMS STATUS
+--- EMS MASTER status
+
+emsStatusEMSName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ device. "
+ ::= { emsStatus 1 }
+
+emsStatusCommStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ noComm(1),
+ comm(2),
+ commLost(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The communication status between the agent
+ and the device.
+
+ noComm(1), Communication has never been established.
+ comm(2), Communication has been established.
+ commLost(3), Communication was established, but was lost."
+ ::= { emsStatus 2 }
+
+emsStatusProbeCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of T/H probes (both local and remote) that
+ is supported by this device."
+ ::= { emsStatus 3 }
+
+emsStatusInputContactCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of Input Contacts that
+ is supported by this device."
+ ::= { emsStatus 4 }
+
+emsStatusOutputRelayCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of Output Relays that
+ is supported by this device."
+ ::= { emsStatus 5 }
+
+emsStatusOutletCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of AC Outlets that
+ is supported by this device."
+ ::= { emsStatus 6 }
+
+emsStatusSensorCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of Sensors that
+ is supported by this device."
+ ::= { emsStatus 7 }
+
+emsStatusAlinkAruDeviceCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of remote Aru's supported by this device."
+ ::= { emsStatus 8 }
+
+emsStatusAlinkProbeDeviceCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of remote T/H probes supported by this device."
+ ::= { emsStatus 9 }
+
+emsStatusAlarmDeviceCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of alarm devices supported by this device."
+ ::= { emsStatus 10 }
+
+emsStatusSysTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ in the system, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { emsStatus 11 }
+
+emsStatusCheckLogLight OBJECT-TYPE
+ SYNTAX INTEGER {
+ lightOff (1),
+ lightOn (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the check-log light on the device.
+ For the EMU2, this will always indicate lightOff(1).
+
+ lightOff (1) indicates the light is off (no new log entries).
+ lightOn (2) indicates the light is on (new log entries present)."
+
+ ::= { emsStatus 12 }
+
+emsStatusHardwareStatus OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the EMS hardware. This integer should be interpreted
+ as a bit map, with each bit representing the presence or absence of
+ a specific hardware error condition.
+
+ 0 indicates there are no error conditions detected in the EMS hardware.
+ 1 indicates a Current Limit error condition related to the Alink port.
+ 2 indicates incorrect hardware is plugged into an EMS port.
+ 3 indicates that both of these error conditions are present."
+
+ ::= { emsStatus 13 }
+
+-- EMS PROBE STATUS TABLE
+
+emsProbeStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSProbeStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for access of individual probes. The number of
+ entries is contained in the emsStatusProbeCount OID."
+ ::= { emsProbeStatus 1 }
+
+emsProbeStatusEntry OBJECT-TYPE
+ SYNTAX EMSProbeStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The probes to access."
+ INDEX { emsProbeStatusProbeIndex }
+ ::= { emsProbeStatusTable 1 }
+
+EMSProbeStatusEntry ::=
+ SEQUENCE {
+ emsProbeStatusProbeIndex INTEGER,
+ emsProbeStatusProbeName DisplayString,
+ emsProbeStatusProbeTemperature INTEGER,
+ emsProbeStatusProbeHighTempThresh INTEGER,
+ emsProbeStatusProbeLowTempThresh INTEGER,
+ emsProbeStatusProbeHumidity INTEGER,
+ emsProbeStatusProbeHighHumidityThresh INTEGER,
+ emsProbeStatusProbeLowHumidityThresh INTEGER,
+ emsProbeStatusProbeSerialNumber DisplayString,
+ emsProbeStatusProbeCommStatus INTEGER,
+ emsProbeStatusProbeAlarmStatus INTEGER,
+ emsProbeStatusProbeMaxTempThresh INTEGER,
+ emsProbeStatusProbeMinTempThresh INTEGER,
+ emsProbeStatusProbeMaxHumidityThresh INTEGER,
+ emsProbeStatusProbeMinHumidityThresh INTEGER
+ }
+
+emsProbeStatusProbeIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the probe entry."
+ ::= { emsProbeStatusEntry 1 }
+
+emsProbeStatusProbeName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the probe."
+ ::= { emsProbeStatusEntry 2 }
+
+emsProbeStatusProbeTemperature OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe temperature reading.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeStatusEntry 3 }
+
+emsProbeStatusProbeHighTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe high temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeStatusEntry 4 }
+
+emsProbeStatusProbeLowTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe low temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeStatusEntry 5 }
+
+emsProbeStatusProbeHumidity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe humidity reading.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeStatusEntry 6 }
+
+emsProbeStatusProbeHighHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe high humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeStatusEntry 7 }
+
+emsProbeStatusProbeLowHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe low humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeStatusEntry 8 }
+
+emsProbeStatusProbeSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A label indicating the type (Local[L] or Remote[R]) and Number
+ of the probe. For example, the first local probe would be L1 and
+ the third remote probe would be R3."
+ ::= { emsProbeStatusEntry 9 }
+
+emsProbeStatusProbeCommStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ commsNeverDiscovered(1),
+ commsEstablished(2),
+ commsLost(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ " The state of communications to the probe.
+ commNeverDiscovered(1) indicates there has never been communications with this device.
+ commsEstablished(2) indicates communication is normal and active with this device.
+ commsLost(3) indicates communication had been established, but is no longer."
+ ::= { emsProbeStatusEntry 10 }
+
+emsProbeStatusProbeAlarmStatus OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The alarm status of the probe. This integer should be interpreted
+ as a bit map, with each bit representing the presence or absence of
+ the specific alarm conditions listed below. The bit will be '1' if
+ the condition is present, and '0' if the condition is not present.
+
+ Bit Hex. Value Description
+ 1 0x0001 Maximum temperature exceeded.
+ 2 0x0002 High temperature exceeded.
+ 3 0x0004 Low temperature exceeded.
+ 4 0x0008 Minimum temperature exceeded.
+ 5 0x0010 Short-term increasing temperature rate exceeded.
+ 6 0x0020 Short-term decreasing temperature rate exceeded.
+ 7 0x0040 Long-term increasing temperature rate exceeded.
+ 8 0x0080 Long-term decreasing temperature rate exceeded.
+ 9 0x0100 Maximum humidity exceeded.
+ 10 0x0200 High humidity exceeded.
+ 11 0x0400 Low humidity exceeded.
+ 12 0x0800 Minimum humidity exceeded."
+ ::= { emsProbeStatusEntry 11 }
+
+emsProbeStatusProbeMaxTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe maximum temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeStatusEntry 12 }
+
+emsProbeStatusProbeMinTempThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe minimum temperature threshold.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the emsStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { emsProbeStatusEntry 13 }
+
+emsProbeStatusProbeMaxHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe maximum humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeStatusEntry 14 }
+
+emsProbeStatusProbeMinHumidityThresh OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Probe minimum humidity threshold.
+
+ Values are represented in whole number percentage."
+ ::= { emsProbeStatusEntry 15 }
+
+
+-- EMS INPUT CONTACT STATUS TABLE
+
+emsInputContactStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSInputContactStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for access of individual input contacts. The number of
+ entries is contained in the emsStatusInputContactCount OID."
+ ::= { emsInputContactStatus 1 }
+
+emsInputContactStatusEntry OBJECT-TYPE
+ SYNTAX EMSInputContactStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The input contacts to access."
+ INDEX { emsInputContactStatusInputContactIndex }
+ ::= { emsInputContactStatusTable 1 }
+
+EMSInputContactStatusEntry ::=
+ SEQUENCE {
+ emsInputContactStatusInputContactIndex INTEGER,
+ emsInputContactStatusInputContactName DisplayString,
+ emsInputContactStatusInputContactState INTEGER,
+ emsInputContactStatusInputContactNormalState INTEGER
+ }
+
+emsInputContactStatusInputContactIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the input contact entry."
+ ::= { emsInputContactStatusEntry 1 }
+
+emsInputContactStatusInputContactName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the input contact."
+ ::= { emsInputContactStatusEntry 2 }
+
+emsInputContactStatusInputContactState OBJECT-TYPE
+ SYNTAX INTEGER {
+ contactClosedEMS (1),
+ contactOpenEMS (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the state of the input contact. If
+ the input contact is closed, the contactClosedEMS (1) value will be returned.
+ If the input contact state is open, the contactOpenEMS (2) value will be
+ returned. "
+
+ ::= { emsInputContactStatusEntry 3 }
+
+emsInputContactStatusInputContactNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyClosedEMS (1),
+ normallyOpenEMS (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the input contact. If
+ the normal state is closed, the normallyClosedEMS (1) value will be returned.
+ If the normal state is open, the normallyOpenEMS (2) value will be
+ returned. "
+
+ ::= { emsInputContactStatusEntry 4 }
+
+
+-- EMS OUTPUT RELAY STATUS TABLE
+
+emsOutputRelayStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSOutputRelayStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for access of individual output relays. The number of
+ entries is contained in the emsStatusOutputRelayCount OID."
+ ::= { emsOutputRelayStatus 1 }
+
+emsOutputRelayStatusEntry OBJECT-TYPE
+ SYNTAX EMSOutputRelayStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The output relays to access."
+ INDEX { emsOutputRelayStatusOutputRelayIndex }
+ ::= { emsOutputRelayStatusTable 1 }
+
+EMSOutputRelayStatusEntry ::=
+ SEQUENCE {
+ emsOutputRelayStatusOutputRelayIndex INTEGER,
+ emsOutputRelayStatusOutputRelayName DisplayString,
+ emsOutputRelayStatusOutputRelayState INTEGER,
+ emsOutputRelayStatusOutputRelayNormalState INTEGER
+ }
+
+emsOutputRelayStatusOutputRelayIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the output relay entry."
+ ::= { emsOutputRelayStatusEntry 1 }
+
+emsOutputRelayStatusOutputRelayName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the output relay."
+ ::= { emsOutputRelayStatusEntry 2 }
+
+emsOutputRelayStatusOutputRelayState OBJECT-TYPE
+ SYNTAX INTEGER {
+ relayClosedEMS (1),
+ relayOpenEMS (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the state of the output relay. If
+ the output relay is closed, the relayClosedEMS (1) value will be returned.
+ If the output relay is open, the relayOpenEMS (2) value will be
+ returned. "
+
+ ::= { emsOutputRelayStatusEntry 3 }
+
+emsOutputRelayStatusOutputRelayNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyClosedEMS (1),
+ normallyOpenEMS (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the output relay. If
+ the normal state is closed, the normallyClosedEMS (1) value will be returned.
+ If the normal state is open, the normallyOpenEMS (2) value will be
+ returned. "
+
+ ::= { emsOutputRelayStatusEntry 4 }
+
+-- EMS OUTLET STATUS TABLE
+
+emsOutletStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSOutletStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for access of individual outlets. The number of
+ entries is contained in the emsStatusOutletCount OID."
+ ::= { emsOutletStatus 1 }
+
+emsOutletStatusEntry OBJECT-TYPE
+ SYNTAX EMSOutletStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The outlets to access."
+ INDEX { emsOutletStatusOutletIndex }
+ ::= { emsOutletStatusTable 1 }
+
+EMSOutletStatusEntry ::=
+ SEQUENCE {
+ emsOutletStatusOutletIndex INTEGER,
+ emsOutletStatusOutletName DisplayString,
+ emsOutletStatusOutletState INTEGER,
+ emsOutletStatusOutletNormalState INTEGER
+ }
+
+emsOutletStatusOutletIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the outlet entry."
+ ::= { emsOutletStatusEntry 1 }
+
+emsOutletStatusOutletName OBJECT-TYPE
+ SYNTAX DisplayString ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the outlet."
+ ::= { emsOutletStatusEntry 2 }
+
+emsOutletStatusOutletState OBJECT-TYPE
+ SYNTAX INTEGER {
+ outletOnEMS (1),
+ outletOffEMS (2)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the state of the outlet. If
+ the outlet is on, the outletOnEMS (1) value will be returned.
+ If the outlet is off, the outletOffEMS (2) value will be
+ returned. "
+
+ ::= { emsOutletStatusEntry 3 }
+
+emsOutletStatusOutletNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyOnEMS (1),
+ normallyOffEMS (2)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the outlet. If
+ the normal state is on, the normallyOnEMS (1) value will be returned.
+ If the normal state is off, the normallyOffEMS (2) value will be
+ returned. "
+
+ ::= { emsOutletStatusEntry 4 }
+
+-- EMS ALARM DEVICE STATUS TABLE
+
+emsAlarmDeviceStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSAlarmDeviceStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for access of individual alarm devices. The number of
+ entries is contained in the emsStatusAlarmDeviceCount OID."
+ ::= { emsAlarmDeviceStatus 1 }
+
+emsAlarmDeviceStatusEntry OBJECT-TYPE
+ SYNTAX EMSAlarmDeviceStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The alarm devices to access."
+ INDEX { emsAlarmDeviceStatusDeviceIndex }
+ ::= { emsAlarmDeviceStatusTable 1 }
+
+EMSAlarmDeviceStatusEntry ::=
+ SEQUENCE {
+ emsAlarmDeviceStatusDeviceIndex INTEGER,
+ emsAlarmDeviceStatusDeviceName DisplayString,
+ emsAlarmDeviceStatusDeviceState INTEGER
+ }
+
+emsAlarmDeviceStatusDeviceIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the alarm device entry."
+ ::= { emsAlarmDeviceStatusEntry 1 }
+
+emsAlarmDeviceStatusDeviceName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the alarm device.
+ This OID is provided for informational purposes only."
+ ::= { emsAlarmDeviceStatusEntry 2 }
+
+emsAlarmDeviceStatusDeviceState OBJECT-TYPE
+ SYNTAX INTEGER {
+ alarmDeviceOnEMS (1),
+ alarmDeviceOffEMS (2),
+ alarmDeviceNotInstalledEMS (3)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the device state. If
+ the device is active, the alarmDeviceOnEMS (1) value will be returned.
+ If the device is inactive, the alarmDeviceOffEMS (2) value will be
+ returned. If the device is not installed, the
+ alarmDeviceNotInstalledEMS (3) value will be returned."
+
+ ::= { emsAlarmDeviceStatusEntry 3 }
+
+
+-- EMS SENSOR STATUS TABLE
+
+emsSensorStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF EMSSensorStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for access of individual sensors. The number of
+ entries is contained in the emsStatusSensorCount OID."
+ ::= { emsSensorStatus 1 }
+
+emsSensorStatusEntry OBJECT-TYPE
+ SYNTAX EMSSensorStatusEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The sensors to access."
+ INDEX { emsSensorStatusSensorIndex }
+ ::= { emsSensorStatusTable 1 }
+
+EMSSensorStatusEntry ::=
+ SEQUENCE {
+ emsSensorStatusSensorIndex INTEGER,
+ emsSensorStatusSensorSystemName DisplayString,
+ emsSensorStatusSensorName DisplayString,
+ emsSensorStatusSensorState INTEGER,
+ emsSensorStatusSensorNormalState INTEGER,
+ emsSensorStatusSensorAlarmDelay INTEGER
+ }
+
+emsSensorStatusSensorIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the sensor entry."
+ ::= { emsSensorStatusEntry 1 }
+
+emsSensorStatusSensorSystemName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system name of the sensor. This describes the hardware system
+ intent of this sensor."
+ ::= { emsSensorStatusEntry 2 }
+
+emsSensorStatusSensorName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the sensor as given by the system user."
+ ::= { emsSensorStatusEntry 3 }
+
+emsSensorStatusSensorState OBJECT-TYPE
+ SYNTAX INTEGER {
+ sensorFaultedEMS (1),
+ sensorOKEMS (2),
+ sensorNotInstalledEMS (3)
+ }
+
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the sensor state. If the sensor is faulted,
+ the sensorFaultedEMS (1) value will be returned.
+ If the sensor is not faulted, the sensorOKEMS (2) value will be
+ returned. If the sensor is not installed, the sensorNotInstalledEMS (3)
+ value will be returned."
+ ::= { emsSensorStatusEntry 4 }
+
+emsSensorStatusSensorNormalState OBJECT-TYPE
+ SYNTAX INTEGER {
+ normallyClosedEMS (1),
+ normallyOpenEMS (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "Getting this variable will return the normal state of the sensor. If
+ the normal state is closed, the normallyClosedEMS (1) value will be returned.
+ If the normal state is closed, the normallyOpenEMS (2) value will be
+ returned."
+ ::= { emsSensorStatusEntry 5 }
+
+emsSensorStatusSensorAlarmDelay OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The delay (in seconds) after a sensor detects an alarm condition before the
+ condition is reported."
+ ::= { emsSensorStatusEntry 6 }
+
+
+
+-- airFM AIR CONDITIONER IDENT
+
+airFMIdentName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ device. "
+ ::= { airFMIdent 1 }
+
+airFMIdentTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the airFMIdentTable. "
+ ::= { airFMIdent 2 }
+
+airFMIdentTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AirFMIdentTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting identification information
+ from each module in the system. "
+ ::= { airFMIdent 3 }
+
+airFMIdentTableEntry OBJECT-TYPE
+ SYNTAX AirFMIdentTableEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The module to get information from."
+ INDEX { airFMIdentModuleIndex }
+ ::= { airFMIdentTable 1 }
+
+AirFMIdentTableEntry ::=
+ SEQUENCE {
+ airFMIdentModuleIndex INTEGER,
+ airFMIdentModuleModelNumber DisplayString,
+ airFMIdentModuleDateOfMfg DisplayString,
+ airFMIdentModuleSerialNumber DisplayString,
+ airFMIdentModuleFirmwareRev DisplayString,
+ airFMIdentModuleHardwareRev DisplayString
+ }
+
+airFMIdentModuleIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the module information."
+ ::= { airFMIdentTableEntry 1 }
+
+airFMIdentModuleModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ model number. "
+ ::= { airFMIdentTableEntry 2 }
+
+airFMIdentModuleDateOfMfg OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ manufacture date. "
+ ::= { airFMIdentTableEntry 3 }
+
+airFMIdentModuleSerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ unit serial number. "
+ ::= { airFMIdentTableEntry 4 }
+
+airFMIdentModuleFirmwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ firmware revision. "
+ ::= { airFMIdentTableEntry 5 }
+
+airFMIdentModuleHardwareRev OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ hardware revision. "
+ ::= { airFMIdentTableEntry 6 }
+
+-- airFM AIR CONDITIONER STATUS
+
+airFMStatusSystemOn OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusOn (1),
+ statusOff (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The operating state of the system. "
+ ::= { airFMStatus 1 }
+
+airFMStatusSystemAverageRetTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system average return air
+ temperature in tenths of degrees Celsius. "
+ ::= { airFMStatus 2 }
+
+airFMStatusSystemAverageRetTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system average return air
+ temperature in tenths of degrees Fahrenheit. "
+ ::= { airFMStatus 3 }
+
+airFMStatusSystemAverageRetHum OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system average return air
+ humidity. "
+ ::= { airFMStatus 4 }
+
+airFMStatusSystemActionTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system action air
+ temperature in tenths of degrees Celsius. "
+ ::= { airFMStatus 5 }
+
+airFMStatusSystemActionTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system action air
+ temperature in tenths of degrees Fahrenheit. "
+ ::= { airFMStatus 6 }
+
+airFMStatusSystemActionHum OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system action air humidity. "
+ ::= { airFMStatus 7 }
+
+airFMStatusSystemRemoteHighTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system remote high air
+ temperature in tenths of degrees Celsius. "
+ ::= { airFMStatus 8 }
+
+airFMStatusSystemRemoteHighTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system remote high air
+ temperature in tenths of degrees Fahrenheit. "
+ ::= { airFMStatus 9 }
+
+airFMStatusSystemRemoteAvgTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system remote average air
+ temperature in tenths of degrees Celsius. "
+ ::= { airFMStatus 10 }
+
+airFMStatusSystemRemoteAvgTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system remote average air
+ temperature in tenths of degrees Fahrenheit. "
+ ::= { airFMStatus 11 }
+
+airFMStatusSystemRemoteAvgHum OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system remote average air
+ humidity. "
+ ::= { airFMStatus 12 }
+
+airFMStatusSystemRemoteLowTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system remote low air
+ temperature in tenths of degrees Celsius. "
+ ::= { airFMStatus 13 }
+
+airFMStatusSystemRemoteLowTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The system remote low air
+ temperature in tenths of degrees Fahrenheit. "
+ ::= { airFMStatus 14 }
+
+airFMStatusSystemCoolingEnabled OBJECT-TYPE
+ SYNTAX INTEGER {
+ enabledYes (1),
+ enabledNo (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The state of the system cooling
+ function enable. "
+ ::= { airFMStatus 15 }
+
+airFMStatusSystemReheatingEnabled OBJECT-TYPE
+ SYNTAX INTEGER {
+ enabledYes (1),
+ enabledNo (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The state of the system reheating
+ function enable. "
+ ::= { airFMStatus 16 }
+
+airFMStatusSystemHumidifyEnabled OBJECT-TYPE
+ SYNTAX INTEGER {
+ enabledYes (1),
+ enabledNo (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The state of the system humidify
+ function enable. "
+ ::= { airFMStatus 17 }
+
+airFMStatusSystemDehumidifyEnabled OBJECT-TYPE
+ SYNTAX INTEGER {
+ enabledYes (1),
+ enabledNo (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The state of the system dehumidify
+ function enable. "
+ ::= { airFMStatus 18 }
+
+airFMStatusModuleTableSize OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of entries in the airFMStatusModuleTable. "
+ ::= { airFMStatus 19 }
+
+airFMStatusModuleTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AirFMStatusModuleEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for getting information from each module
+ in the system. "
+ ::= { airFMStatus 20 }
+
+airFMStatusModuleEntry OBJECT-TYPE
+ SYNTAX AirFMStatusModuleEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The module to get status from."
+ INDEX { airFMStatusModuleIndex }
+ ::= { airFMStatusModuleTable 1 }
+
+AirFMStatusModuleEntry ::=
+ SEQUENCE {
+ airFMStatusModuleIndex INTEGER,
+ airFMStatusModuleOutputCapacity INTEGER,
+ airFMStatusModuleSupplyTempC INTEGER,
+ airFMStatusModuleSupplyTempF INTEGER,
+ airFMStatusModuleSupplyHum INTEGER,
+ airFMStatusModuleReturnTempC INTEGER,
+ airFMStatusModuleReturnTempF INTEGER,
+ airFMStatusModuleReturnHum INTEGER
+ }
+
+airFMStatusModuleIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index of the module information."
+ ::= { airFMStatusModuleEntry 1 }
+
+airFMStatusModuleOutputCapacity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The module output capacity in kilowatts."
+ ::= { airFMStatusModuleEntry 2 }
+
+airFMStatusModuleSupplyTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The module supply air temperature in
+ tenths of degrees Celsius. "
+ ::= { airFMStatusModuleEntry 3 }
+
+airFMStatusModuleSupplyTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The module supply air temperature in
+ tenths of degrees Fahrenheit. "
+ ::= { airFMStatusModuleEntry 4 }
+
+airFMStatusModuleSupplyHum OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The module supply air humidity. "
+ ::= { airFMStatusModuleEntry 5 }
+
+airFMStatusModuleReturnTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The module return air temperature in
+ tenths of degrees Celsius. "
+ ::= { airFMStatusModuleEntry 6 }
+
+airFMStatusModuleReturnTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The module return air temperature in
+ tenths of degrees Fahrenheit. "
+ ::= { airFMStatusModuleEntry 7 }
+
+airFMStatusModuleReturnHum OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The module return air humidity. "
+ ::= { airFMStatusModuleEntry 8 }
+
+-- airFM AIR CONDITIONER GROUP DATA
+
+airFMGroupSysStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusOnLine (1),
+ statusIdle (2),
+ statusLoadShare (3),
+ statusOffLine (4),
+ statusFailed (5)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of this system within the group. "
+ ::= { airFMGroup 1 }
+
+airFMGroupSysRuntime OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The number of hours the system has been running. "
+ ::= { airFMGroup 2 }
+
+airFMGroupSysRole OBJECT-TYPE
+ SYNTAX INTEGER {
+ rolePrimary (1),
+ roleBackup (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The role of this system within the group. "
+ ::= { airFMGroup 3 }
+
+-- airPA Portable Air Conditioner Ident
+
+airPAIdentName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the device name. "
+ ::= { airPAIdent 1 }
+
+airPAModelNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the device model number. "
+ ::= { airPAIdent 2 }
+
+airPADateOfManufacture OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying when the device was produced. "
+ ::= { airPAIdent 3 }
+
+airPASerialNumber OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the device serial number. "
+ ::= { airPAIdent 4 }
+
+airPAFirmwareRevision OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the device firmware revision. "
+ ::= { airPAIdent 5 }
+
+airPAHardwareRevision OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the device hardware revision. "
+ ::= { airPAIdent 6 }
+
+-- airPA Portable Air Conditioner Status
+
+airPASystemPower OBJECT-TYPE
+ SYNTAX INTEGER {
+ powerON (1),
+ powerOFF (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The status of the unit's system power setting.
+
+ ON(1) The system power is turned on.
+ OFF(2) The system power is turned off. "
+ ::= { airPAStatus 1 }
+
+airPAOperatingMode OBJECT-TYPE
+ SYNTAX INTEGER {
+ modeOFF (1),
+ modeVENTING (2),
+ modeCOOLING (3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The current operating mode of the unit.
+
+ OFF(1) The system is off.
+ VENTING(2) The system's venting function is active.
+ COOLING(3) The system's cooling function is active. "
+ ::= { airPAStatus 2 }
+
+airPASetpointTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature setpoint in Fahrenheit to which the unit is controlling. "
+ ::= { airPAStatus 3 }
+
+airPASetpointTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature setpoint in Celsius to which the unity is controlling. "
+ ::= { airPAStatus 4 }
+
+airPABlowerSpeed OBJECT-TYPE
+ SYNTAX INTEGER {
+ speedLOW (1),
+ speedHIGH (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The unit's blower speed setting.
+
+ LOW(1) The blower speed is low.
+ HIGH(2) The blower speed is high. "
+ ::= { airPAStatus 5 }
+
+airPACompressor OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusON (1),
+ statusOFF (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The unit's compressor status.
+
+ ON(1) The compressor is turned on.
+ OFF(2) The compressor is turned off. "
+ ::= { airPAStatus 6 }
+
+airPACondenserFan OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusON (1),
+ statusOFF (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The unit's condenser fan status.
+
+ ON(1) The condenser fan is turned on.
+ OFF(2) The condenser fan is turned off. "
+ ::= { airPAStatus 7 }
+
+airPACondensatePump OBJECT-TYPE
+ SYNTAX INTEGER {
+ statusON (1),
+ statusOFF (2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The unit's condensate pump status.
+
+ ON(1) The condensate pump is turned on.
+ OFF(2) The condensate pump is turned off. "
+ ::= { airPAStatus 8 }
+
+airPASupplyTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The supply temperature in degrees Fahrenheit. "
+ ::= { airPAStatus 9 }
+
+airPASupplyTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The supply temperature in degrees Celsius. "
+ ::= { airPAStatus 10 }
+
+airPAReturnTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The return temperature in degrees Fahrenheit. "
+ ::= { airPAStatus 11 }
+
+airPAReturnTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The return temperature in degrees Celsius. "
+ ::= { airPAStatus 12 }
+
+airPARemoteTempF OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The remote temperature in degrees Fahrenheit. "
+ ::= { airPAStatus 13 }
+
+airPARemoteTempC OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The remote temperature in degrees Celsius. "
+ ::= { airPAStatus 14 }
+
+airPARemoteHumidity OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The remote humidity. "
+ ::= { airPAStatus 15 }
+
+-- RACK AIR REMOVAL UNIT IDENT
+
+rARUIdentTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF IdentRARUEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for query of the individual devices.
+ The number of entries is contained in the
+ rARUStatusAruDeviceCount OID."
+ ::= { rARUIdent 1 }
+
+rARUIdentEntry OBJECT-TYPE
+ SYNTAX IdentRARUEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The device to query."
+ INDEX { rARUIdentIndex}
+ ::= { rARUIdentTable 1 }
+
+IdentRARUEntry ::=
+ SEQUENCE {
+ rARUIdentIndex INTEGER,
+ rARUIdentName DisplayString
+ }
+
+rARUIdentIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the device entry."
+ ::= { rARUIdentEntry 1 }
+
+rARUIdentName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "A character string identifying the
+ device. "
+ ::= { rARUIdentEntry 2 }
+
+
+-- RACK AIR REMOVAL UNIT CONFIGURATION
+
+rARUConfigTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF ConfigRARUEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for configuration of individual ARUs. The number of
+ entries is contained in the rARUStatusAruDeviceCount OID."
+ ::= { rARUConfig 1 }
+
+rARUConfigEntry OBJECT-TYPE
+ SYNTAX ConfigRARUEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The ARUs to configure."
+ INDEX { rARUConfigAruIndex }
+ ::= { rARUConfigTable 1 }
+
+ConfigRARUEntry ::=
+ SEQUENCE {
+ rARUConfigAruIndex INTEGER,
+ rARUConfigAruName DisplayString,
+ rARUConfigAruRemoteSetpoint INTEGER,
+ rARUConfigAruTempOvrdEnableDisable INTEGER,
+ rARUConfigAruTempOvrdSetpoint INTEGER
+ }
+
+rARUConfigAruIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the device entry."
+ ::= { rARUConfigEntry 1 }
+
+rARUConfigAruName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the ARU."
+ ::= { rARUConfigEntry 2 }
+
+rARUConfigAruRemoteSetpoint OBJECT-TYPE
+ SYNTAX INTEGER {
+ aruOff (1),
+ aru85F-29C (2),
+ aru90F-32C (3),
+ aru95F-35C (4),
+ aru100F-38C (5),
+ aru7kW (6),
+ aru5kW (7),
+ aru3kW (8),
+ aru2kW (9)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID is the Remote setpoint of the ARU.
+ NOTE: -1 will be returned if the ARU is not communicating."
+
+ ::= { rARUConfigEntry 3 }
+
+rARUConfigAruTempOvrdEnableDisable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID is used to enable/disable the remote temperature override setting of the ARU.
+
+ If this OID is set to 1, the remote setting for temperature override is disabled.
+ If this OID is set to 2, the remote setting for temperature override is enabled."
+ ::= { rARUConfigEntry 4 }
+
+rARUConfigAruTempOvrdSetpoint OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-write
+ STATUS mandatory
+ DESCRIPTION
+ "This OID is the Temperature Override setpoint of the ARU.
+ NOTE: -1 will be returned if the ARU is not communicating."
+
+ ::= { rARUConfigEntry 5 }
+
+-- RACK AIR REMOVAL UNIT STATUS
+
+rARUStatusAruDeviceCount OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The total number of ARUs accessible from this IP."
+ ::= { rARUStatus 1 }
+
+rARUStatusSysTempUnits OBJECT-TYPE
+ SYNTAX INTEGER {
+ celsius(1),
+ fahrenheit(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The temperature scale used to display the temperature
+ in the system, Celsius(1) or Fahrenheit(2).
+ This setting is based on the system preferences
+ configuration in the agent."
+ ::= { rARUStatus 2 }
+
+rARUStatusTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF StatusRARUEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "Allows for access of individual ARUs. The number of
+ entries is contained in the rARUStatusAruDeviceCount OID."
+ ::= { rARUStatus 3 }
+
+rARUStatusEntry OBJECT-TYPE
+ SYNTAX StatusRARUEntry
+ ACCESS not-accessible
+ STATUS mandatory
+ DESCRIPTION
+ "The ARUs to access."
+ INDEX { rARUStatusAruIndex }
+ ::= { rARUStatusTable 1 }
+
+StatusRARUEntry ::=
+ SEQUENCE {
+ rARUStatusAruIndex INTEGER,
+ rARUStatusAruName DisplayString,
+ rARUStatusAruRemoteSetpoint INTEGER,
+ rARUStatusAruManualSetpoint INTEGER,
+ rARUStatusAruTemp1 INTEGER,
+ rARUStatusAruTemp2 INTEGER,
+ rARUStatusAruTemp3 INTEGER,
+ rARUStatusAruTempOvrdEnableDisable INTEGER,
+ rARUStatusAruTempOvrdSetpoint INTEGER,
+ rARUStatusAruAlarmState DisplayString,
+ rARUStatusAruCommStatus INTEGER
+ }
+
+rARUStatusAruIndex OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The index to the ARU entry."
+ ::= { rARUStatusEntry 1 }
+
+rARUStatusAruName OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The name of the ARU."
+ ::= { rARUStatusEntry 2 }
+
+rARUStatusAruRemoteSetpoint OBJECT-TYPE
+ SYNTAX INTEGER {
+ aruOff (1),
+ aru85F-29C (2),
+ aru90F-32C (3),
+ aru95F-35C (4),
+ aru100F-38C (5),
+ aru7kW (6),
+ aru5kW (7),
+ aru3kW (8),
+ aru2kW (9)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "ARU remote setpoint temperature setting.
+
+ NOTE: -1 will be returned if the ARU is not communicating.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the rARUStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { rARUStatusEntry 3 }
+
+rARUStatusAruManualSetpoint OBJECT-TYPE
+ SYNTAX INTEGER {
+ aruOff (1),
+ aru85F-29C (2),
+ aru90F-32C (3),
+ aru95F-35C (4),
+ aru100F-38C (5),
+ aru7kW (6),
+ aru5kW (7),
+ aru3kW (8),
+ aru2kW (9),
+ aruRem (10)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "ARU manual setpoint temperature setting.
+
+ NOTE: -1 will be returned if the ARU is not communicating.
+
+ Values are represented in whole number degrees.
+ If the manual setpoint is set to Remote, this OID will return 0.
+ Units are displayed in the scale shown in
+ the rARUStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { rARUStatusEntry 4 }
+
+rARUStatusAruTemp1 OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "ARU temperature probe #1 reading.
+
+ NOTE: -1 will be returned if the ARU is not communicating.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the rARUStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { rARUStatusEntry 5 }
+
+rARUStatusAruTemp2 OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "ARU temperature probe #2 reading.
+
+ NOTE: -1 will be returned if the ARU is not communicating.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the rARUStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { rARUStatusEntry 6 }
+
+rARUStatusAruTemp3 OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "ARU temperature probe #3 reading.
+
+ NOTE: -1 will be returned if the ARU is not communicating.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the rARUStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { rARUStatusEntry 7 }
+
+rARUStatusAruTempOvrdEnableDisable OBJECT-TYPE
+ SYNTAX INTEGER {
+ disabled(1),
+ enabled(2)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "This OID indicates whether the ARU remote temperature override is enabled or disabled.
+ If this OID is a 1, the remote setting for temperature override is disabled.
+ If this OID is a 2, the remote setting for temperature override is enabled."
+ ::= { rARUStatusEntry 8 }
+
+rARUStatusAruTempOvrdSetpoint OBJECT-TYPE
+ SYNTAX INTEGER
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "ARU remote temperature override setpoint setting.
+
+ NOTE: -1 will be returned if the ARU is not communicating.
+
+ Values are represented in whole number degrees.
+ Units are displayed in the scale shown in
+ the rARUStatusSysTempUnits OID (Celsius or Fahrenheit)."
+ ::= { rARUStatusEntry 9 }
+
+rARUStatusAruAlarmState OBJECT-TYPE
+ SYNTAX DisplayString
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "An ASCII string containing the 8 flags representing
+ the current alarm state of the ARU. If the state of
+ the ARU is unknown, this variable is set to ‘UNKNOWN’.
+
+ The flags are numbered 1 to 8, read from left to
+ right. The flags are defined as follows:
+
+ Flag 1: Fan Fail 1
+ Flag 2: Fan Fail 2
+ Flag 3: Fan Fail 3
+ Flag 4: Smoke
+
+ Flag 5: High Temp (Out of Thermal Control)
+ Flag 6: Over Temp (Exhaust Temp. Exceeds Override Setpoint)
+ Flag 7: Reserved
+ Flag 8: Reserved"
+ ::= { rARUStatusEntry 10 }
+
+rARUStatusAruCommStatus OBJECT-TYPE
+ SYNTAX INTEGER {
+ commsNeverDiscovered(1),
+ commsEstablished(2),
+ commsLost(3)
+ }
+ ACCESS read-only
+ STATUS mandatory
+ DESCRIPTION
+ "The state of communications to the device.
+ commNeverDiscovered(1) indicates there has never been communications with this device.
+ commsEstablished(2) indicates communication is normal and active with this device.
+ commsLost(3) indicates communication had been established, but is no device."
+ ::= { rARUStatusEntry 11 }
+
+-- Traps
+-- Annotations are provided for Novell's NMS product
+--
+-- Each trap has at least one variable (mtrapargsString) which always appears
+-- as the last variable in the list. This variable contains either a static
+-- or dynamically-constructed string which provides an enhanced description of
+-- the trap's purpose and any pertinent information about the trap.
+
+communicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communication to the UPS has been lost. Steps
+ to reestablish communication are in progress."
+ --#TYPE "APC UPS: Communication lost"
+ --#SUMMARY "Communication lost between the agent and the UPS."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 1
+
+upsOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The UPS has sensed a load greater than 100 percent
+ of its rated capacity."
+ --#TYPE "APC UPS: Overload"
+ --#SUMMARY "The UPS has sensed a load greater than 100 percent of its rated capacity."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 2
+
+upsDiagnosticsFailed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The UPS failed its internal diagnostic self-test."
+ --#TYPE "APC UPS: Failed self-test"
+ --#SUMMARY "The UPS has failed its internal self-test."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 3
+
+upsDischarged TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The UPS batteries are discharged; if utility power fails
+ an immediate low battery condition will exist. Sufficient runtime
+ for necessary action cannot be guaranteed."
+ --#TYPE "APC UPS: batteries are discharged"
+ --#SUMMARY "The UPS batteries are discharged."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 4
+
+upsOnBattery TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The UPS has switched to battery backup power."
+ --#TYPE "APC UPS: On battery"
+ --#SUMMARY "The UPS has switched to battery backup power."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 5
+
+smartBoostOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The UPS has enabled SmartBoost(TM)."
+ --#TYPE "APC UPS: SmartBoost(TM)"
+ --#SUMMARY "The UPS has enabled SmartBoost(TM); low incoming line voltage."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 6
+
+lowBattery TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The UPS batteries are low and will soon be exhausted.
+ If utility power is not restored the UPS will put itself
+ to 'sleep' and immediately cut power to the load."
+ --#TYPE "APC UPS: Low battery"
+ --#SUMMARY "The UPS system's batteries are low and will soon be exhausted."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 7
+
+communicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communication with the UPS has been established."
+ --#TYPE "APC UPS: Communication established"
+ --#SUMMARY "UPS communication has been established."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 8
+
+powerRestored TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Utility power has been restored."
+ --#TYPE "APC UPS: Utility power restored"
+ --#SUMMARY "Returned from battery backup power; utility power restored."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 9
+
+upsDiagnosticsPassed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The UPS passed its internal self-test."
+ --#TYPE "APC UPS: Passed self-test"
+ --#SUMMARY "The UPS passed internal self-test."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 10
+
+returnFromLowBattery TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The UPS has returned from a low battery
+ condition."
+ --#TYPE "APC UPS: Returned from Low-Battery condition"
+ --#SUMMARY "The UPS has returned from a Low-Battery condition."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 11
+
+upsTurnedOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The UPS has been turned 'off' by the management station."
+ --#TYPE "APC UPS: Turned off"
+ --#SUMMARY "The UPS has been switched off by a management station."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE NONOPERATIONAL
+ ::= 12
+
+upsSleeping TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The UPS is entering 'sleep' mode. Power
+ to the load will be cut off."
+ --#TYPE "APC UPS: Entered sleep mode"
+ --#SUMMARY "The UPS entered sleep mode. Power to the load will be cut off."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE NONOPERATIONAL
+ ::= 13
+
+upsWokeUp TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATION: The UPS has returned from 'sleep' mode. Power
+ to the load has been restored."
+ --#TYPE "APC UPS: Wake up"
+ --#SUMMARY "The UPS has returned from sleep mode. Power to the load has been restored."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 14
+
+upsRebootStarted TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The UPS has started its reboot sequence.
+ The UPS will reboot itself at this time."
+ --#TYPE "APC UPS: Starting reboot"
+ --#SUMMARY "The UPS has started its reboot sequence."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE NONOPERATIONAL
+ ::= 15
+
+upsDipSwitchChanged TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The dip switch settings on the UPS have been
+ changed, possibly altering UPS performance."
+ --#TYPE "APC UPS: DIP switch altered"
+ --#SUMMARY "The DIP switch settings on the UPS have been changed."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 16
+
+upsBatteryNeedsReplacement TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The batteries of the UPS need immediate replacement."
+ --#TYPE "APC UPS: UPS batteries need replacement"
+ --#SUMMARY "The UPS batteries require immediate replacement."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 17
+
+
+-- the Environmental Monitor traps
+
+contactFault TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: One of the contacts on the Environmental Monitor has
+ changed from its default position. The first variable is
+ the contact number that is faulted."
+ --#TYPE "APC Environment: Contact fault"
+ --#SUMMARY "An Environment contact closure has faulted."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 18
+
+contactFaultResolved TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A fault on one of the Environmental Monitor contacts
+ has been resolved. The first variable is
+ the contact number that has been resolved."
+ --#TYPE "APC Environment: Contact fault cleared."
+ --#SUMMARY "A Environment contact closure has returned to it's default state."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 19
+
+-- the Matrix-UPS traps
+
+hardwareFailureBypass TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: UPS on bypass due to internal fault"
+ --#TYPE "APC UPS: On bypass due to internal fault"
+ --#SUMMARY "The UPS is on bypass due to an internal fault."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 20
+
+softwareBypass TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: UPS on bypass - user set via software or panel"
+ --#TYPE "APC UPS: On bypass by user via software or panel"
+ --#SUMMARY "UPS put on bypass by user via software or front UPS panel."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 21
+
+switchedBypass TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: UPS on bypass - initiated by user"
+ --#TYPE "APC UPS: On bypass initiated by user"
+ --#SUMMARY "UPS put on bypass by user."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 22
+
+returnFromBypass TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: UPS has returned from bypass"
+ --#TYPE "APC UPS: UPS has returned from bypass"
+ --#SUMMARY "The UPS has returned from bypass mode."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 23
+
+bypassPowerSupplyFailure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Base module bypass power supply needs repair"
+ --#TYPE "APC UPS: Base module bypass power supply needs repair"
+ --#SUMMARY "The base module bypass power supply needs repair."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE NONOPERATIONAL
+ ::= 24
+
+baseFanFailure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Base module fan needs repair"
+ --#TYPE "APC UPS: Base module fan needs repair"
+ --#SUMMARY "The base module fan needs repair."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE NONOPERATIONAL
+ ::= 25
+
+batteryPackCommLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Check installation of external battery packs signal cable"
+ --#TYPE "APC UPS: Communication lost with battery packs"
+ --#SUMMARY "Communication lost with external battery packs, check battery signal cable."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 26
+
+batteryPackCommEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: UPS is communicating with the external battery packs."
+ --#TYPE "APC UPS: Communication established with battery packs"
+ --#SUMMARY "Communication established with external battery packs."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 27
+
+calibrationStart TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A battery calibration test has been initiated on the UPS."
+ --#TYPE "APC UPS: Calibration initiated"
+ --#SUMMARY "A battery run time calibration test has been initiated."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 28
+
+-- Misc. Traps
+
+restartAgent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Agent restarting as commanded by manager."
+ --#TYPE "APC SNMP Agent: Agent restarting"
+ --#SUMMARY "Agent restarting as commanded by manager."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 29
+
+upsTurnedOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A UPS is turned on."
+ --#TYPE "APC UPS: A UPS is turned on."
+ --#SUMMARY " A UPS is turned on."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 30
+
+smartAvrReducing TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The UPS is reducing the line voltage via SmartTrim(TM)."
+ --#TYPE "APC UPS: SmartTrim(TM) reducing"
+ --#SUMMARY "The UPS has enabled SmartTrim(TM) voltage reduction."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 31
+
+codeAuthenticationDone TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mconfigTFTPServerIP, newCodeAuthentViaTFTP }
+ DESCRIPTION
+ "INFORMATIONAL: Authentication on agent code image is done."
+ --#TYPE "APC CODE: Authentication on agent code image is done."
+ --#SUMMARY "Authentication on agent code image is done."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 32
+
+upsOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The overload condition has been cleared."
+ --#TYPE "APC UPS: Overload cleared."
+ --#SUMMARY "The overload condition has been cleared. ."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 33
+
+smartBoostOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The UPS has returned from SmartBoost(TM)."
+ --#TYPE "APC UPS: SmartBoost(TM) off."
+ --#SUMMARY "The UPS has returned from SmartBoost(TM)."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 34
+
+smartAvrReducingOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The UPS has returned from SmartTrim(TM)."
+ --#TYPE "APC UPS: SmartTrim(TM) reducing off"
+ --#SUMMARY "The UPS has returned from SmartTrim(TM) voltage reduction."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 35
+
+upsBatteryReplaced TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A bad battery fault has been cleared."
+ --#TYPE "APC UPS: Bad battery replaced"
+ --#SUMMARY "The UPS has returned from a bad battery fault."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 36
+
+calibrationEnd TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The UPS has finished calibrating."
+ --#TYPE "APC UPS: Calibration end"
+ --#SUMMARY "The UPS has finished calibrating"
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 37
+
+dischargeCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A UPS discharge condition has been cleared."
+ --#TYPE "APC UPS: Discharge cleared."
+ --#SUMMARY "The UPS discharge condition has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 38
+
+gracefullShutdown TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A graceful shutdown has been initiated."
+ --#TYPE "APC UPS: A graceful shutdown has been initiated."
+ --#SUMMARY "A graceful shutdown has been initiated."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 39
+
+
+outletOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUOutletControlIndex }
+ DESCRIPTION
+ "WARNING: The specified PDU outlet has turned on.
+ If sPDUOutletControlIndex equals zero, then all outlets have
+ turned on."
+ --#TYPE "APC PDU: Outlet has been turned on."
+ --#SUMMARY "Outlet has been turned on"
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 41
+
+
+outletOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUOutletControlIndex }
+ DESCRIPTION
+ "WARNING: The specified PDU outlet has turned off.
+ If sPDUOutletControlIndex equals zero, then all outlets
+ have turned off."
+ --#TYPE "APC PDU: Outlet has turned off."
+ --#SUMMARY "Outlet has turned off."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 42
+
+outletReboot TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUOutletControlIndex }
+ DESCRIPTION
+ "WARNING: The specified PDU outlet has rebooted.
+ If sPDUOutletControlIndex equals zero, then all outlets
+ have rebooted."
+ --#TYPE "APC PDU: Outlet has rebooted."
+ --#SUMMARY "Outlet has rebooted."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 43
+
+configChangeSNMP TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The SNMP configuration has been changed."
+ --#TYPE "APC: The SNMP configuration has been changed."
+ --#SUMMARY "The SNMP configuration has been changed."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 44
+
+
+configChangeOutlet TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUOutletConfigIndex }
+ DESCRIPTION
+ "WARNING: The specified PDU outlet has changed configuration.
+ If sPDUOutletConfigIndex equals zero, then the Master outlet
+ has changed configuration."
+ --#TYPE "APC PDU: Outlet configuration has been changed."
+ --#SUMMARY "Outlet configuration has been changed."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 45
+
+accessViolationConsole TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: Someone has attempted to login via the console with the incorrect password."
+ --#TYPE "APC: Access violation via the console."
+ --#SUMMARY "Three unsuccessful logins have been attempted via the console."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 46
+
+accessViolationHTTP TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: Someone has attempted to login via HTTP with the incorrect password."
+ --#TYPE "APC: Access violation via HTTP."
+ --#SUMMARY "An unsuccessful attempt to login via HTTP."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 47
+
+passwordChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The password for the device has been changed."
+ --#TYPE "APC: Password change for the device."
+ --#SUMMARY "Someone has changed the password on the device."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 48
+
+badVoltage TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The output voltage is not within acceptable range."
+ --#TYPE "APC UPS: Bad output voltage."
+ --#SUMMARY "The output voltage is not within acceptable range."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 49
+
+badVoltageCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The output voltage has returned to an acceptable level."
+ --#TYPE "APC UPS: The bad voltage output condition has been cleared."
+ --#SUMMARY "The output voltage has returned to an acceptable level."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 50
+
+chargerFailure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The battery charger has failed."
+ --#TYPE "APC UPS: The battery charger has failed."
+ --#SUMMARY "The battery charger has failed."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 51
+
+chargerFailureCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The battery charger failure condition has been cleared."
+ --#TYPE "APC UPS: The battery charger failure condition cleared"
+ --#SUMMARY "The battery charger failure condition has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 52
+
+batteryOverTemperature TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The battery temperature threshold has been violated."
+ --#TYPE "APC UPS: The battery temperature threshold has been violated."
+ --#SUMMARY "The battery temperature threshold has been violated."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 53
+
+batteryOverTemperatureCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The battery over temperature has been cleared."
+ --#TYPE "APC UPS: The battery over temperature has been cleared."
+ --#SUMMARY "The battery over temperature has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 54
+
+ smartRelayFault TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: SmartBoost(TM) or SmartTrim(TM) relay fault."
+ --#TYPE "APC UPS: SmartBoost(TM) or SmartTrim(TM) relay fault."
+ --#SUMMARY "SmartBoost(TM) or SmartTrim(TM) relay fault."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 55
+
+smartRelayFaultCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: SmartBoost(TM) or SmartTrim(TM) relay fault has been cleared."
+ --#TYPE "APC UPS: SmartBoost(TM) or SmartTrim(TM) relay fault cleared."
+ --#SUMMARY "SmartBoost(TM) or SmartTrim(TM) relay fault has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 56
+
+humidityThresholdViolation1 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Probe 1 humidity threshold violated. The
+ first variable is the current humidity."
+ --#TYPE "APC Environmental Monitor: Probe 1 humidity threshold violation"
+ --#SUMMARY "A humidity threshold has been violated on probe 1."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 57
+
+humidityThresholdViolationCleared1 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Environmental Monitor humidity threshold violation has been cleared on probe 1."
+ --#TYPE "APC Environmental Monitor: Probe 1 humidity violation cleared"
+ --#SUMMARY "A humidity threshold violation has been cleared on probe 1."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 58
+
+temperatureThresholdViolation1 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: An Environmental Monitor temperature threshold has been violated on probe 1.
+ The first variable is the current temperature."
+ --#TYPE "APC Environmental Monitor: Probe 1 temperature violation"
+ --#SUMMARY "A temperature threshold has been violated on probe 1."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 59
+
+temperatureThresholdViolationCleared1 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Environmental Monitor temperature threshold violation has been cleared on probe 1."
+ --#TYPE "APC Environmental Monitor: Probe 1 temperature violation cleared"
+ --#SUMMARY "A temperature threshold violation has been cleared on probe 1."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 60
+
+humidityThresholdViolation2 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: An Environmental Monitor humidity threshold has been violated on probe 2.
+ The first variable is the current humidity."
+ --#TYPE "APC Environmental Monitor: Probe 2 humidity violation"
+ --#SUMMARY "A humidity threshold has been violated on probe 2."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 61
+
+humidityThresholdViolationCleared2 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Environmental Monitor humidity threshold violation has been cleared on probe 2."
+ --#TYPE "APC Environmental Monitor: Probe 2 humidity violation cleared"
+ --#SUMMARY "A humidity threshold violation has been cleared on probe 2."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 62
+
+temperatureThresholdViolation2 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: An Environmental Monitor temperature threshold has been violated on probe 2.
+ The first variable is the current temperature."
+ --#TYPE "APC Environmental Monitor: Probe 2 temperature violation"
+ --#SUMMARY "A temperature threshold has been violated on probe 2."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 63
+
+temperatureThresholdViolationCleared2 TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Environmental Monitor temperature threshold violation has been cleared on probe 2."
+ --#TYPE "APC Environmental Monitor: Probe 2 temperature violation cleared"
+ --#SUMMARY "A temperature threshold violation has been cleared on probe 2."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 64
+
+mupsCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communication with the Environmental Monitor has been established."
+ --#TYPE "APC Environmental Monitor: Communication established"
+ --#SUMMARY "Communication established between the agent and the Environmental Monitor."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 65
+
+mupsCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communication to the Environmental Monitor has been lost. Steps
+ to reestablish communication are in progress."
+ --#TYPE "APC Environmental Monitor: Communication failure"
+ --#SUMMARY "Communication lost between the agent and the Environmental Monitor."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 66
+
+batteryIncrease TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The number of batteries has increased."
+ --#TYPE "APC UPS: The number of batteries has increased."
+ --#SUMMARY "The number of batteries has increased."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 67
+
+batteryDecrease TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The number of batteries has decreased."
+ --#TYPE "APC UPS: The number of batteries has decreased."
+ --#SUMMARY "The number of batteries has decreased."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 68
+
+powerModuleIncrease TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The number of power modules has increased."
+ --#TYPE "APC UPS: The number of power modules has increased."
+ --#SUMMARY "The number of power modules has increased."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 69
+
+powerModuleDecrease TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The number of power modules has decreased."
+ --#TYPE "APC UPS: The number of power modules has decreased."
+ --#SUMMARY "The number of power modules has decreased."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 70
+
+intelligenceModuleInserted TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An intelligence module has been inserted."
+ --#TYPE "APC UPS: An intelligence module has been inserted."
+ --#SUMMARY "An intelligence module has been inserted."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 71
+
+intelligenceModuleRemoved TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An intelligence module has been removed."
+ --#TYPE "APC UPS: An intelligence module has been removed."
+ --#SUMMARY "An intelligence module has been removed."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 72
+
+rintelligenceModuleInserted TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A redundant intelligence module has been inserted."
+ --#TYPE "APC UPS: A redundant intelligence module has been inserted."
+ --#SUMMARY "A redundant intelligence module has been inserted."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 73
+
+rintelligenceModuleRemoved TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A redundant intelligence module has been removed."
+ --#TYPE "APC UPS: A redundant intelligence module has been removed."
+ --#SUMMARY "A redundant intelligence module has been removed."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 74
+
+extBatteryFrameIncease TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An external battery frame has been added."
+ --#TYPE "APC UPS: An external battery frame has been added."
+ --#SUMMARY "An external battery frame has been added."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 75
+
+extBatteryFrameDecrease TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An external battery frame has been removed."
+ --#TYPE "APC UPS: An external battery frame has been removed."
+ --#SUMMARY "An external battery frame has been removed."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 76
+
+abnormalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: An abnormal condition has been detected.
+ The first variable is the fault condition."
+ --#TYPE "APC: An abnormal condition has been detected."
+ --#SUMMARY "An abnormal condition has been detected."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 77
+
+abnormalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An abnormal condition has been cleared.
+ The first variable is the fault condition."
+ --#TYPE "APC: An abnormal condition has been cleared."
+ --#SUMMARY "An abnormal condition has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 78
+
+deviceStatusChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString}
+ DESCRIPTION
+ "INFORMATIONAL: The status of the device being monitored has changed."
+ --#TYPE "APC : The status of the device being monitored has changed."
+ --#SUMMARY "The status of the device being monitored has changed."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 79
+
+noBatteries TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The UPS has no batteries attached."
+ --#TYPE "APC UPS: No batteries attached."
+ --#SUMMARY "The UPS has no batteries attached."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 80
+
+noBatteriesCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The UPS's batteries have been attached."
+ --#TYPE "APC UPS: The no batteries attached condition has been cleared."
+ --#SUMMARY "The UPS's batteries have been attached."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 81
+
+userAdded TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A new user has been added."
+ --#TYPE "APC: A new user has been added."
+ --#SUMMARY "A new user has been added."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 82
+
+userDeleted TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A user has been deleted."
+ --#TYPE "APC: A user has been deleted."
+ --#SUMMARY "A user has been deleted."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 83
+
+userModified TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A user has been modified."
+ --#TYPE "APC: A user has been modified."
+ --#SUMMARY "A user has been modified."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 84
+
+-- MasterSwitch Vm Traps
+
+msvmCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communications with the MasterSwitch VM has been established."
+ --#TYPE "APC: Communications established with the MasterSwitch VM."
+ --#SUMMARY "Communications with the MasterSwitch VM has been established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 85
+
+msvmCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communications with the MasterSwitch VM has been lost."
+ --#TYPE "APC: Communications lost with the MasterSwitch VM."
+ --#SUMMARY "Communications with the MasterSwitch VM has been lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 86
+
+msvmOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The MasterSwitch VM in an overload condition."
+ --#TYPE "APC: The MasterSwitch VM is near or at an overload condition."
+ --#SUMMARY "The MasterSwitch VM is near or at an overload condition."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 87
+
+msvmOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The overload condition on the MasterSwitch VM has been cleared."
+ --#TYPE "APC: The overload condition cleared on the MasterSwitch VM."
+ --#SUMMARY "The overload condition on the MasterSwitch VM has been cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 88
+
+msvmOutletOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName,
+ sPDUOutletControlVMOutletIndex, sPDUOutletControlVMOutletName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet on the MasterSwitch VM has turned on."
+ --#TYPE "APC: An outlet on the MasterSwitch VM has turned on."
+ --#SUMMARY "An outlet on the MasterSwitch VM has turned on."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 89
+
+msvmOutletOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName,
+ sPDUOutletControlVMOutletIndex, sPDUOutletControlVMOutletName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet on the MasterSwitch VM has turned off."
+ --#TYPE "APC: An outlet on the MasterSwitch VM has turned off."
+ --#SUMMARY "An outlet on the MasterSwitch VM has turned off."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 90
+
+msvmDeviceConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A device configuration change has been made on a MasterSwitch VM."
+ --#TYPE "APC: A device configuration change on a MasterSwitch VM."
+ --#SUMMARY "A device configuration change has been made on a MasterSwitch VM."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 91
+
+msvmOutletConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName,
+ sPDUOutletControlVMOutletIndex, sPDUOutletControlVMOutletName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet configuration change has been made on a MasterSwitch VM."
+ --#TYPE "APC: An outlet configuration change on a MasterSwitch VM."
+ --#SUMMARY "An outlet configuration change has been made on a MasterSwitch VM."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 92
+
+msvmLowLoad TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The MasterSwitch VM has violated the low load threshold."
+ --#TYPE "APC: The MasterSwitch VM has violated the low load threshold."
+ --#SUMMARY "The MasterSwitch VM has violated the low load threshold."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 93
+
+msvmLowLoadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The low load condition on the MasterSwitch VM has been cleared."
+ --#TYPE "APC: The low load condition cleared on the MasterSwitch VM."
+ --#SUMMARY "The low load condition on the MasterSwitch VM has been cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 94
+
+msvmNearOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The MasterSwitch VM is approaching an overload condition."
+ --#TYPE "APC: The MasterSwitch VM is near or at an overload condition."
+ --#SUMMARY "The MasterSwitch VM is near or at an overload condition."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 95
+
+msvmNearOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The near overload condition on the MasterSwitch VM has been cleared."
+ --#TYPE "APC: The overload condition cleared on the MasterSwitch VM."
+ --#SUMMARY "The overload condition on the MasterSwitch VM has been cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 96
+
+msvmPowerSupplyStatusChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlVMIndex, sPDUMasterControlVMName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The power supply status of the MasterSwitch VM has changed."
+ --#TYPE "APC: The power supply status changed on MasterSwitch VM"
+ --#SUMMARY "The power supply status of the MasterSwitch VM has changed."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 97
+
+-- MasterSwitch plus (MSP) Traps
+
+mspCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlMSPIndex, sPDUMasterControlMSPName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communications with the MasterSwitch plus has been established."
+ --#TYPE "APC: Communications established with the MasterSwitch plus."
+ --#SUMMARY "Communications with the MasterSwitch plus has been established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 98
+
+mspCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlMSPIndex, sPDUMasterControlMSPName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communications with the MasterSwitch plus has been lost."
+ --#TYPE "APC: Communications lost with the MasterSwitch plus."
+ --#SUMMARY "Communications with the MasterSwitch plus has been lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 99
+
+mspOutletOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlMSPIndex, sPDUMasterControlMSPName,
+ sPDUOutletControlMSPOutletIndex, sPDUOutletControlMSPOutletName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet on the MasterSwitch plus has turned on."
+ --#TYPE "APC: An outlet on the MasterSwitch plus has turned on."
+ --#SUMMARY "An outlet on the MasterSwitch plus has turned on."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 100
+
+mspOutletOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlMSPIndex, sPDUMasterControlMSPName,
+ sPDUOutletControlMSPOutletIndex, sPDUOutletControlMSPOutletName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet on the MasterSwitch plus has turned off."
+ --#TYPE "APC: An outlet on the MasterSwitch plus has turned off."
+ --#SUMMARY "An outlet on the MasterSwitch plus has turned off."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 101
+
+mspDeviceConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlMSPIndex, sPDUMasterControlMSPName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A device configuration change has been made on a MasterSwitch plus."
+ --#TYPE "APC: A device configuration change on a MasterSwitch plus."
+ --#SUMMARY "A device configuration change has been made on a MasterSwitch plus."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 102
+
+mspOutletConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { sPDUMasterControlMSPIndex, sPDUMasterControlMSPName, sPDUOutletControlMSPOutletIndex, sPDUOutletControlMSPOutletName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet configuration change has been made on a MasterSwitch plus."
+ --#TYPE "APC: An outlet configuration change on a MasterSwitch plus."
+ --#SUMMARY "An outlet configuration change has been made on a MasterSwitch plus."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 103
+
+rsSourceSwitched TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger02, mtrapargsString03, mtrapargsInteger, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The Redundant Switch has switched source.
+ The first variable is an integer representing the current source: 0=A, 1=B.
+ The second variable is the 32-character name of the current source.
+ The third variable is an integer representing the transfer cause:
+ 0=No Transfers Recorded, 1=Due to user action or preferred switching,
+ 3=Due to line notch or spike, 5=Due to low line voltage,
+ 7=Transfer due to high line voltage,
+ 9=Transfer due to frequency out of range.
+ The fourth variable is a character string listing the transfer cause."
+ --#TYPE "APC Redundant Switch: The Redundant Switch has switched source"
+ --#SUMMARY "The Redundant Switch has switched source."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 104
+
+rsLostRedundancy TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The Redundant Switch has lost redundancy.
+ The first variable is an integer representing the source which is no longer available: 0=A, 1=B.
+ The second variable is the 32-character name of the source which is no longer available."
+ --#TYPE "APC Redundant Switch: The Redundant Switch has lost redundancy"
+ --#SUMMARY "The Redundant Switch has has lost redundancy."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 105
+
+rsRedundancyRestored TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Redundancy has been restored to the Redundant Switch .
+ The first variable is an integer representing the source which has been restored: 0=A, 1=B.
+ The second variable is the 32-character name of the source which has been restored."
+ --#TYPE "APC Redundant Switch: Redundancy has been restored."
+ --#SUMMARY "Redundancy has been restored to the Redundant Switch ."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 106
+
+rsConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A configuration change has been made on a Redundant Switch."
+ --#TYPE "APC: A configuration change on a Redundant Switch."
+ --#SUMMARY "A configuration change has been made on a Redundant Switch."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 107
+
+rsCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communications with the Redundant Switch has been established."
+ --#TYPE "APC: Communications established with the Redundant Switch."
+ --#SUMMARY "Communications with the Redundant Switch has been established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 108
+
+rsCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communications with the Redundant Switch has been lost."
+ --#TYPE "APC: Communications lost with the Redundant Switch."
+ --#SUMMARY "Communications with the Redundant Switch has been lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 109
+
+dcCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communications with the DC power plant has been established."
+ --#TYPE "APC: Communications established with the DC power plant."
+ --#SUMMARY "Communications with the DC power plant has been established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 110
+
+dcCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communications with the DC power plant has been lost."
+ --#TYPE "APC: Communications lost with the DC power plant."
+ --#SUMMARY "Communications with the DC power plant has been lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 111
+
+dcPINChanged TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The active PIN on the DC controller has been changed."
+ --#TYPE "APC: The active PIN on the DC controller has been changed."
+ --#SUMMARY "The active PIN on the DC controller has been changed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 112
+
+dcMajorAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A Major alarm is active in the DC power plant."
+ --#TYPE "APC: A Major alarm is active in the DC power plant."
+ --#SUMMARY "A Major alarm is active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 113
+
+dcMajorAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Major alarm is no longer active in the DC power plant."
+ --#TYPE "APC: A Major alarm is no longer active in the DC power plant."
+ --#SUMMARY "A Major alarm is no longer active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 114
+
+dcMinorAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Minor alarm is active in the DC power plant."
+ --#TYPE "APC: A Minor alarm is active in the DC power plant."
+ --#SUMMARY "A Minor alarm is active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 115
+
+dcMinorAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Minor alarm is no longer active in the DC power plant."
+ --#TYPE "APC: A Minor alarm is no longer active in the DC power plant."
+ --#SUMMARY "A Minor alarm is no longer active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 116
+
+dcOutputRelayOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { dm3StatusOutRlyIndex, dm3StatusOutRlyName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An output relay for the powerplant has been activated (state changed to on).
+ The first variable is an integer representing the output relay number that has gone on.
+ The second variable is the 16-character name of the output relay."
+ --#TYPE "APC: An output relay has gone on."
+ --#SUMMARY "An output relay has gone on in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 117
+
+dcOutputRelayOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { dm3StatusOutRlyIndex, dm3StatusOutRlyName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An output relay for the powerplant has been deactivated (state changed to off).
+ The first variable is an integer representing the output relay number that has gone off.
+ The second variable is the 16-character name of the output relay."
+ --#TYPE "APC: An output relay has gone off."
+ --#SUMMARY "An output relay has gone off in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 118
+
+dcInputRelayOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { dm3StatusInRlyIndex, dm3StatusInRlyName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An input relay for the powerplant has been activated (state changed to on).
+ The first variable is an integer representing the input relay number that has gone on.
+ The second variable is the 16-character name of the input relay."
+ --#TYPE "APC: An input relay has gone on."
+ --#SUMMARY "An input relay has gone on in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 119
+
+dcInputRelayOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { dm3StatusInRlyIndex, dm3StatusInRlyName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An input relay for the powerplant has been deactivated (state changed to off).
+ The first variable is an integer representing the input relay number that has gone off.
+ The second variable is the 16-character name of the input relay."
+ --#TYPE "APC: An input relay has gone off."
+ --#SUMMARY "An input relay has gone off in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 120
+
+logicPowerSuppliesIncreased TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The number of system power supplies has increased."
+ --#TYPE "APC UPS: The number of system power supplies has increased."
+ --#SUMMARY "The number of system power supplies has increased."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 121
+
+logicPowerSuppliesDecreased TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The number of system power supplies has decreased."
+ --#TYPE "APC UPS: The number of system power supplies has decreased."
+ --#SUMMARY "The number of system power supplies has decreased."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 122
+
+externalSwitchGearClosed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: External Switch Gear closed."
+ --#TYPE "APC UPS: External Switch Gear closed."
+ --#SUMMARY "External Switch Gear closed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 123
+
+externalSwitchGearOpened TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: External Switch Gear opened."
+ --#TYPE "APC UPS: External Switch Gear opened."
+ --#SUMMARY "External Switch Gear opened."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 124
+
+generalDeviceEvent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: APC Device event."
+ --#TYPE "APC Device event"
+ --#SUMMARY "APC Device event."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 125
+
+atsSourceSwitched TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The Automatic Transfer Switch has switched source.
+ The first variable is an integer representing the current source: 0=A, 1=B.
+ The second variable is the 32-character name of the current source."
+ --#TYPE "APC Automatic Transfer Switch: The ATS has switched source"
+ --#SUMMARY "The Automatic Transfer Switch has switched source."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 126
+
+atsLostRedundancy TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The Automatic Transfer Switch has lost redundancy.
+ The first variable is an integer representing the source which is no longer available: 0=A, 1=B.
+ The second variable is the 32-character name of the source which is no longer available."
+ --#TYPE "APC Automatic Transfer Switch: The ATS has lost redundancy. "
+ --#SUMMARY "The Automatic Transfer Switch has has lost redundancy."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 127
+
+atsRedundancyRestored TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Redundancy has been restored to the Automatic Transfer Switch .
+ The first variable is an integer representing the source which has been restored: 0=A, 1=B.
+ The second variable is the 32-character name of the source which has been restored."
+ --#TYPE "APC Automatic Transfer Switch: Redundancy has been restored."
+ --#SUMMARY "Redundancy has been restored to the Automatic Transfer Switch ."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 128
+
+atsConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A configuration change has been made on the Automatic Transfer Switch.
+ The first variable is an integer representing the configuration setting which changed:
+ 0=Transfer Voltage Range, 1=Sensitivity 2=Preferred Source
+ 3=Front Panel Lockout 4=Current Limit"
+ --#TYPE "APC Automatic Transfer Switch: ATS configuration changed."
+ --#SUMMARY "A configuration change has been made on a Automatic Transfer Switch."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 129
+
+atsCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communications with the Automatic Transfer Switch has been established."
+ --#TYPE "APC Automatic Transfer Switch: Communications established."
+ --#SUMMARY "Communications with the Automatic Transfer Switch has been established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 130
+
+atsCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communications with the Automatic Transfer Switch has been lost."
+ --#TYPE "APC Automatic Transfer Switch: Communications lost."
+ --#SUMMARY "Communications with the Automatic Transfer Switch has been lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 131
+
+atsOverCurrent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Output Current has exceeded threshold."
+ --#TYPE "APC Automatic Transfer Switch: Output Current exceeded threshold"
+ --#SUMMARY "Output Current has exceeded Threshold. "
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 132
+
+atsOverCurrentCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Output Current has returned below threshold."
+ --#TYPE "APC Automatic Transfer Switch: Output Current below threshold."
+ --#SUMMARY "Output Current has returned below threshold."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 133
+
+atsPowerSupplyFailure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The Automatic Transfer Switch Power Supply has failed.
+ The first variable is an integer representing the Power Supply which
+ has failed: 0=24V, 1=12V 2=5V."
+ --#TYPE "APC Automatic Transfer Switch: The ATS Power Supply has failed."
+ --#SUMMARY "The Automatic Transfer Switch Power Supply has failed."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 134
+
+atsPowerSupplyFailureCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The Automatic Transfer Power Supply Failure Cleared.
+ The first variable is an integer representing the Power Supply which
+ has cleared: 0=24V, 1=12V 2=5V."
+ --#TYPE "APC Automatic Transfer Switch: Power Supply Failure Cleared."
+ --#SUMMARY "The Automatic Transfer Switch Power Supply Failure Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 135
+
+dcMainsFailAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Mains Fail alarm is active in the DC power plant."
+ --#TYPE "APC: A Mains Fail alarm is active in the DC power plant."
+ --#SUMMARY "A Mains Fail alarm is active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 136
+
+dcMainsFailAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Mains Fail alarm is no longer active in the DC power plant."
+ --#TYPE "APC: Mains Fail alarm is no longer active in the DC power plant."
+ --#SUMMARY "Mains Fail alarm is no longer active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 137
+
+dcFanFailAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Fan Fail alarm is active in the DC power plant."
+ --#TYPE "APC: A Fan Fail alarm is active in the DC power plant."
+ --#SUMMARY "A Fan Fail alarm is active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 138
+
+dcFanFailAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Fan Fail alarm is no longer active in the DC power plant."
+ --#TYPE "APC: A Fan Fail alarm is no longer active in the DC power plant."
+ --#SUMMARY "A Fan Fail alarm is no longer active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 139
+
+dcRectifierOvertempAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: Rect. Overtemp alarm is active in the power plant."
+ --#TYPE "APC: Rect. Overtemp alarm is active in the power plant."
+ --#SUMMARY "Rect. Overtemp alarm is active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 140
+
+dcRectifierOvertempAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Rect. Overtemp alarm is no longer active in the power plant."
+ --#TYPE "APC: Rect. Overtmp alarm is no longer active in the power plant."
+ --#SUMMARY "Rect. Overtmp alarm is no longer active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 141
+
+dcCurrentLimitAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Current Limit alarm is active in the power plant."
+ --#TYPE "APC: A Current Limit alarm is active in the power plant."
+ --#SUMMARY "A Current Limit alarm is active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 142
+
+dcCurrentLimitAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Current Limit alarm is no longer active in the power plant."
+ --#TYPE "APC: Current Limit alarm is no longer active in the power plant."
+ --#SUMMARY "Current Limit alarm is no longer active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 143
+
+dcRectifierFailAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Rect. Fail alarm is active in the power plant."
+ --#TYPE "APC: A Rect. Fail alarm is active in the power plant."
+ --#SUMMARY "A Rect. Fail alarm is active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 144
+
+dcRectifierFailAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Rect. Fail alarm is no longer active in the power plant."
+ --#TYPE "APC: Rect. Fail alarm is no longer active in the power plant."
+ --#SUMMARY "Rect. Fail alarm is no longer active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 145
+
+dcMultRectFailAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: Multiple Rect. Fail alarm is active in the powerplant."
+ --#TYPE "APC: Multiple Rect. Fail alarm is active in the powerplant."
+ --#SUMMARY "Multiple Rect. Fail alarm is active in the powerplant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 146
+
+dcMultRectFailAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Mult Rect Fail alarm is no longer active in the powerplant."
+ --#TYPE "APC: Mult Rect Fail alarm is no longer active in the powerplant."
+ --#SUMMARY "Mult Rect Fail alarm is no longer active in the powerplant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 147
+
+dcBatteryBreakerAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: Batt. Breaker alarm is active in the power plant."
+ --#TYPE "APC: Batt. Breaker alarm is active in the power plant."
+ --#SUMMARY "Batt. Breaker alarm is active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 148
+
+dcBatteryBreakerAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Batt. Breaker alarm is no longer active in the power plant."
+ --#TYPE "APC: Batt. Breaker alarm is no longer active in the power plant."
+ --#SUMMARY "Batt. Breaker alarm is no longer active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 149
+
+dcRectifierOVPAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Rect. OVP alarm is active in the power plant."
+ --#TYPE "APC: A Rect. OVP alarm is active in the power plant."
+ --#SUMMARY "A Rect. OVP alarm is active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 150
+
+dcRectifierOVPAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Rect. OVP alarm is no longer active in the power plant."
+ --#TYPE "APC: A Rect. OVP alarm is no longer active in the power plant."
+ --#SUMMARY "A Rect. OVP alarm is no longer active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 151
+
+dcLVDImminentAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A LVD Imminent alarm is active in the powerplant."
+ --#TYPE "APC: A LVD Imminent alarm is active in the powerplant."
+ --#SUMMARY "A LVD Imminent alarm is active in the powerplant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 152
+
+dcLVDImminentAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A LVD Imminent alarm is no longer active in the powerplant."
+ --#TYPE "APC: A LVD Imminent alarm is no longer active in the powerplant."
+ --#SUMMARY "A LVD Imminent alarm is no longer active in the powerplant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 153
+
+dcFuseCBAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Fuse/CB alarm is active in the DC power plant."
+ --#TYPE "APC: A Fuse/CB alarm alarm is active in the DC power plant."
+ --#SUMMARY "A Fuse/CB alarm is active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 154
+
+dcFuseCBAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Fuse/CB alarm is no longer active in the DC power plant."
+ --#TYPE "APC: A Fuse/CB alarm is no longer active in the DC power plant."
+ --#SUMMARY "A Fuse/CB alarm is no longer active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 155
+
+dcBatteryTestFail TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Battery Test failed in the DC power plant."
+ --#TYPE "APC: A Battery Test failed in the DC power plant."
+ --#SUMMARY "A Battery Test failed in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 156
+
+dcTemperatureAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Temperature is active in the power plant."
+ --#TYPE "APC: A Temperature alarm is active in the power plant."
+ --#SUMMARY "A Temperature alarm is active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 157
+
+dcTemperatureAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Temperature alarm is no longer active in the power plant."
+ --#TYPE "APC: A Temperature alarm is no longer active in the power plant."
+ --#SUMMARY "A Temperature alarm is no longer active in the power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 158
+
+dcHumidityAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Humidity alarm is active in the DC power plant."
+ --#TYPE "APC: A Humidity alarm is active in the DC power plant."
+ --#SUMMARY "A Humidity alarm is active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 159
+
+dcHumidityAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Humidity alarm is no longer active in the DC power plant."
+ --#TYPE "APC: A Humidity alarm is no longer active in the DC power plant."
+ --#SUMMARY "A Humidity alarm is no longer active in the DC power plant."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 160
+
+dcBBCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Power plant bridging board communications established."
+ --#TYPE "APC: Power plant bridging board communications established."
+ --#SUMMARY "Power plant bridging board communications established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 161
+
+dcBBCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Power plant bridging board communications lost."
+ --#TYPE "APC: Power plant bridging board communications lost."
+ --#SUMMARY "Power plant bridging board communications lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 162
+
+iemHighTempThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeCurrentTemp, iemStatusProbeTempUnits, iemStatusProbeNumber,
+ iemStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: High temperature threshold violated on Integrated
+ Environmental Monitor probe. The first variable is the
+ current temperature. The second variable is the temperature
+ scale. The third variable is the probe number. The fourth
+ variable is the probe name."
+ --#TYPE "APC IEM: High temperature threshold violation."
+ --#SUMMARY "High temperature threshold violation."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 163
+
+iemHighTempThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeNumber, iemStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: High temperature threshold violated on Integrated
+ Environmental Monitor probe has been cleared. The first variable
+ is the probe number. The second variable is the probe name."
+ --#TYPE "APC IEM: High temperature threshold violation cleared."
+ --#SUMMARY "High temperature threshold violation has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 164
+
+iemLowTempThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeCurrentTemp, iemStatusProbeTempUnits, iemStatusProbeNumber,
+ iemStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Low temperature threshold violated on integrated
+ probe. The first variable is the current temperature. The
+ second variable is the temperature scale. The third
+ variable is the probe number. The fourth variable is the
+ probe name."
+ --#TYPE "APC IEM: Low temperature threshold violation."
+ --#SUMMARY "Low temperature threshold violation."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 165
+
+iemLowTempThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeNumber, iemStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Low temperature threshold violated on integrated
+ probe has been cleared. The first variable is the probe number.
+ The second variable is the probe name."
+ --#TYPE "APC IEM: Low temperature threshold violation cleared."
+ --#SUMMARY "Low temperature threshold violation has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 166
+
+iemHighHumidThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeCurrentHumid, iemStatusProbeNumber, iemStatusProbeName,
+ mtrapargsString }
+ DESCRIPTION
+ "SEVERE: High humidity threshold violated on integrated
+ probe. The first variable is the current humidity. The
+ second variable is the probe number. The third variable
+ is the probe name."
+ --#TYPE "APC IEM: High humidity threshold violation."
+ --#SUMMARY "High humidity threshold violation."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 167
+
+iemHighHumidThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeNumber, iemStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: High humidity threshold violated on integrated
+ probe cleared. The first variable is the probe number. The second
+ variable is the probe name."
+ --#TYPE "APC IEM: High humidity threshold violation cleared."
+ --#SUMMARY "High humidity threshold violation has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 168
+
+iemLowHumidThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeCurrentHumid, iemStatusProbeNumber, iemStatusProbeName,
+ mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Low humidity threshold violated on integrated
+ probe. The first variable is the current humidity. The
+ second variable is the probe number. The third variable
+ is the probe name."
+ --#TYPE "APC IEM: Low humidity threshold violation."
+ --#SUMMARY "Low humidity threshold violation."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 169
+
+iemLowHumidThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusProbeNumber, iemStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Low humidity threshold violated on integrated
+ probe cleared. The first variable is the probe number. The second
+ variable is the probe name."
+ --#TYPE "APC IEM: Low humidity threshold violation cleared."
+ --#SUMMARY "Low humidity threshold violation has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 170
+
+iemProbeDisconnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The temperature/humidity probe on the Integrated
+ Environmental Monitor has been disconnected. This trap is
+ generated when a probe that has been in communication with
+ the Environmental Monitor has been disconnected or can no
+ longer communicate."
+ --#TYPE "APC IEM: Probe disconnected."
+ --#SUMMARY "Probe has been disconnected."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 171
+
+iemProbeConnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The temperature/humidity probe on the Integrated
+ Environmental Monitor has been connected. This trap is generated
+ when the Environmental Monitor establishes communication with a
+ probe that had previously not been connected."
+ --#TYPE "APC IEM: Probe Connected."
+ --#SUMMARY "Probe has been connected."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 172
+
+iemContactFault TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusContactNumber, iemStatusContactName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: There is a contact fault on the Integrated
+ Environmental Monitor. The first argument is the number
+ of the contact. The second argument is the name of the
+ contact."
+ --#TYPE "APC IEM: Contact fault."
+ --#SUMMARY "Contact fault."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 173
+
+iemContactFaultCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusContactNumber, iemStatusContactName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The contact fault on the Integrated
+ Environmental Monitor has been cleared. The first
+ argument is the number of the contact. The second
+ argument is the name of the contact."
+ --#TYPE "APC IEM: Contact fault."
+ --#SUMMARY "Contact fault cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 174
+
+iemRelayFault TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusRelayNumber, iemStatusRelayName, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The output relay on the Integrated Environmental
+ Monitor has switched to the fault state. The first
+ argument is the number of the output relay. The second
+ argument is the name of the output relay. The third
+ argument is the event that caused the fault."
+ --#TYPE "APC IEM: Output relay fault."
+ --#SUMMARY "Output relay has faulted."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 175
+
+iemRelayFaultCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { iemStatusRelayNumber, iemStatusRelayName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The fault condition on the output relay on the
+ Integrated Environmental Monitor has cleared. The first
+ argument is the number of the output relay. The second
+ argument is the name of the output relay."
+ --#TYPE "APC IEM: Output relay fault condition cleared."
+ --#SUMMARY "Output relay fault cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 176
+
+bmBatManCommEstab TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Serial Communications Established with Battery Manager."
+ --#TYPE "BatMan : Communications Established."
+ --#SUMMARY "Communications Established."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 177
+
+bmBatManCommLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Serial Communications Lost with Battery Manager."
+ --#TYPE "BatMan : Communications Lost."
+ --#SUMMARY "Communications Lost."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 178
+
+bmBatManKneeAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Battery Voltage Knee Threshold Alarm Detected."
+ --#TYPE "BatMan : Knee Alarm Detected."
+ --#SUMMARY "Knee Alarm Detected."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 179
+
+bmBatManKneeAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Battery Voltage Knee Threshold Alarm Cleared."
+ --#TYPE "BatMan : Knee Alarm Cleared."
+ --#SUMMARY "Knee Alarm Cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 180
+
+bmBatManChargerAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Charger Alarm Detected."
+ --#TYPE "BatMan : Charger Alarm Detected."
+ --#SUMMARY "Charger Alarm Detected."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 181
+
+bmBatManChargerAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Charger Alarm Cleared."
+ --#TYPE "BatMan : Charger Alarm Cleared."
+ --#SUMMARY "Charger Alarm Cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 182
+
+bmBatManBatteryAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Battery Alarm Detected."
+ --#TYPE "BatMan : Battery Alarm Detected."
+ --#SUMMARY "Battery Alarm Detected."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 183
+
+bmBatManBatteryAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Battery Alarm Cleared."
+ --#TYPE "BatMan : Battery Alarm Cleared."
+ --#SUMMARY "Battery Alarm Cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 184
+
+bmBatManEnvironmentAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Environment Alarm Detected."
+ --#TYPE "BatMan : Environment Alarm Detected."
+ --#SUMMARY "Environment Alarm Detected."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 185
+
+bmBatManEnvironmentAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Environment Alarm Cleared."
+ --#TYPE "BatMan : Environment Alarm Cleared."
+ --#SUMMARY "Environment Alarm Cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 186
+
+bmBatManMaintenanceAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Maintenance Alarm Detected."
+ --#TYPE "BatMan : Maintenance Due Alarm Detected."
+ --#SUMMARY "Maintenance Due Alarm Detected."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 187
+
+bmBatManMaintenanceAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Maintenance Alarm Cleared."
+ --#TYPE "BatMan : Maintenance Due Alarm Cleared."
+ --#SUMMARY "Maintenance Due Alarm Cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 188
+
+pduCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communication Established.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Communication Established."
+ --#SUMMARY "Communication Established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 189
+
+pduCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communication Lost.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Communication Lost."
+ --#SUMMARY "Communication Lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 190
+
+pduUtilityLineUndervoltage TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Utility Line Undervoltage.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Utility Line Undervoltage."
+ --#SUMMARY "Utility Line Undervoltage."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 191
+
+pduUtilityLineUndervoltageCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Utility Line Undervoltage Cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Utility Line Undervoltage Cleared."
+ --#SUMMARY "Utility Line Undervoltage Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 192
+
+pduUtilityLineOvervoltage TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Utility Line Overvoltage.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Utility Line Overvoltage."
+ --#SUMMARY "Utility Line Overvoltage."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 193
+
+pduUtilityLineOvervoltageCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Utility Line Overvoltage Cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Utility Line Overvoltage Cleared."
+ --#SUMMARY "Utility Line Overvoltage Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 194
+
+pduGroundOvercurrent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Ground Overcurrent.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Ground Overcurrent."
+ --#SUMMARY "Ground Overcurrent."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 195
+
+pduGroundOvercurrentCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Ground Overcurrent Cleared.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Ground Overcurrent Cleared."
+ --#SUMMARY "Ground Overcurrent Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 196
+
+pduCircuitPanelInputUndervoltage TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Circuit Panel Input Undervoltage.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Undervoltage."
+ --#SUMMARY "Circuit Panel Input Undervoltage."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 197
+
+pduCircuitPanelInputUndervoltageCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Circuit Panel Input Undervoltage Cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Undervoltage Cleared."
+ --#SUMMARY "Circuit Panel Input Undervoltage Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 198
+
+pduCircuitPanelInputOvervoltage TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Circuit Panel Input Overvoltage.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Overvoltage."
+ --#SUMMARY "Circuit Panel Input Overvoltage."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 199
+
+pduCircuitPanelInputOvervoltageCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Circuit Panel Input Overvoltage Cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Overvoltage Cleared."
+ --#SUMMARY "Circuit Panel Input Overvoltage Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 200
+
+pduCircuitPanelInputUndercurrent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Circuit Panel Input Undercurrent.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Undercurrent."
+ --#SUMMARY "Circuit Panel Input Undercurrent."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 201
+
+pduCircuitPanelInputUndercurrentCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Circuit Panel Input Undercurrent Cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Undercurrent Cleared."
+ --#SUMMARY "Circuit Panel Input Undercurrent Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 202
+
+pduCircuitPanelInputOvercurrent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Circuit Panel Input Overcurrent.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Overcurrent."
+ --#SUMMARY "Circuit Panel Input Overcurrent."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 203
+
+pduCircuitPanelInputOvercurrentCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Circuit Panel Input Overcurrent Cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: Circuit Panel Input Overcurrent Cleared."
+ --#SUMMARY "Circuit Panel Input Overcurrent Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 204
+
+pduCircuitPanelFrequencyOutOfRange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Circuit Panel Input Frequency Out Of Range.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Circuit Panel Input Frequency Out Of Range."
+ --#SUMMARY "Circuit Panel Input Frequency Out Of Range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 205
+
+pduCircuitPanelFrequencyOutofRangeCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Circuit Panel Input Frequency No Longer Out Of Range.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Circuit Panel Input Frequency No Longer Out Of Range."
+ --#SUMMARY "Circuit Panel Input Frequency No Longer Out Of Range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 206
+
+pduCircuitPanelNeutralOvercurrent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Circuit Panel Input Neutral Overcurrent.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Circuit Panel Input Neutral Overcurrent."
+ --#SUMMARY "Circuit Panel Input Neutral Overcurrent."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 207
+
+pduCircuitPanelNeutralOvercurrentCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Circuit Panel Input Neutral Overcurrent Cleared.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Circuit Panel Input Neutral Overcurrent Cleared."
+ --#SUMMARY "Circuit Panel Input Neutral Overcurrent Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 208
+
+pduSystemOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: PDU System Off.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: System Off."
+ --#SUMMARY "PDU System Off."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 209
+
+pduOnBatteryMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: PDU is in On Battery Mode.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: On Battery Mode."
+ --#SUMMARY "PDU is in On Battery Mode."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 210
+
+pduMaintenanceBypassMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: PDU is in Maintenance Bypass Mode.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Maintenance Bypass Mode."
+ --#SUMMARY "PDU is in Maintenance Bypass Mode."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 211
+
+pduAtypicalBypassMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "WARNING: PDU is in Atypical Bypass Mode.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Atypical Bypass Mode."
+ --#SUMMARY "PDU is in Atypical Bypass Mode."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 212
+
+pduNoPanelFeedMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: PDU is in No Panel Feed Mode.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: No Panel Feed Mode."
+ --#SUMMARY "PDU is in No Panel Feed Mode."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 213
+
+pduUpsOperationMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: PDU is in Ups Operation Mode.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Ups Operation Mode."
+ --#SUMMARY "PDU is in Ups Operation Mode."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 214
+
+pduForcedBypassMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "WARNING: PDU is in Forced Bypass Mode.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Forced Bypass Mode."
+ --#SUMMARY "PDU is in Forced Bypass Mode."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 215
+
+pduInputTransformerOverTemperature TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Input Transformer Over Temperature.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Input Transformer Over Temperature."
+ --#SUMMARY "Input Transformer Over Temperature."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 216
+
+pduInputTransformerOverTemperatureCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Input Transformer Over Temperature Cleared.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC PDU: Input Transformer Over Temperature Cleared."
+ --#SUMMARY "Input Transformer Over Temperature Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 217
+
+pduUPSInputVoltageLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: UPS Input Voltage phase-N Lost.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: UPS Input Voltage phase-N Lost."
+ --#SUMMARY "UPS Input Voltage phase-N Lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 218
+
+pduUPSInputVoltageRestored TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: UPS Input Voltage phase-N Restored.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC PDU: UPS Input Voltage phase-N Restored."
+ --#SUMMARY "UPS Input Voltage phase-N Restored."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 219
+
+pduContactFault TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A contact closure in the PDU is in an abnormal position.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the number of the contact."
+ --#TYPE "APC PDU: Contact Abnormal."
+ --#SUMMARY "Contact Abnormal."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 220
+
+pduContactFaultCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A contact closure in the PDU is in a normal position.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the number of the contact."
+ --#TYPE "APC PDU: Contact Normal."
+ --#SUMMARY "Contact Normal."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 221
+
+rPDUBankPhaseLowLoad TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusBankNumber, rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A bank or phase on the Rack PDU has violated the low load threshold.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the bank number (0 if this is phase data).
+ The fourth argument is the phase number (0 if this is bank data)."
+ --#TYPE "APC Rack PDU: Violation of bank or phase low load threshold."
+ --#SUMMARY "A bank or phase on the Rack PDU has violated the low load threshold."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 222
+
+rPDUBankPhaseLowLoadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusBankNumber, rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The bank or phase low load condition on a Rack PDU has been
+ cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the bank number (0 if this is phase data).
+ The fourth argument is the phase number (0 if this is bank data)."
+ --#TYPE "APC Rack PDU: Bank or phase low load condition cleared."
+ --#SUMMARY "The bank or phase low load condition on a Rack PDU has been cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 223
+
+rPDUBankPhaseNearOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusBankNumber, rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A bank or phase of the Rack PDU is near an overload condition.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the bank number (0 if this is phase data).
+ The fourth argument is the phase number (0 if this is bank data)."
+ --#TYPE "APC Rack PDU: Bank or phase near an overload condition."
+ --#SUMMARY "A bank or phase of the Rack PDU is near an overload condition."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 224
+
+rPDUBankPhaseNearOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusBankNumber, rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The bank or phase near overload condition on a Rack PDU has
+ been cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the bank number (0 if this is phase data).
+ The fourth argument is the phase number (0 if this is bank data)."
+ --#TYPE "APC Rack PDU: Bank or phase near overload condition has cleared."
+ --#SUMMARY "Rack PDU bank or phase near overload condition has cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 225
+
+rPDUBankPhaseOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusBankNumber, rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A bank or phase of the Rack PDU is in an overload condition.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number.
+ The third argument is the bank number (0 if this is phase data).
+ The fourth argument is the phase number (0 if this is bank data)."
+ --#TYPE "APC Rack PDU: Bank or phase overload condition."
+ --#SUMMARY "A bank or phase of the Rack PDU is in an overload condition."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 226
+
+rPDUBankPhaseOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusBankNumber, rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The bank or phase overload condition on a Rack PDU has been
+ cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the bank number (0 if this is phase data).
+ The fourth argument is the phase number (0 if this is bank data)."
+ --#TYPE "APC Rack PDU: Bank or phase overload condition has cleared."
+ --#SUMMARY "The bank or phase overload condition on a Rack PDU has cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 227
+
+aruDeviceConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Remote ARU Device Configurtion change.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: ARU Device configuration change."
+ --#SUMMARY "ARU device configuration change."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 228
+
+rmPDUCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString03, mtrapargsString02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communication Lost.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC RM PDU: Communication Lost."
+ --#SUMMARY "Communication Lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 229
+
+emsCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communication Established.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC EMS: Communication Established."
+ --#SUMMARY "Communication Established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 230
+
+emsCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communication Lost.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC EMS: Communication Lost."
+ --#SUMMARY "Communication Lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 231
+
+emsProbeConnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A probe has been connected to the EMS.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the probe number.
+ The fourth argument is the probe name."
+ --#TYPE "APC EMS: Probe Connected."
+ --#SUMMARY "Probe Connected."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 232
+
+emsProbeDisconnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A probe has been disconnected from the EMS.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the probe number.
+ The fourth argument is the probe name."
+ --#TYPE "APC EMS: Probe Disconnected."
+ --#SUMMARY "Probe Disconnected."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 233
+
+emsSensorConnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsSensorStatusSensorIndex, emsSensorStatusSensorName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A sensor has been connected to the EMS.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the sensor number.
+ The fourth argument is the sensor name."
+ --#TYPE "APC EMS: Sensor Connected."
+ --#SUMMARY "Sensor Connected."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 234
+
+emsSensorDisconnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsSensorStatusSensorIndex, emsSensorStatusSensorName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A sensor has been disconnected from the EMS.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the sensor number.
+ The fourth argument is the sensor name."
+ --#TYPE "APC EMS: Sensor Disconnected."
+ --#SUMMARY "Sensor Disconnected."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 235
+
+emsSensorFault TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsSensorStatusSensorIndex, emsSensorStatusSensorName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A EMS sensor is in the fault condition.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the sensor number.
+ The fourth argument is the sensor name."
+ --#TYPE "APC EMS: Sensor Fault."
+ --#SUMMARY "Sensor Fault."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 236
+
+emsSensorFaultCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsSensorStatusSensorIndex, emsSensorStatusSensorName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A EMS sensor fault condition has cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the sensor number.
+ The fourth argument is the sensor name."
+ --#TYPE "APC EMS: Sensor Fault Cleared."
+ --#SUMMARY "Sensor Fault Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 237
+
+emsBeaconConnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A beacon has been connected to the EMS.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC EMS: Beacon Connected."
+ --#SUMMARY "Beacon Connected."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 238
+
+emsBeaconDisconnected TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A beacon has been disconnected from the EMS.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC EMS: Beacon Disconnected."
+ --#SUMMARY "Beacon Disconnected."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 239
+
+emsBeaconOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A EMS beacon has gone on.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC EMS: Beacon On."
+ --#SUMMARY "Beacon On."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 240
+
+emsBeaconOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A EMS beacon has gone off.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC EMS: Beacon Off."
+ --#SUMMARY "Beacon Off."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 241
+
+emsMajorAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A Major Alarm is present in the EMS.
+ The first argument is the EMS serial number.
+ The second argument is the EMS name."
+ --#TYPE "APC EMS: Major Alarm."
+ --#SUMMARY "Major Alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 242
+
+emsMajorAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Major Alarm condition has been cleared in the EMS.
+ The first argument is the EMS serial number.
+ The second argument is the EMS name."
+ --#TYPE "APC EMS: Major Alarm Cleared."
+ --#SUMMARY "Major Alarm Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 243
+
+emsMinorAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A Minor Alarm is present in the EMS.
+ The first argument is the EMS serial number.
+ The second argument is the EMS name."
+ --#TYPE "APC EMS: Minor Alarm."
+ --#SUMMARY "Minor Alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 244
+
+emsMinorAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Minor Alarm condition has been cleared in the EMS.
+ The first argument is the EMS serial number.
+ The second argument is the EMS name."
+ --#TYPE "APC EMS: Minor Alarm Cleared."
+ --#SUMMARY "Minor Alarm Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 245
+
+emsOutletStateAbnormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsOutletStatusOutletIndex, emsOutletStatusOutletName,
+ emsOutletStatusOutletState, emsOutletStatusOutletNormalState, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An outlet on the EMS has changed to its abnormal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the outlet number.
+ The fourth argument is the outlet name.
+ The fifth argument is the current outlet state (1=ON, 2=OFF).
+ The sixth argument is the configured normal outlet state (1=ON, 2=OFF)."
+ --#TYPE "APC EMS: Outlet has changed to its abnormal state."
+ --#SUMMARY "Outlet has changed to its abnormal state."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 246
+
+emsOutletStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsOutletStatusOutletIndex, emsOutletStatusOutletName,
+ emsOutletStatusOutletState, emsOutletStatusOutletNormalState, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet on the EMS has changed to its normal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the outlet number.
+ The fourth argument is the outlet name.
+ The fifth argument is the current outlet state (1=ON, 2=OFF).
+ The sixth argument is the configured normal outlet state (1=ON, 2=OFF)."
+ --#TYPE "APC EMS: Outlet has changed to its normal state."
+ --#SUMMARY "Outlet has changed to its normal state."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 247
+
+emsInputContactStateAbnormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsInputContactStatusInputContactIndex,
+ emsInputContactStatusInputContactName, emsInputContactStatusInputContactState,
+ emsInputContactStatusInputContactNormalState, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An input contact on the EMS has changed to its abnormal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the input contact number.
+ The fourth argument is the input contact name.
+ The fifth argument is the input contact state (1=CLOSED, 2=OPEN).
+ The sixth argument is the configured normal input contact state (1=CLOSED, 2=OPEN)."
+ --#TYPE "APC EMS: Input contact has changed to its abnormal state."
+ --#SUMMARY "Input contact has changed to its abnormal state."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 248
+
+emsInputContactStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsInputContactStatusInputContactIndex,
+ emsInputContactStatusInputContactName, emsInputContactStatusInputContactState,
+ emsInputContactStatusInputContactNormalState, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An input contact on the EMS has changed to its normal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the input contact number.
+ The fourth argument is the input contact name.
+ The fifth argument is the input contact state (1=CLOSED, 2=OPEN).
+ The sixth argument is the configured normal input contact state (1=CLOSED, 2=OPEN)."
+ --#TYPE "APC EMS: Input contact has changed to its normal state."
+ --#SUMMARY "Input contact has changed to its normal state."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 249
+
+emsOutputRelayStateAbnormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsOutputRelayStatusOutputRelayIndex,
+ emsOutputRelayStatusOutputRelayName, emsOutputRelayStatusOutputRelayState,
+ emsOutputRelayStatusOutputRelayNormalState, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An output relay on the EMS has changed to its abnormal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the output relay number.
+ The fourth argument is the output relay name.
+ The fifth argument is the current output relay state (1=CLOSED, 2=OPEN).
+ The sixth argument is the configured normal output relay state (1=CLOSED, 2=OPEN)."
+ --#TYPE "APC EMS: Output Relay has changed to its abnormal state."
+ --#SUMMARY "Output Relay has changed to its abnormal state."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 250
+
+emsOutputRelayStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsOutputRelayStatusOutputRelayIndex,
+ emsOutputRelayStatusOutputRelayName, emsOutputRelayStatusOutputRelayState,
+ emsOutputRelayStatusOutputRelayNormalState, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An output relay on the EMS has changed to its normal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the output relay number.
+ The fourth argument is the output relay name.
+ The fifth argument is the current output relay state (1=CLOSED, 2=OPEN).
+ The sixth argument is the configured normal output relay state (1=CLOSED, 2=OPEN)."
+ --#TYPE "APC EMS: Output Relay has changed to its normal state."
+ --#SUMMARY "Output Relay has changed to its normal state."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 251
+
+emsDeviceConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A device configuration change has been made on the EMS.
+ The first argument is the EMS serial number.
+ The second argument is the EMS name."
+ --#TYPE "APC: A device configuration change on a EMS."
+ --#SUMMARY "A device configuration change has been made on a EMS."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 252
+
+envHighTempThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: High temperature threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: High temperature threshold violation."
+ --#SUMMARY "High temperature threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 253
+
+envHighTempThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: High temperature threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: High temperature threshold violation cleared."
+ --#SUMMARY "High temperature threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 254
+
+envLowTempThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Low temperature threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Low temperature threshold violation."
+ --#SUMMARY "Low temperature threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 255
+
+envLowTempThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Low temperature threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Low temperature threshold violation cleared."
+ --#SUMMARY "Low temperature threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 256
+
+envHighHumidityThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: High humidity threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: High humidity threshold violation."
+ --#SUMMARY "High humidity threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 257
+
+envHighHumidityThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: High humidity threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity.
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: High humidity threshold violation cleared."
+ --#SUMMARY "High humidity threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 258
+
+envLowHumidityThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Low humidity threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: Low humidity threshold violation."
+ --#SUMMARY "Low humidity threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 259
+
+envLowHumidityThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Low humidity threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity.
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: Low humidity threshold violation cleared."
+ --#SUMMARY "Low humidity threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 260
+
+
+-- Switched and Metered Rack PDU Traps
+
+rPDUCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Communication with a Rack PDU has been established.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC Rack PDU: Communication established."
+ --#SUMMARY "Communication with a Rack PDU established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 266
+
+rPDUCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Communication with a Rack PDU has been lost.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC Rack PDU: Communication lost."
+ --#SUMMARY "Communication with a Rack PDU has been lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 267
+
+rPDUOutletOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDUOutletControlIndex, rPDUOutletControlOutletName,
+ mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet on a Switched Rack PDU has turned on.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the outlet index number.
+ The fourth argument is the outlet name."
+ --#TYPE "APC Switched Rack PDU: An outlet has turned on."
+ --#SUMMARY "An outlet on a Switched Rack PDU has turned on."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 268
+
+rPDUOutletOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDUOutletControlIndex, rPDUOutletControlOutletName,
+ mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet on a Switched Rack PDU has turned off.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the outlet index number.
+ The fourth argument is the outlet name."
+ --#TYPE "APC Switched Rack PDU: An outlet has turned off."
+ --#SUMMARY "An outlet on a Switched Rack PDU has turned off."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 269
+
+rPDUDeviceConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A device configuration change has been made on a
+ Rack PDU.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC Rack PDU: Device configuration change made."
+ --#SUMMARY "Device configuration change has been made on a Rack PDU."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 270
+
+rPDUOutletConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDUOutletControlIndex, rPDUOutletControlOutletName,
+ mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An outlet configuration change has been made on a
+ Switched Rack PDU.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the outlet index number.
+ The fourth argument is the outlet name."
+ --#TYPE "APC Switched Rack PDU: Outlet configuration change made."
+ --#SUMMARY "Outlet configuration change has been made on a Switched Rack PDU."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 271
+
+rPDULowLoad TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Rack PDU has violated the low load threshold.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC Rack PDU: Violation of low load threshold."
+ --#SUMMARY "A Rack PDU has violated the low load threshold."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 272
+
+rPDULowLoadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The low load condition on a Rack PDU has been
+ cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC Rack PDU: Low load condition cleared."
+ --#SUMMARY "The low load condition on a Rack PDU has been cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 273
+
+rPDUNearOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Rack PDU is near an overload condition.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC Rack PDU: Near an overload condition."
+ --#SUMMARY "A Rack PDU is near an overload condition."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 274
+
+rPDUNearOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The near overload condition on a Rack PDU has
+ been cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC Rack PDU: Near overload condition has cleared."
+ --#SUMMARY "Rack PDU near overload condition has cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 275
+
+rPDUOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A Rack PDU is in an overload condition.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC Rack PDU: Overload condition."
+ --#SUMMARY "A Rack PDU is in an overload condition."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 276
+
+rPDUOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadStatusPhaseNumber, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The overload condition on a Rack PDU has been
+ cleared.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase number."
+ --#TYPE "APC Rack PDU: Overload condition has cleared."
+ --#SUMMARY "The overload condition on a Rack PDU has cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 277
+
+rPDUPowerSupply1Fail TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Power Supply 1 on Rack PDU is in FAIL state.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC Rack PDU: Power Supply 1 is in FAIL state."
+ --#SUMMARY "Power Supply 1 on Rack PDU is in FAIL state."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 278
+
+rPDUPowerSupply1Ok TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Power Supply 1 on Rack PDU is operating normally.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC Rack PDU: Power Supply 1 is operating normally."
+ --#SUMMARY "Power Supply 1 on Rack PDU is operating normally."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 279
+
+rPDUPowerSupply2Fail TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Power Supply 2 on Rack PDU is in FAIL state.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC Rack PDU: Power Supply 2 is in FAIL state."
+ --#SUMMARY "Power Supply 2 on Rack PDU is in FAIL state."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 280
+
+rPDUPowerSupply2Ok TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Power Supply 2 on Rack PDU is operating normally.
+ The first argument is the serial number.
+ The second argument is the device name."
+ --#TYPE "APC Rack PDU: Power Supply 2 is operating normally."
+ --#SUMMARY "Power Supply 2 on Rack PDU is operating normally."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 281
+
+rPDUPhaseConfigChange TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDULoadPhaseConfigIndex, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A phase configuration change has been made on a
+ Rack PDU.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the phase index number."
+ --#TYPE "APC Rack PDU: Phase configuration change made."
+ --#SUMMARY "Phase configuration change has been made on a Rack PDU."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 282
+
+rPDUCancelPendingCommand TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { rPDUIdentSerialNumber, rPDUIdentName,
+ rPDUOutletControlIndex, rPDUOutletControlOutletName,
+ mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A cancel pending command has been made on a
+ Switched Rack PDU.
+ The first argument is the serial number.
+ The second argument is the device name.
+ The third argument is the outlet index number (0 indicates all outlets).
+ The fourth argument is the outlet name (or device name if all outlets)."
+ --#TYPE "APC Switched Rack PDU: Cancel Pending Command made."
+ --#SUMMARY "A Cancel Pending Command has been made on a Switched Rack PDU."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 283
+
+aruAlinkCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Remote ARU Communication Established.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Communication Established."
+ --#SUMMARY "Communication Established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 284
+
+aruAlinkCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Remote ARU Communication Lost.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Communication Lost."
+ --#SUMMARY "Communication Lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 285
+
+aruFanFail TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Remote ARU Fan Fail.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Fan Fail."
+ --#SUMMARY "Fan Fail."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 286
+
+aruFanFailCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Remote ARU Fan Fail Cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Fan Fail Cleared."
+ --#SUMMARY "Fan Fail Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 287
+
+aruSmokeAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Remote ARU Smoke Alarm.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Smoke Alarm."
+ --#SUMMARY "Smoke Alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 288
+
+aruSmokeAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Remote ARU Smoke Alarm Cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Smoke Alarm Cleared."
+ --#SUMMARY "Smoke Alarm Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 289
+
+aruHighTemperatureAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Remote ARU High Temperature Alarm.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: High Temperature Alarm."
+ --#SUMMARY "High Temperature Alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 290
+
+aruHighTemperatureAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Remote ARU High Temperature Alarm Cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: High Temperature Alarm Cleared."
+ --#SUMMARY "High Temperature Alarm Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 291
+
+aruExhaustTemperatureAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Remote ARU Exhaust Temperature Alarm.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Exhaust Temperature Alarm."
+ --#SUMMARY "Exhaust Temperature Alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 292
+
+aruExhaustTemperatureAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ rARUStatusAruIndex, rARUStatusAruName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Remote ARU Exhaust Temperature Alarm Cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the ARU number.
+ The fourth argument is the ARU name."
+ --#TYPE "APC ARU: Exhaust Temperature Alarm Cleared."
+ --#SUMMARY "Exhaust Temperature Alarm Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 293
+
+envAlinkCommunicationEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Remote Probe Communication Established.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the probe number.
+ The fourth argument is the probe name."
+ --#TYPE "APC ENV: Communication Established."
+ --#SUMMARY "Communication Established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 294
+
+envAlinkCommunicationLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Remote Probe Communication Lost.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the probe number.
+ The fourth argument is the probe name."
+ --#TYPE "APC ENV: Communication Lost."
+ --#SUMMARY "Communication Lost."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 295
+
+emsAlinkPowerOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Alink Power Overload.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC EMS: Alink Power Overload."
+ --#SUMMARY "Alink Power Overload."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 296
+
+emsAlinkPowerOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Alink Power Overload Cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC EMS: Alink Power Overload Cleared."
+ --#SUMMARY "Alink Power Overload Cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 297
+
+upsOutletGroupTurnedOn TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { upsOutletGroupControlIndex, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The specified Outlet Group turned on."
+ --#TYPE "APC UPS: Outlet Group turned on."
+ --#SUMMARY "Outlet Group turned on"
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 298
+
+upsOutletGroupTurnedOff TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { upsOutletGroupControlIndex, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The specified Outlet Group turned off."
+ --#TYPE "APC UPS: Outlet Group turned off."
+ --#SUMMARY "Outlet Group turned off."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 299
+
+smwCriticalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsGauge, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A Symmetra MW UPS critical condition has been detected.
+ The first variable is the fault condition."
+ --#TYPE "APC Symmetra MW UPS: A critical condition has been detected."
+ --#SUMMARY "A critical condition has been detected."
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 300
+
+smwCriticalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsGauge, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Symmetra MW UPS critical condition has been cleared.
+ The first variable is the fault condition."
+ --#TYPE "APC Symmetra MW UPS: A critical condition has been cleared."
+ --#SUMMARY "A critical condition has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 301
+
+smwWarningCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsGauge, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Symmetra MW UPS warning condition has been detected.
+ The first variable is the fault condition."
+ --#TYPE "APC Symmetra MW UPS: A warning condition has been detected."
+ --#SUMMARY "A warning condition has been detected."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 302
+
+smwWarningConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsGauge, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Symmetra MW UPS warning condition has been cleared.
+ The first variable is the fault condition."
+ --#TYPE "APC Symmetra MW UPS: A warning condition has been cleared."
+ --#SUMMARY "A warning condition has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 303
+
+smwInformationalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsGauge, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Symmetra MW UPS informational condition has been detected.
+ The first variable is the fault condition."
+ --#TYPE "APC Symmetra MW UPS: Informational condition detected."
+ --#SUMMARY "An informational condition has been detected."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 304
+
+smwInformationalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsGauge, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Symmetra MW UPS informational condition has been cleared.
+ The first variable is the fault condition."
+ --#TYPE "APC Symmetra MW UPS: Informational condition cleared."
+ --#SUMMARY "An informational condition has been cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 305
+
+airCriticalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: An Air critical condition was detected.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC Air: A critical condition was detected. "
+ --#SUMMARY "A critical condition was detected. "
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 306
+
+airCriticalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Air critical condition was cleared.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC Air: A critical condition was cleared. "
+ --#SUMMARY "A critical condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 307
+
+airWarningCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An Air warning condition was detected.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC Air: A warning condition was detected. "
+ --#SUMMARY "A warning condition was detected. "
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 308
+
+airWarningConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An Air warning condition was cleared.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC Air: A warning condition was cleared. "
+ --#SUMMARY "A warning condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 309
+
+airInformationalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Air informational condition was detected.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC Air: Informational condition detected. "
+ --#SUMMARY "An informational condition was detected. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 310
+
+airInformationalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Air informational condition was cleared.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC Air: Informational condition was cleared. "
+ --#SUMMARY "An informational condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 311
+
+-- xPDU Traps (part 1)
+
+xPDUInputVoltageLowAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Three-phase input voltage to the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase
+ (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, from which the alarm was generated."
+ --#TYPE "APC XPDU: Main input voltage out-of-range alarm."
+ --#SUMMARY "Input voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 312
+
+xPDUInputVoltageLowAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Three-phase input voltage to the device is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XPDU: Main input voltage back in range."
+ --#SUMMARY "Input voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 313
+
+
+xPDUInputVoltageHighAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Three-phase input voltage to the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase
+ (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, above which the alarm was generated."
+ --#TYPE "APC XPDU: Main input voltage out-of-range alarm."
+ --#SUMMARY "Input voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 314
+
+xPDUInputVoltageHighAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Three-phase input voltage to the device is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XPDU: Main input voltage back in range."
+ --#SUMMARY "Input voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 315
+
+xPDUBypassVoltageLowAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Three-phase bypass input voltage to the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, from which the alarm was generated."
+ --#TYPE "APC XPDU: Bypass input voltage out-of-range alarm."
+ --#SUMMARY "Bypass input voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 316
+
+xPDUBypassVoltageLowAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Three-phase bypass input voltage to the device is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XPDU: Bypass input voltage back in range."
+ --#SUMMARY "Bypass input voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 317
+
+xPDUBypassVoltageHighAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Three-phase bypass input voltage to the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, above which the alarm was generated."
+ --#TYPE "APC XPDU: Bypass input voltage out-of-range alarm."
+ --#SUMMARY "Bypass input voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 318
+
+xPDUBypassVoltageHighAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Three-phase bypass input voltage to the device is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XPDU: Bypass input voltage back in range."
+ --#SUMMARY "Bypass input voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 319
+
+xPDUOutputVoltageLowAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The device three-phase output voltage of the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, from which the alarm was generated."
+ --#TYPE "APC XPDU: Output voltage out-of-range alarm."
+ --#SUMMARY "Output voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 320
+
+xPDUOutputVoltageLowAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output voltage is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XPDU: Output voltage back in range."
+ --#SUMMARY "Output voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 321
+
+xPDUOutputVoltageHighAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The device three-phase output voltage of the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, above which the alarm was generated."
+ --#TYPE "APC XPDU: Output voltage out-of-range alarm."
+ --#SUMMARY "Output voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 322
+
+xPDUOutputVoltageHighAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output voltage is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XPDU: Output voltage back in range."
+ --#SUMMARY "Output voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 323
+
+xPDUOutputCurrentLowAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The devices three-phase load current is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3).
+ The fourth argument is the measured current in tenths of Amps.
+ The fifth argument is the threshold, in Amps, from which the alarm was generated."
+ --#TYPE "APC XPDU: Output (load) current out-of-range alarm."
+ --#SUMMARY "Output current is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 324
+
+xPDUOutputCurrentLowAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output current is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3).
+ The fourth argument is the measured current in tenths of Amps."
+ --#TYPE "APC XPDU: Output (load) current back in range."
+ --#SUMMARY "Output current in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 325
+
+xPDUOutputCurrentHighAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The devices three-phase load current is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3).
+ The fourth argument is the measured current in tenths of Amps.
+ The fifth argument is the threshold, in Amps, above which the alarm was generated."
+ --#TYPE "APC XPDU: Output (load) current out-of-range alarm."
+ --#SUMMARY "Output current is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 326
+
+xPDUOutputCurrentHighAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output current is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3).
+ The fourth argument is the measured current in tenths of Amps."
+ --#TYPE "APC XPDU: Output (load) current back in range."
+ --#SUMMARY "Output current in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 327
+
+xPDUOutputFrequencyAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The devices output frequency is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the frequency deviation from the nominal in tenths of Hertz."
+ --#TYPE "APC XPDU: Output frequency out-of-range alarm."
+ --#SUMMARY "Output frequency is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 328
+
+xPDUOutputFrequencyAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices output frequency is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Output frequency back in range."
+ --#SUMMARY "Output frequency in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 329
+
+xPDUSystemGroundCurrentAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The devices earth ground current is over the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the measured current in tenths of Amps."
+ --#TYPE "APC XPDU: Earth ground current over range alarm."
+ --#SUMMARY "Earth ground current is over limit."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 330
+
+xPDUSystemGroundCurrentAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices earth ground current is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the measured current in tenths of Amps."
+ --#TYPE "APC XPDU: Earth ground current back in range."
+ --#SUMMARY "Earth ground current in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 331
+
+xPDUInputContactStateAbnormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsString02, mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A user input contact on the device has changed to its abnormal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the input contact number.
+ The fourth argument is the input contact name.
+ The fifth argument is the input contact state (1=OPEN, 2=CLOSED).
+ The sixth argument is the configured normal input contact state (1=OPEN, 2=CLOSED)."
+ --#TYPE "APC XPDU: Input contact has changed to its abnormal state."
+ --#SUMMARY "Input contact has changed to its abnormal state."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 332
+
+xPDUInputContactStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsString02, mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A user input contact on the device has changed to its normal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the input contact number.
+ The fourth argument is the input contact name.
+ The fifth argument is the input contact state (1=CLOSED, 2=OPEN).
+ The sixth argument is the configured normal input contact state (1=OPEN, 2=CLOSED)."
+ --#TYPE "APC XPDU: Input contact has changed to its normal state."
+ --#SUMMARY "Input contact has changed to its normal state."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 333
+
+xPDUOutputRelayStateAbnormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsString02, mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "WARNING: An Output Relay on the device has changed to its abnormal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the Output Relay number.
+ The fourth argument is the Output Relay name.
+ The fifth argument is the current Output Relay state (1=OPEN, 2=CLOSED).
+ The sixth argument is the configured normal Output Relay state (1=OPEN, 2=CLOSED)."
+ --#TYPE "APC XPDU: Output Relay has changed to its abnormal state."
+ --#SUMMARY "Output Relay has changed to its abnormal state."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 334
+
+xPDUOutputRelayStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsString02, mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: An Output Relay on the device has changed to its normal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the Output Relay number.
+ The fourth argument is the Output Relay name.
+ The fifth argument is the current Output Relay state (1=OPEN, 2=CLOSED).
+ The sixth argument is the configured normal Output Relay state (1=OPEN, 2=CLOSED)."
+ --#TYPE "APC XPDU: Output Relay has changed to its normal state."
+ --#SUMMARY "Output Relay has changed to its normal state."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 335
+
+xPDUCoolingFanAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The device's internal cooling fans have failed.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Cooling fan failure alarm."
+ --#SUMMARY "Cooling fan failure."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 336
+
+xPDUCoolingFanAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The device's cooling fans are now functioning properly.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Cooling fan alarm cleared."
+ --#SUMMARY "Cooling fan alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 337
+
+xPDUTransformerTempAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The device's isolation transformer is over temperature.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Isolation transformer over temperature alarm."
+ --#SUMMARY "Transformer temp alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 338
+
+xPDUTransformerTempAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The device's isolation transformer is no longer over temperature.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Isolation transformer over temperature alarm cleared."
+ --#SUMMARY "Transformer temp alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 339
+
+xPDUBranchCurrentLowAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The current in a branch circuit is outside the limits specified for that
+ branch circuit.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the panel position of the branch circuit (1-based index).
+ The fourth argument is the measured current in tenths of Amps.
+ The fifth argument is the threshold, in tenth of Amps, from which the alarm was generated."
+ --#TYPE "APC XPDU: Branch circuit current out-of-range alarm."
+ --#SUMMARY "Branch circuit current is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 340
+
+xPDUBranchCurrentLowAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The current in a branch circuit is back within the limits
+ specified for that branch circuit.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the panel position of the branch circuit (1-based index).
+ The fourth argument is the measured current in tenths of Amps."
+ --#TYPE "APC XPDU: Branch circuit current back in range."
+ --#SUMMARY "Branch circuit current in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 341
+
+xPDUBranchCurrentHighAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The current in a branch circuit is outside the limits specified for that
+ branch circuit.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the panel position of the branch circuit (1-based index).
+ The fourth argument is the measured current in tenths of Amps.
+ The fifth argument is the threshold, in tenth of Amps, above which the alarm was generated."
+ --#TYPE "APC XPDU: Branch circuit current out-of-range alarm."
+ --#SUMMARY "Branch circuit current is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 342
+
+xPDUBranchCurrentHighAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The current in a branch circuit is back within the limits
+ specified for that branch circuit.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the panel position of the branch circuit (1-based index).
+ The fourth argument is the measured current in tenths of Amps."
+ --#TYPE "APC XPDU: Branch circuit current back in range."
+ --#SUMMARY "Branch circuit current in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 343
+
+
+xPDUInternalCommError TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: There is an internal communication error in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Internal communication error."
+ --#SUMMARY "Internal communication error."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 344
+
+emsHardwareStateAbnormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The device's hardware is improperly configured and operating outside
+ normal bounds for the hardware. This can be caused by improper devices being
+ connected to the EMS ports or Alink Current limit detection."
+ --#TYPE "APC EMS: Hardware is in an abnormal state."
+ --#SUMMARY "Hardware is in an abnormal state."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 345
+
+emsHardwareStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The device's hardware is in its normal operational state.
+ The first argument is the host device serial number."
+ --#TYPE "APC EMS: Hardware is in a normal state."
+ --#SUMMARY "Hardware is in its normal state."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 346
+
+ceSevereCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A Custom Event severe condition was detected.
+ The first variable is the custom event text message.
+ The second variable is the custom event number."
+ --#TYPE "APC CustomEvent: A severe condition was detected. "
+ --#SUMMARY "A severe condition was detected. "
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 347
+
+ceSevereConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Custom Event severe condition was cleared.
+ The first variable is the custom event text message.
+ The second variable is the custom event number."
+ --#TYPE "APC CustomEvent: A severe condition was cleared. "
+ --#SUMMARY "A severe condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 348
+
+ceWarningCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Custom Event warning condition was detected.
+ The first variable is the custom event text message.
+ The second variable is the custom event number."
+ --#TYPE "APC CustomEvent: A warning condition was detected. "
+ --#SUMMARY "A warning condition was detected. "
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 349
+
+ceWarningConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Custom Event warning condition was cleared.
+ The first variable is the custom event text message.
+ The second variable is the custom event number."
+ --#TYPE "APC CustomEvent: A warning condition was cleared. "
+ --#SUMMARY "A warning condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 350
+
+ceInformationalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Custom Event informational condition was detected.
+ The first variable is the custom event text message.
+ The second variable is the custom event number."
+ --#TYPE "APC CustomEvent: Informational condition detected. "
+ --#SUMMARY "An informational condition was detected. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 351
+
+ceInformationalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Custom Event informational condition was cleared.
+ The first variable is the custom event text message.
+ The second variable is the custom event number."
+ --#TYPE "APC CustomEvent: Informational condition was cleared. "
+ --#SUMMARY "An informational condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 352
+
+upsInternalOverTemperature TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "WARNING: The internal over temperature condition exists."
+ --#TYPE "APC UPS: The internal over temperature condition exists."
+ --#SUMMARY "The internal over temperature condition exists."
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 353
+
+upsInternalOverTemperatureCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The internal over temperature condition cleared."
+ --#TYPE "APC UPS: The internal over temperature condition cleared."
+ --#SUMMARY "The internal over temperature condition cleared."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 354
+
+upsMpuReset TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The MPU has been reset."
+ --#TYPE "APC UPS: The MPU has been reset."
+ --#SUMMARY "The MPU has been reset."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 355
+
+upsOutputSwitchClosed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The Output Switch is closed."
+ --#TYPE "APC UPS: The Output Switch is closed."
+ --#SUMMARY "The Output Switch is closed."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 356
+
+upsOutputSwitchOpened TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The Output Switch is open."
+ --#TYPE "APC UPS: The Output Switch is open."
+ --#SUMMARY "The Output Switch is open."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 357
+
+upsCalibrationStackChanged TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A calibration value in the stack was changed."
+ --#TYPE "APC UPS: A calibration value in the stack was changed."
+ --#SUMMARY "A calibration value in the stack was changed."
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 358
+
+
+-- Upgraded EMS now has more env traps
+
+envMaxTempThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Max temperature threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Max temperature threshold violation."
+ --#SUMMARY "Max temperature threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 359
+
+envMaxTempThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Max temperature threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Max temperature threshold violation cleared."
+ --#SUMMARY "Max temperature threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 360
+
+envMinTempThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Min temperature threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Min temperature threshold violation."
+ --#SUMMARY "Min temperature threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 361
+
+envMinTempThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Min temperature threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Min temperature threshold violation cleared."
+ --#SUMMARY "Min temperature threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 362
+
+envMaxHumidityThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Max humidity threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: Max humidity threshold violation."
+ --#SUMMARY "Max humidity threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 363
+
+envMaxHumidityThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Max humidity threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity.
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: Max humidity threshold violation cleared."
+ --#SUMMARY "Max humidity threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 364
+
+envMinHumidityThresholdViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Min humidity threshold violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: Min humidity threshold violation."
+ --#SUMMARY "Min humidity threshold violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 365
+
+envMinHumidityThresholdViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeHumidity,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Min humidity threshold violation cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current humidity.
+ The fourth argument is the probe number.
+ The fifth argument is the probe name."
+ --#TYPE "APC ENV: Min humidity threshold violation cleared."
+ --#SUMMARY "Min humidity threshold violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 366
+
+envSTIncTempRateViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Short-term increasing temperature rate violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Short-term inc. temp rate violation."
+ --#SUMMARY "Short-term inc. temp rate violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 367
+
+envSTIncTempRateViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Short-term increasing temperature rate cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Short-term inc. temp rate violation cleared."
+ --#SUMMARY "Short-term inc. temp rate violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 368
+
+envSTDecTempRateViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Short-term decreasing temperature rate violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Short-term dec. temp rate violation."
+ --#SUMMARY "Short-term dec. temp rate violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 369
+
+envSTDecTempRateViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Short-term decreasing temperature rate cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Short-term dec. temp rate violation cleared."
+ --#SUMMARY "Short-term dec. temp rate violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 370
+
+envLTIncTempRateViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Long-term increasing temperature rate violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Long-term inc. temp rate violation."
+ --#SUMMARY "Long-term inc. temp rate violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 371
+
+envLTIncTempRateViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Long-term increasing temperature rate cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Long-term inc. temp rate violation cleared."
+ --#SUMMARY "Long-term inc. temp rate violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 372
+
+envLTDecTempRateViolation TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Long-term decreasing temperature rate violated on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Long-term dec. temp rate violation."
+ --#SUMMARY "Long-term dec. temp rate violation."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 373
+
+envLTDecTempRateViolationCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { emsIdentSerialNumber, emsIdentEMSName, emsProbeStatusProbeTemperature, emsStatusSysTempUnits,
+ emsProbeStatusProbeIndex, emsProbeStatusProbeName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Long-term decreasing temperature rate cleared on the probe.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the current temperature.
+ The fourth argument is the temperature scale.
+ The fifth argument is the probe number.
+ The sixth argument is the probe name."
+ --#TYPE "APC ENV: Long-term dec. temp rate violation cleared."
+ --#SUMMARY "Long-term dec. temp rate violation cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 374
+
+-- Battery Management System Traps
+
+bmsCriticalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A Battery Management System critical condition was detected.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC BMS: A critical condition was detected. "
+ --#SUMMARY "A critical condition was detected. "
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 375
+
+bmsCriticalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Battery Management System critical condition was cleared.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC BMS: A critical condition was cleared. "
+ --#SUMMARY "A critical condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 376
+
+bmsWarningCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Battery Management System warning condition was detected.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC BMS: A warning condition was detected. "
+ --#SUMMARY "A warning condition was detected. "
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 377
+
+bmsWarningConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: A Battery Management System warning condition was cleared.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC BMS: A warning condition was cleared. "
+ --#SUMMARY "A warning condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 378
+
+bmsInformationalCondition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Battery Management System informational condition was detected.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC BMS: Informational condition detected. "
+ --#SUMMARY "An informational condition was detected. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 379
+
+bmsInformationalConditionCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsString02, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A Battery Management System informational condition was cleared.
+ The first variable is the error condition text message.
+ The second variable is the error number."
+ --#TYPE "APC BMS: Informational condition was cleared. "
+ --#SUMMARY "An informational condition was cleared. "
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 380
+
+-- xATS Traps
+
+xATSOutputVoltageLowAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The device three-phase output voltage of the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, from which the alarm was generated."
+ --#TYPE "APC XATS: Output voltage out-of-range alarm."
+ --#SUMMARY "Output voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 381
+
+xATSOutputVoltageLowAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output voltage is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XATS: Output voltage back in range."
+ --#SUMMARY "Output voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 382
+
+xATSOutputVoltageHighAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The device three-phase output voltage of the device is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts.
+ The fifth argument is the threshold, in tenths of Volts, above which the alarm is generated."
+ --#TYPE "APC XATS: Output voltage out-of-range alarm."
+ --#SUMMARY "Output voltage is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 383
+
+xATSOutputVoltageHighAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output voltage is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1-N, 2=L2-N, 3=L3-N, 4=unused, 5=L1-L2, 6=L2-L3, 7=L3-L1).
+ The fourth argument is the measured voltage in tenths of Volts."
+ --#TYPE "APC XATS: Output voltage back in range."
+ --#SUMMARY "Output voltage in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 384
+
+xATSOutputCurrentLowAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The devices three-phase load current is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3, 4=Neutral, 5=L1-2, 6=L2-3, 7=L3-1).
+ The fourth argument is the measured current in Amps.
+ The fifth argument is the threshold, in Amps, from which the alarm was generated."
+ --#TYPE "APC XATS: Output (load) current out-of-range alarm."
+ --#SUMMARY "Output current is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 385
+
+xATSOutputCurrentLowAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output current is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3, 4=Neutral).
+ The fourth argument is the measured current in Amps."
+ --#TYPE "APC XATS: Output (load) current back in range."
+ --#SUMMARY "Output current in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 386
+
+xATSOutputCurrentHighAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The devices three-phase load current is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3, 4=Neutral).
+ The fourth argument is the measured current in Amps.
+ The fifth argument is the threshold, in Amps, from which the alarm was generated."
+ --#TYPE "APC XATS: Output (load) current out-of-range alarm."
+ --#SUMMARY "Output current is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 387
+
+xATSOutputCurrentHighAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices three-phase output current is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3, 4=Neutral).
+ The fourth argument is the measured current in Amps."
+ --#TYPE "APC XATS: Output (load) current back in range."
+ --#SUMMARY "Output current in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 388
+
+
+xATSOutputFrequencyAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The devices output frequency is outside the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the frequency deviation from the nominal in tenths of Hertz.
+ The fourth argument is the frequency deviation threshold in tenths of Hertz,
+ from which the alarm was generated."
+ --#TYPE "APC XATS: Output frequency out-of-range alarm."
+ --#SUMMARY "Output frequency is out-of-range."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 389
+
+xATSOutputFrequencyAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The devices output frequency is back within the specified limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Output frequency back in range."
+ --#SUMMARY "Output frequency in range."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 390
+
+xATSInternalCommError TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: There is an internal communication error in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Internal communication error."
+ --#SUMMARY "Internal communication error."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 391
+
+xATSInternalCommErrorCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Internal communication has been restored.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Internal Communication error cleared."
+ --#SUMMARY "ATS Communication error cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 392
+
+xATSDataCommMismatchError TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A data incompatibility exists within the device. This
+ is typically the result of mismatches between firmware revisions
+ of the transfer switch controller and the Network Management interface.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Data mismatch error."
+ --#SUMMARY "ATS data mismatch error."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 393
+
+xATSDataCommMismatchErrorCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The internal data incompatibility has been resolved.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: data mismatch error cleared."
+ --#SUMMARY "ATS data mismatch error cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 394
+
+xATSGenCommLost TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The XATS cannot communicate with the generator.
+ This will make unavailable all the xATSGenerator OIDs.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: No communication with generator."
+ --#SUMMARY "ATS/Generator communication lost."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 395
+
+xATSGenCommEstablished TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The XATS has established communication with the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Communication with generator established."
+ --#SUMMARY "ATS/generator communication established."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 396
+
+xATSNeutralPosition TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsString }
+ DESCRIPTION
+ "WARNING: XATS has transferred to neutral position.
+ In this position neither Source 1 nor Source 2 is selected,
+ and the XATS will have no output voltage.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the mode in which the switch is operating
+ (1=Auto, 2=Not-in-Auto, Abnormal Condition 3=Not-in-Auto, manual)."
+ --#TYPE "APC XATS: Transferred to the neutral (no output power) position."
+ --#SUMMARY "Transferred to neutral."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 397
+
+xATSSwitchTransferEvent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: XATS has transferred from one source to the other.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the mode in which the switch is operating.
+ (1=Auto, 2=Not-in-Auto, Abnormal Condition 3=Not-in-Auto, manual).
+ The fourth argument is the input source selected (1=Source 1, 2=Source 2).
+ The fifth argument is type of transfer that took place. (1=Closed, 2=Open, 3=Unknown)"
+ --#TYPE "APC XATS: Transferred from Source-X to Source-Y."
+ --#SUMMARY "Source-to-Source transfer."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 398
+
+xATSInternalATSFault TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: An internal XATS fault has been detected.
+ The XATS may have forced itself to not-in-auto mode (abnormal condition),
+ as indicated by the xATSSwitchStatusAutoSwitchOperationalMode OID.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument indicates the detected fault.
+
+ 1=Cannot Close S1
+ 2=Cannot Close S2
+ 3=Cannot Open S1
+ 4=Cannot Open S2
+ 5=Cannot Trip Open S1
+ 6=Cannot Trip Open S2
+ 7=Start Contact Failure
+ 8=Voltage Sensing Failure"
+
+ --#TYPE "APC XATS: Internal fault detected."
+ --#SUMMARY "ATS internal fault detected."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 399
+
+xATSInternalATSFaultCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected internal XATS fault has been cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument indicates the detected fault.
+
+ 1=Cannot Close S1
+ 2=Cannot Close S2
+ 3=Cannot Open S1
+ 4=Cannot Open S2
+ 5=Cannot Trip Open S1
+ 6=Cannot Trip Open S2
+ 7=Start Contact Failure
+ 8=Voltage Sensing Failure"
+
+ --#TYPE "APC XATS: Internal fault cleared."
+ --#SUMMARY "ATS internal fault cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 400
+
+xATSEngineStartAsserted TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The XATS has asserted the Engine Start contact.
+ This should result in the generator producing output voltage.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument indicates the reason that the start signal was asserted
+ 1=Unknown, 2=S1 Low Voltage, 3=S1 High Voltage, 4=S1 Line Imbalance,
+ 5=S1 Freq Range, 6=S1 Bad Rotation."
+ --#TYPE "APC XATS: Engine Start signal asserted."
+ --#SUMMARY "Engine Start asserted."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 401
+
+xATSEngineStopAsserted TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The XATS has de-asserted the Engine Start contact.
+ This should result in the generator shutting down, and producing no output voltage.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Engine Stop signal asserted."
+ --#SUMMARY "Engine Stop asserted."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 402
+
+xATSStartFailure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator failed to start. After assertion of the
+ Engine Start signal, the quality of Source 2 was not seen as good.
+ This alarm can be cleared using the xATSSwitchStatusClearLatchedAlarms OID.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument indicates the line quality at S2
+ 1=Unknown, 2=S2 Low Voltage, 3=S2 High Voltage, 4=S2 Line Imbalance,
+ 4=S2 Freq Range, 5=S2 Bad Rotation."
+ --#TYPE "APC XATS: Generator failed to start alarm."
+ --#SUMMARY "Generator failed to start."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 403
+
+xATSStopFailure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The generator failed to stop. After de-assertion of the
+ Engine Start signal, the quality of Source 2 continued to be seen as good.
+ This alarm can be cleared using the xATSSwitchStatusClearLatchedAlarms OID.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Generator failed to stop alarm."
+ --#SUMMARY "Generator failed to stop."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 404
+
+xATSNotInAutomaticMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Automatic Transfer Switch is not in automatic mode.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The xATSSwitchStatusAutoSwitchStatus OID and the
+ xATSSwitchStatusAutoSwitchOperationalMode OID
+ can provide more information about the state of the XATS."
+ --#TYPE "APC XATS: XATS is not-in-automatic mode."
+ --#SUMMARY "ATS not in auto."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 405
+
+xATSNotInAutomaticModeCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Automatic Transfer Switch is in automatic mode.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: XATS in auto mode."
+ --#SUMMARY "ATS in auto mode."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 406
+
+xATSEpoTripped TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The device's Emergency Power Off (EPO) circuit is tripped.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Emergency Power Off (EPO) tripped."
+ --#SUMMARY "EPO tripped."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 407
+
+xATSEpoReset TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The device's Emergency Power Off (EPO) circuit has been
+ reset to the armed position.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Emergency Power Off (EPO) reset."
+ --#SUMMARY "EPO armed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 408
+
+xATSEpoTestMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The device's Emergency Power Off (EPO) circuit has been
+ switched back to the test position.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Emergency Power Off (EPO) in test mode."
+ --#SUMMARY "EPO disabled."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 409
+
+xATSEpoArmed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The device's Emergency Power Off (EPO) circuit has been
+ switched back to the armed position.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Emergency Power Off (EPO) enabled."
+ --#SUMMARY "EPO armed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 410
+
+xATSTestInitiated TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A scheduled test has been initiated.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the type of test initiated (1=scheduled, 2=manual)."
+ --#TYPE "APC XATS: Test initiated."
+ --#SUMMARY "Test initiated."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 411
+
+xATSTestCancelled TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The scheduled test has been canceled
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the type of test initiated (1=scheduled, 2=manual)."
+ --#TYPE "APC XATS: Test cancelled."
+ --#SUMMARY "Test cancelled."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 412
+
+xATSTestFailed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The initiated test has failed.
+ This alarm can be cleared using the xATSSwitchStatusClearLatchedAlarms OID.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Initiated test failed."
+ --#SUMMARY "Initiated test failed."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 413
+
+xATSTestPassed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The initiated test has passed
+ switched back to the armed position.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Initiated test passed."
+ --#SUMMARY "Initiated test passed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 414
+
+xATSInputContactStateAbnormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsString02, mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A user input contact on the device has changed to its abnormal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the input contact number.
+ The fourth argument is the input contact name.
+ The fifth argument is the input contact state (1=OPEN, 2=CLOSED).
+ The sixth argument is the configured normal input contact state (1=OPEN, 2=CLOSED)."
+ --#TYPE "APC XATS: Input contact has changed to its abnormal state."
+ --#SUMMARY "Input contact has changed to its abnormal state."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 415
+
+xATSInputContactStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger,
+ mtrapargsString02, mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A user input contact on the device has changed to its normal state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the input contact number.
+ The fourth argument is the input contact name.
+ The fifth argument is the input contact state (1=OPEN, 2=CLOSED).
+ The sixth argument is the configured normal input contact state (1=OPEN, 2=CLOSED)."
+ --#TYPE "APC XATS: Input contact has changed to its normal state."
+ --#SUMMARY "Input contact has changed to its normal state."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 416
+
+xATSRemoteStartContactMismatch TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The state of the generator's Remote Start input
+ and the ATS's Engine Start output do not match.
+ This indicates something wrong in the Engine Start wiring,
+ which must be corrected. This condition will prevent the
+ generator from being started when needed.
+
+ (See also: xATSGeneratorStatusRemoteStart
+ and xATSSwitchStatusEngineStartSignal OIDs)
+
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Generator/ATS start contact mismatch."
+ --#SUMMARY "Generator/ATS start contact mismatch."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 417
+
+xATSRemoteStartContactMismatchCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Mismatch in the state of the generator's
+ Remote Start input and the ATS's Engine Start output as been resolved.
+ This indicates something wrong in the Engine Start wiring,
+ which must be corrected. This condition will prevent the
+ generator from being started when needed.
+
+ (See also: xATSGeneratorStatusRemoteStart
+ and xATSSwitchStatusEngineStartSignal OIDs)
+
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Generator/ATS start contact mismatch cleared."
+ --#SUMMARY "Generator/ATS start contact mismatch cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 418
+
+xATSDoorOpenAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The XATS exterior panel door is open.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Panel door is open alarm."
+ --#SUMMARY "Panel door open alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 419
+
+xATSDoorOpenAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The external door to the device is closed.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Panel door open alarm cleared."
+ --#SUMMARY "Panel door open alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 420
+
+xATSDCBackupAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The XATS's DC backup has been lost. The XATS will lose power
+ on Source 1 failure, causing the Engine Start signal to be asserted.
+ The XATS will then restart from Source 2.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: DC backup failure."
+ --#SUMMARY "ATS DC backup failure."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 421
+
+xATSDCBackupAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: DC backup alarm has been cleared in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: DC backup alarm cleared."
+ --#SUMMARY "DC backup alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 422
+
+-- xATS Generator Traps
+
+xATSGeneratorLowCoolantLevelAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Low coolant level has been detected in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low coolant level alarm."
+ --#SUMMARY "Generator low coolant level alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 423
+
+xATSGeneratorLowCoolantLevelAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected low coolant level has been cleared in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low coolant level alarm cleared."
+ --#SUMMARY "Generator low coolant level alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 424
+
+xATSGeneratorVeryLowCoolantLevelAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Very low coolant level has been detected in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator very low coolant level alarm."
+ --#SUMMARY "Generator very low coolant level alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 425
+
+xATSGeneratorVeryLowCoolantLevelAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected Very low coolant level has been cleared in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator very low coolant level alarm cleared."
+ --#SUMMARY "Generator very low coolant level alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 426
+
+xATSGeneratorHighCoolantTempAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: High coolant temperature has been detected in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator high coolant temperature alarm."
+ --#SUMMARY "Generator high coolant temperature alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 427
+
+xATSGeneratorHighCoolantTempAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected high coolant temperature has been cleared in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator high coolant temperature alarm cleared."
+ --#SUMMARY "Generator high coolant temperature alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 428
+
+xATSGeneratorVeryHighCoolantTempAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Very high coolant temperature has been detected in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator very high coolant temperature alarm."
+ --#SUMMARY "Generator very high coolant temperature alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 429
+
+xATSGeneratorVeryHighCoolantTempAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The Very high coolant temperature condition has been cleared in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator very high coolant temperature alarm cleared."
+ --#SUMMARY "Generator very high coolant temperature alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 430
+
+xATSGeneratorLowCoolantTempAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Low coolant temperature has been detected in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low coolant temperature alarm."
+ --#SUMMARY "Generator low coolant temperature alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 431
+
+xATSGeneratorLowCoolantTempAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The low coolant temperature condition has been cleared in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low coolant temperature alarm cleared."
+ --#SUMMARY "Generator low coolant temperature alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 432
+
+xATSGeneratorLowOilLevelAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Low oil level has been detected in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low oil level alarm."
+ --#SUMMARY "Generator low oil level alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 433
+
+xATSGeneratorLowOilLevelAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Low oil level alarm has been cleared in the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low oil level alarm cleared."
+ --#SUMMARY "Generator low oil level alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 434
+
+xATSGeneratorLowBatteryVoltDuringCrankAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator's battery voltage has been detected
+ as low while cranking the engine.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Low batt. voltage while cranking alarm."
+ --#SUMMARY "Generator low battery volts while cranking alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 435
+
+xATSGeneratorLowBatteryVoltDuringCrankAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator's low battery voltage while
+ cranking condition has been cleared.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "XGEN: Generator low batt. voltage while cranking alarm cleared."
+ --#SUMMARY "Generator low battery volts while cranking alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 436
+
+xATSGeneratorVeryLowBatteryVoltDuringCrankAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator's battery voltage has been detected
+ as very low while cranking the engine.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "XGEN: Generator v.low battery voltage while cranking alarm."
+ --#SUMMARY "Generator v.low battery volts while cranking alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 437
+
+xATSGeneratorVeryLowBatteryVoltDuringCrankAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator's high battery voltage while
+ cranking condition has been cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "XGEN: Generator v.low batt volt, while cranking alarm cleared."
+ --#SUMMARY "Generator v.low battery volts while cranking alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 438
+
+xATSGeneratorEStop TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator's emergency stop input has been activated.
+ After the emergency stop signal has been removed, the E-Stop condition
+ must be cleared before the generator can be started again.
+ E-Stop conditions can only be cleared via the generator front panel.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code.
+ The fourth argument is the type of E-Stop (1=LOCAL, 2=REMOTE)."
+ --#TYPE "APC XGEN: Generator emergency stop engaged."
+ --#SUMMARY "Generator emergency stop engaged."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE NONOPERATIONAL
+ ::= 439
+
+xATSGeneratorEStopCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator's emergency stop condition has been cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code.
+ The fourth argument is the type of E-Stop (1=LOCAL, 2=REMOTE)."
+ --#TYPE "APC XGEN: Generator emergency stop condition cleared."
+ --#SUMMARY "Generator emergency stop condition cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 440
+
+xATSGeneratorHighBatteryVolt TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The generator's battery voltage has been detected as high.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator high battery voltage."
+ --#SUMMARY "Generator high battery volts."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 441
+
+xATSGeneratorHighBatteryVoltCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected high battery voltage has been cleared, on the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator high battery voltage condition cleared."
+ --#SUMMARY "Generator high battery volts condition cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 442
+
+xATSGeneratorLowBatteryVolt TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator's battery voltage has been detected as low.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low battery voltage."
+ --#SUMMARY "Generator low battery volts."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 443
+
+xATSGeneratorLowBatteryVoltCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected low battery voltage has been cleared, on the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low battery voltage condition cleared."
+ --#SUMMARY "Generator low battery volts condition cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 444
+
+xATSGeneratorControlSwitchNotAuto TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The control switch on the generator is not in auto position.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator not-in-automatic mode."
+ --#SUMMARY "Generator not-in-auto."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 445
+
+xATSGeneratorControlSwitchNotAutoCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The control switch on the generator is in auto position.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator automatic mode restored."
+ --#SUMMARY "Generator not-in-auto cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 446
+
+xATSGeneratorLowOilPressure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator's oil pressure has been detected as low.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low oil pressure."
+ --#SUMMARY "Generator low oil pressure."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 447
+
+xATSGeneratorLowOilPressureCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected low oil pressure has been cleared, on the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator low oil pressure condition cleared."
+ --#SUMMARY "Generator low oil pressure condition cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 448
+
+xATSGeneratorVeryLowOilPressure TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator's oil pressure has been detected as very low.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator v.low oil pressure."
+ --#SUMMARY "Generator v.low oil pressure."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 449
+
+xATSGeneratorVeryLowOilPressureCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected v.low oil pressure has been cleared, on the generator.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator v.low oil pressure condition cleared."
+ --#SUMMARY "Generator v.low oil pressure condition cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 450
+
+xATSGeneratorOverload TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator is overloaded.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator is in overload event."
+ --#SUMMARY "Generator on overload event."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 451
+
+xATSGeneratorOverloadCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator is running within loading limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator is in overload event cleared."
+ --#SUMMARY "Generator on overload event cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 452
+
+xATSGeneratorLowACVEvent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator AC voltage is outside the acceptable bounds.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: State of the Generator ac voltage."
+ --#SUMMARY " State of the Generator ac voltage."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 453
+
+xATSGeneratorLowACVEventCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator AC voltage is within normal bounds.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: State of the Generator ac voltage cleared."
+ --#SUMMARY "State of the Generator ac voltage cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 454
+
+xATSGeneratorHighACVEvent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator AC voltage is outside the acceptable bounds.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: State of the Generator ac voltage."
+ --#SUMMARY " State of the Generator ac voltage."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 455
+
+xATSGeneratorHighACVEventCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator AC voltage is within normal bounds.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: State of the Generator ac voltage cleared."
+ --#SUMMARY "State of the Generator ac voltage cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 456
+
+xATSGeneratorOverspeed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator is running over the acceptable RPM.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator overspeed condition."
+ --#SUMMARY "Generator overspeed condition."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 457
+
+xATSGeneratorOverspeedCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator overspeed shutdown has been cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator overspeed condition cleared."
+ --#SUMMARY "Generator overspeed condition cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 458
+
+xATSGeneratorEngineCold TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator engine is cold, may not start.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator engine is cold, may not start."
+ --#SUMMARY "Generator engine is cold."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 459
+
+xATSGeneratorEngineColdCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The engine is not cold to start.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Engine is cold to start condition cleared."
+ --#SUMMARY "Engine is cold to start condition cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 460
+
+xATSGeneratorOutputBreakerOpen TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generators output breaker has been detected as open.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator output breaker open alarm."
+ --#SUMMARY "Generator output breaker open."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE NONOPERATIONAL
+ ::= 461
+
+xATSGeneratorOutputBreakerOpenCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The engine is not cold to start.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator output breaker open alarm cleared."
+ --#SUMMARY "Generator output breaker open cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 462
+
+xATSGeneratorLowFuelLevelAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The tank fuel level is below the limits specified
+ in the xATSGeneratorFuelSystemLowFuelLevelThreshold OID.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the measured fuel level in percent of full."
+ --#TYPE "APC XGEN: Low fuel level alarm."
+ --#SUMMARY "Generator low fuel level alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 463
+
+xATSGeneratorLowFuelLevelAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The tank fuel level is back above the specified limit.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XGEN: Low fuel level alarm cleared."
+ --#SUMMARY "Generator low fuel level alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 464
+
+xATSGeneratorVeryLowFuelLevelAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The tank fuel level is below the low threshold limits.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the measured tank fuel level in percent of full."
+ --#TYPE "APC XGEN: Very Low fuel level alarm."
+ --#SUMMARY "Generator very low fuel level alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 465
+
+xATSGeneratorVeryLowFuelLevelAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected low tank level has been cleared in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XGEN: Very low fuel level alarm cleared."
+ --#SUMMARY "Generator very low fuel level alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 466
+
+xATSGeneratorLowRunTimeAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The estimated runtime is below the limits specified.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the estimated runtime in hours."
+ --#TYPE "APC XGEN: Low run time alarm."
+ --#SUMMARY "Generator low run time alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 467
+
+xATSGeneratorLowRunTimeAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected low runtime has been cleared in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XGEN: Low run time alarm cleared."
+ --#SUMMARY "Generator low run time alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 468
+
+xATSGeneratorVeryLowRunTimeAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The estimated runtime is below the limits specified
+ in the xATSGeneratorFuelSystemVeryLowRunTimeThreshold OID.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the estimated runtime in hours."
+ --#TYPE "APC XGEN: Very low run time alarm."
+ --#SUMMARY "Generator very low run time alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 469
+
+xATSGeneratorVeryLowRunTimeAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The detected low runtime has been cleared in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XGEN: Very low run time alarm cleared."
+ --#SUMMARY "Generator very low run time alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 470
+
+xATSGeneratorServiceDueAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The generator is due for scheduled service.
+ Generation of this alarm is based on calender days since
+ and/or actual generator run-hours since last service.
+ This alarm is cleared using the xATSGeneratorServiceResetRecord OID.
+
+ (See also: xATSGeneratorServiceCalendarIntervalThreshold
+ and xATSGeneratorServiceRunHoursThreshold OIDs)
+
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Generator scheduled maintenance is due."
+ --#SUMMARY "Generator maintenance due."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 471
+
+xATSGeneratorServiceDueAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator's service registers have been reset.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Generator service due alarm is cleared."
+ --#SUMMARY "Generator service alarm is cleard."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 472
+
+xATSGeneratorShutdown TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator is shutdown.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator shutdown."
+ --#SUMMARY "Generator shutdown"
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 473
+
+xATSGeneratorShutdownCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The generator shutdown alarm is cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator shutdown is cleared."
+ --#SUMMARY "Generator shutdown is cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 474
+
+xATSGeneratorBatteryCharger TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: The generator battery charger is nonfunctional.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator batt. charger is nonfunctional."
+ --#SUMMARY "Generator battery charger is nonfunctional"
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 475
+
+xATSGeneratorBatteryChargerCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: nonfunctionality of the generator battery is cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: " Nonfunctionality of battery charger is cleared."
+ --#SUMMARY "non-functionality of Generator battery charger is cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 476
+
+xATSGeneratorGenericEvent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: Any generic generator event.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generator generic event."
+ --#SUMMARY "Generator generic event."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 477
+
+xATSGeneratorGenericEventCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xATSIdentSerialNumber, xATSIdentProductName, mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Generated generic generator event is cleared.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the OEM's fault/event code."
+ --#TYPE "APC XGEN: Generic generator event is cleared."
+ --#SUMMARY "Generic generator event is cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 478
+
+-- xPDU Traps (part 2)
+
+xPDUInternalCommErrorCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Internal communication has been restored.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Internal Communication error cleared."
+ --#SUMMARY "Communication error cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 479
+
+xPDUSystemStateAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName,
+ mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The PDU's breakers (Q1, Q2 & Q3) are in a configuration that might lead
+ to system unavailability. it may signify a temporary condition, when the breakers
+ are placed in an atypical manner as the user transitions to (UPS OPERATION or MAINTENANCE BYPASS)
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the type of alarm
+ (1=NO UPS INPUT, 2=NO PANEL FEED, 3=ATYPICAL BYPASS MODE)."
+ --#TYPE "APC XPDU: System state alarm ."
+ --#SUMMARY "PDU state alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 480
+
+xPDUSystemStateNormal TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName,
+ mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The PDU's breakers (Q1, Q2 & Q3) are set in a configuration
+ that is a non-alarm state.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the type of alarm (1=UPS OPERATION, 2=MAINTENANCE BYPASS)."
+ --#TYPE "APC XPDU: System state returned to normal."
+ --#SUMMARY "PDU state normal."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 481
+
+xPDUEpoTestMode TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "WARNING: The device's Emergency Power Off (EPO) circuit has been
+ switched back to the test position.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Emergency Power Off (EPO) in test mode."
+ --#SUMMARY "EPO disabled."
+ --#ARGUMENTS { }
+ --#SEVERITY WARNING
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 482
+
+xPDUEpoArmed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: The device's Emergency Power Off (EPO) circuit has been
+ switched back to the armed position.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Emergency Power Off (EPO) enabled."
+ --#SUMMARY "EPO armed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 483
+
+xPDUFuseBlownAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName,
+ mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: One or more fuses in this PDU have been detected as open.
+ These fuses are in the feed to the UPS associated with this PDU.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3)."
+ --#TYPE "APC XPDU: Check fuse alarm."
+ --#SUMMARY "Fuse detected opened."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 484
+
+xPDUFuseBlownAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName,
+ mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A previous check fuse alarm in this PDU has cleared.
+ These fuses are in the feed to the UPS associated with this PDU.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the phase (1=L1, 2=L2, 3=L3)."
+ --#TYPE "APC XPDU: Check fuse alarm cleared."
+ --#SUMMARY "Fuse alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 485
+
+xPDUBreakerPositionAlarm TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName,
+ mtrapargsInteger, mtrapargsInteger02, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: A PDU breaker is in a state that compromises system availability.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the breaker (1=MAIN INPUT, 2=BYPASS INPUT, 3=CROSS TIE).
+ The fourth argument is the breaker position (1=OPEN, 2=CLOSED)."
+ --#TYPE "APC XPDU: Breaker position alarm."
+ --#SUMMARY "Breaker position alarm."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 486
+
+xPDUBreakerPositionAlarmCleared TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName,
+ mtrapargsInteger, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A PDU breaker is no longer in a state that compromises system availability.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the breaker (1=MAIN INPUT, 2=BYPASS INPUT, 3=CROSS TIE)."
+ --#TYPE "APC XPDU: Breaker position alarm cleared."
+ --#SUMMARY "Breaker alarm cleared."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 487
+
+xPDUBreakerChangeEvent TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsInteger,
+ mtrapargsInteger02, mtrapargsInteger03, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: A system breaker or switch within the device has changed state.
+ They are generated when any of the Q1, Q2 or Q3 breakers have changed states.
+ The first argument is the host device serial number.
+ The second argument is the host device name.
+ The third argument is the breaker that has changed
+ (1=UPS FEED (Q1), 2=UPS OUTPUT(Q2), 3=MAINTENANCE BYPASS (Q3).
+ The fourth argument is the state of the breaker that has changed (1=OPEN, 2=CLOSED).
+ The fifth argument is a 8-bit field representing the state of all breakers in the system,
+ when any of one of the Q1, Q2 or Q3 breakers have changed state.
+
+ The bit map is represented in the following manner (b7, b6 ... b0)
+ b0 - UPS FEED (Q1)
+ b1 - MAINTENANCE BYPASS (Q3)
+ b2 - UPS OUTPUT (Q2)
+ b3 - MAIN INPUT
+ b4 - BYPASS INPUT
+ b5 - CROSS-TIE OUTPUT
+
+ Example: value of 60 (0x3C) indicates that the CROSS_TIE, BYPASS and MAIN INPUT, and Q2 breakers
+ are CLOSED and Q2, Q1 breakers are OPEN."
+ --#TYPE "APC XPDU: Breaker/switch change event."
+ --#SUMMARY "Breaker/switch change event."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 488
+
+xPDUControllerFirmwareUpdateTransferStart TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Start Controller firmware transfer in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Start controller firmware transfer."
+ --#SUMMARY "Start controller firmware transfer."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 489
+
+xPDUControllerFirmwareUpdateTransferComplete TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Transfer of Controller firmware was completed in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Controller firmware transfer completed."
+ --#SUMMARY "Controller firmware transfer completed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 490
+
+xPDUControllerFirmwareUpdateTransferFailed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Transfer of Controller firmware has failed in the PDU.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XPDU: Controller firmware transfer failed."
+ --#SUMMARY "Controller firmware transfer failed."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 491
+
+xATSControllerFirmwareUpdateTransferStart TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Start Controller firmware transfer in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Start controller firmware transfer."
+ --#SUMMARY "Start controller firmware transfer."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 492
+
+xATSControllerFirmwareUpdateTransferComplete TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "INFORMATIONAL: Transfer of Controller firmware was completed in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Controller firmware transfer completed."
+ --#SUMMARY "Controller firmware transfer completed."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 493
+
+xATSControllerFirmwareUpdateTransferFailed TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { xPDUIdentSerialNumber, xPDUIdentProductName, mtrapargsString }
+ DESCRIPTION
+ "SEVERE: Transfer of Controller firmware has failed in the device.
+ The first argument is the host device serial number.
+ The second argument is the host device name."
+ --#TYPE "APC XATS: Controller firmware transfer failed."
+ --#SUMMARY "Controller firmware transfer failed."
+ --#ARGUMENTS { }
+ --#SEVERITY SEVERE
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE DEGRADED
+ ::= 494
+
+apcDeviceShutdownHeartbeat TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { mtrapargsInteger, mtrapargsTimeTicks, mtrapargsString}
+ DESCRIPTION
+ "INFORMATIONAL: "
+ --#TYPE "APC X:"
+ --#SUMMARY "."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 999
+
+apcDiscoveryAlarmStateTableUpdate TRAP-TYPE
+ ENTERPRISE apc
+ VARIABLES { apcDiscoveryDeviceAlarmStateChangeCount }
+ DESCRIPTION
+ "INTERNAL: A Discovery Alarm State Table Update trap is sent
+ when any data alarm state is added, removed, or its parameters
+ are changed in the condition table. This trap is
+ only for machine-to-machine communication. "
+ --#TYPE "APC X:"
+ --#SUMMARY "."
+ --#ARGUMENTS { }
+ --#SEVERITY INFORMATIONAL
+ --#TIMEINDEX 1
+ --#HELP ""
+ --#HELPTAG 0
+ --#STATE OPERATIONAL
+ ::= 1000
+
+END
diff --git a/agents/autodetect/a.py b/agents/autodetect/a.py
new file mode 100644
index 0000000..608d0f8
--- /dev/null
+++ b/agents/autodetect/a.py
@@ -0,0 +1,8 @@
+from b import myf
+
+def maf():
+ return 5
+
+def maf2():
+ return myf()
+ \ No newline at end of file
diff --git a/agents/autodetect/autodetect.py b/agents/autodetect/autodetect.py
new file mode 100755
index 0000000..24d9a73
--- /dev/null
+++ b/agents/autodetect/autodetect.py
@@ -0,0 +1,255 @@
+#!/usr/bin/python
+
+import pexpect
+import re
+import logging
+import time
+import sys
+import fencing
+
+import fence_apc
+import fence_bladecenter
+import fence_brocade
+import fence_rsa
+
+def check_agent(conn, options, found_prompt, prompts, test_fn, eol=None):
+ options["--action"] = "list"
+ options["--command-prompt"] = found_prompt
+ if any(x in options["--command-prompt"][0] for x in prompts):
+ options["--command-prompt"] = prompts
+
+ return test_fn(conn, options)
+ return False
+
+def get_list(conn, options, found_prompt, prompts, list_fn, eol=None):
+ def test_fn(conn, options):
+ if len(list_fn(conn, options)) > 0:
+ return True
+ else:
+ return False
+
+ return check_agent(conn, options, found_prompt, prompts, test_fn, eol)
+
+""" *************************** MAIN ******************************** """
+
+
+def detect_login_telnet(options):
+ options["--ipport"] = 23
+ re_login_string = r"([\r\n])((?!Last )login\s*:)|((?!Last )Login Name: )|(username: )|(User Name :)"
+ re_login = re.compile(re_login_string, re.IGNORECASE)
+ re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
+
+ options["eol"] = "\r\n"
+ conn = fencing.fspawn(options, options["--telnet-path"])
+ conn.send("set binary\n")
+ conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
+
+ conn.log_expect(re_login, int(options["--login-timeout"]))
+ conn.send_eol(options["--username"])
+
+ ## automatically change end of line separator
+ screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ if re_login.search(screen) != None:
+ options["eol"] = "\n"
+ conn.send_eol(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ elif re_pass.search(screen) == None:
+ conn.log_expect(re_pass, int(options["--shell-timeout"]))
+
+ try:
+ conn.send_eol(options["--password"])
+ valid_password = conn.log_expect([re_login] + \
+ [pexpect.TIMEOUT], int(options["--shell-timeout"]))
+ if valid_password == 0:
+ ## password is invalid or we have to change EOL separator
+ options["eol"] = "\r"
+ conn.send_eol("")
+ screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ ## after sending EOL the fence device can either show 'Login' or 'Password'
+ if re_login.search(conn.after + screen) != None:
+ conn.send_eol("")
+ conn.send_eol(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ conn.send_eol(options["--password"])
+ conn.log_expect(pexpect.TIMEOUT, int(options["--login-timeout"]))
+ except KeyError:
+ fencing.fail(fencing.EC_PASSWORD_MISSING)
+
+ found_cmd_prompt = guess_prompt(conn, options, conn.before)
+ return (found_cmd_prompt, conn)
+
+def guess_prompt(conn, options, before=""):
+ time.sleep(2)
+ conn.send_eol("")
+ conn.send_eol("")
+
+ conn.log_expect(pexpect.TIMEOUT, int(options["--login-timeout"]))
+ lines = re.split(r'\r|\n', before + conn.before)
+ logging.info("Cmd-prompt candidate: %s" % (lines[-1]))
+ if lines.count(lines[-1]) >= 3:
+ found_cmd_prompt = ["\n" + lines[-1]]
+ else:
+ if lines.count(lines[-1]) == 2:
+ conn.log_expect(lines[-1], int(options["--shell-timeout"]))
+ conn.log_expect(lines[-1], int(options["--shell-timeout"]))
+ options["eol"] = "\r"
+ conn.send_eol("")
+ time.sleep(0.1)
+ conn.send_eol("")
+ time.sleep(0.1)
+ conn.send_eol("")
+ time.sleep(0.1)
+ conn.log_expect(pexpect.TIMEOUT, int(options["--login-timeout"]))
+ lines = re.split(r'\r|\n', conn.before)
+ logging.info("Cmd-prompt candidate: %s" % (lines[1]))
+ if lines.count(lines[-1]) >= 3:
+ found_cmd_prompt = ["\n" + lines[-1]]
+ else:
+ print "Unable to obtain command prompt automatically"
+ sys.exit(1)
+ else:
+ print "Unable to obtain command prompt automatically"
+ print lines[-1]
+ print conn.before
+ sys.exit(1)
+
+ conn.log_expect(found_cmd_prompt, int(options["--shell-timeout"]))
+ conn.log_expect(found_cmd_prompt, int(options["--shell-timeout"]))
+ conn.log_expect(found_cmd_prompt, int(options["--shell-timeout"]))
+
+ # Handle situation when CR/LF is interpreted as ENTER, ENTER
+ # In such case we will have get two additional command prompts to get on right position
+ res = conn.log_expect([pexpect.TIMEOUT] + found_cmd_prompt, int(options["--shell-timeout"]))
+ if res > 0:
+ # @note: store that information?
+ print "CMD twice"
+ conn.log_expect(found_cmd_prompt, int(options["--shell-timeout"]))
+ return found_cmd_prompt
+
+def detect_login_ssh(options, version=2):
+ options["--ipport"] = 22
+ if version == "1":
+ command = '%s %s@%s -p %s -1 -c blowfish -o PubkeyAuthentication=no' % (options["--ssh-path"], options["--username"], options["--ip"], options["--ipport"])
+ else:
+ command = '%s %s@%s -p %s -o PubkeyAuthentication=no' % (options["--ssh-path"], options["--username"], options["--ip"], options["--ipport"])
+
+ conn = fencing.fspawn(options, command)
+ result = conn.log_expect(["ssword:", "Are you sure you want to continue connecting (yes/no)?"], int(options["--login-timeout"]))
+ if result == 1:
+ conn.send("yes\n")
+ conn.log_expect("ssword:", int(options["--login-timeout"]))
+
+ conn.send(options["--password"] + "\n")
+
+ found_cmd_prompt = guess_prompt(conn, options, conn.before)
+ return (found_cmd_prompt, conn)
+
+def detect_device(conn, options, found_cmd_prompt):
+ if get_list(conn, options, found_cmd_prompt, prompts=["\n>", "\napc>"], list_fn=fence_apc.get_power_status):
+ fencing.fence_logout(conn, "4")
+ return "fence_apc # older serie"
+
+ if get_list(conn, options, found_cmd_prompt, prompts=["\n>", "\napc>"], list_fn=fence_apc.get_power_status5):
+ fencing.fence_logout(conn, "exit")
+ return "fence_apc # v5+"
+
+ ## Test fence_lpar with list action (HMC version 3 and 4)
+ def test_lpar(conn, options):
+ conn.send_eol("lssyscfg; echo $?")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ if "\n0\r\n" in conn.before:
+ return True
+ else:
+ return False
+
+ if check_agent(conn, options, found_cmd_prompt, [r":~>", r"]\$", r"\$ "], test_lpar):
+ fencing.fence_logout(conn, "quit")
+ return "fence_lpar # 2"
+
+ if get_list(conn, options, found_cmd_prompt, prompts=["system>"], list_fn=fence_bladecenter.get_blades_list):
+ fencing.fence_logout(conn, "exit")
+ return "fence_bladecenter #2"
+
+ if get_list(conn, options, found_cmd_prompt, prompts=["> "], list_fn=fence_brocade.get_power_status, eol="\n"):
+ fencing.fence_logout(conn, "exit")
+ return "fence_brocade #2"
+
+ if get_list(conn, options, found_cmd_prompt, prompts=["> "], list_fn=fence_rsa.get_power_status):
+ fencing.fence_logout(conn, "exit")
+ return "fence_rsa"
+
+ return None
+
+# Test fence ilo moonshot
+#cmd_possible = ["MP>", "hpiLO->"]
+#options["--action"] = "list"
+#options["--command-prompt"] = found_cmd_prompt
+#options["eol"] = "\n"
+#if any(x in options["--command-prompt"][0] for x in cmd_possible):
+# options["--command-prompt"] = cmd_possible
+#
+# plugs = fence_ilo_moonshot.get_power_status(conn, options)
+# if len(plugs) > 0:
+# print "fence_ilo_moonshot # "
+# fencing.fence_logout(conn, "exit")
+# sys.exit(0)
+
+def xxx():
+ ## login mechanism as in fencing.py.py - differences is that we do not know command prompt
+ #logging.getLogger().setLevel(logging.DEBUG)
+ options = {}
+ options["--ssh-path"] = "/usr/bin/ssh"
+ options["--telnet-path"] = "/usr/bin/telnet"
+
+ # virtual machine
+ #options["--username"] = "marx"
+ #options["--ip"] = "localhost"
+ #options["--password"] = "batalion"
+
+ # APC
+ #options["--username"] = "labuser"
+ #options["--ip"] = "pdu-bar.englab.brq.redhat.com"
+ #options["--password"] = "labuser"
+
+ # LPAR
+ options["--username"] = "rhts"
+ options["--ip"] = "ppc-hmc-01.mgmt.lab.eng.bos.redhat.com"
+ #options["--ip"] = "ibm-js22-vios-02.rhts.eng.bos.redhat.com"
+ options["--password"] = "100yard-"
+
+ # Bladecenter
+ options["--ip"] = "blade-mm.englab.brq.redhat.com"
+
+ # Brocade
+ #options["--ip"] = "hp-fcswitch-01.lab.bos.redhat.com"
+ #options["--password"] = "password"
+ #options["--username"] = "admin"
+
+ # iLO Moonshot - chova sa to divne
+ #options["--password"] = "Access@gis"
+ #options["--username"] = "rcuser"
+ #options["--ip"] = "hp-m1500-mgmt.gsslab.pnq.redhat.com"
+
+ #options["--ip"] = "ibm-x3755-01-rsa.ovirt.rhts.eng.bos.redhat.com"
+ #options["--username"] = "USERID"
+ #options["--password"] = "PASSW0RD"
+
+ options["--login-timeout"] = "10"
+ options["--shell-timeout"] = "5"
+ options["--power-timeout"] = "10"
+
+ options["eol"] = "\r\n"
+
+ (found_cmd_prompt, conn) = detect_login_telnet(options)
+ #(found_cmd_prompt, conn) = detect_login_ssh(options)
+
+ res = detect_device(conn, options, found_cmd_prompt)
+ if not res is None:
+ print res
+ sys.exit(0)
+ else:
+ ## Nothing found
+ sys.exit(2)
+
+if __name__ == "__main__":
+ xxx()
diff --git a/agents/autodetect/autodetect_test.py b/agents/autodetect/autodetect_test.py
new file mode 100755
index 0000000..a18aaed
--- /dev/null
+++ b/agents/autodetect/autodetect_test.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+import unittest
+import autodetect as detect
+
+class TestDetectDevice(unittest.TestCase):
+ options = {}
+
+ def setUp(self):
+ self.options = {}
+ self.options["--ssh-path"] = "/usr/bin/ssh"
+ self.options["--telnet-path"] = "/usr/bin/telnet"
+ self.options["--login-timeout"] = "10"
+ self.options["--shell-timeout"] = "5"
+ self.options["--power-timeout"] = "10"
+ self.options["eol"] = "\r\n"
+
+ def test_bladecenter(self):
+ self.options["--username"] = "rhts"
+ self.options["--password"] = "100yard-"
+ self.options["--ip"] = "blade-mm.englab.brq.redhat.com"
+
+ (found_cmd_prompt, conn) = detect.detect_login_telnet(self.options)
+ res = detect.detect_device(conn, self.options, found_cmd_prompt)
+ self.assertEqual('fence_bladecenter', res)
+
+ def test_apc5(self):
+ self.assertEqual('foo', 'foo')
+ self.options["c"] = "c"
+ print self.options
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/agents/autodetect/b.py b/agents/autodetect/b.py
new file mode 100644
index 0000000..fdfda59
--- /dev/null
+++ b/agents/autodetect/b.py
@@ -0,0 +1,2 @@
+def myf():
+ return 3
diff --git a/agents/autodetect/fence_apc.py b/agents/autodetect/fence_apc.py
new file mode 100644
index 0000000..c6dd106
--- /dev/null
+++ b/agents/autodetect/fence_apc.py
@@ -0,0 +1,259 @@
+#!/usr/bin/python -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Model Firmware
+## +---------------------------------------------+
+## AP7951 AOS v2.7.0, PDU APP v2.7.3
+## AP7941 AOS v3.5.7, PDU APP v3.5.6
+## AP9606 AOS v2.5.4, PDU APP v2.7.3
+##
+## @note: ssh is very slow on AP79XX devices protocol (1) and
+## cipher (des/blowfish) have to be defined
+#####
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, EC_STATUS
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION="New APC Agent - test release on steroids"
+REDHAT_COPYRIGHT=""
+BUILD_DATE="March, 2008"
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+ exp_result = 0
+ outlets = {}
+
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ version = 0
+ admin = 0
+ switch = 0
+
+ if None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before):
+ switch = 1
+ if None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before):
+ if not options.has_key("--switch"):
+ fail_usage("Failed: You have to enter physical switch number")
+ else:
+ if not options.has_key("--switch"):
+ options["--switch"] = "1"
+
+ if None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before):
+ version = 2
+ else:
+ version = 3
+
+ if None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before):
+ admin = 0
+ else:
+ admin = 1
+
+ if switch == 0:
+ if version == 2:
+ if admin == 0:
+ conn.send_eol("2")
+ else:
+ conn.send_eol("3")
+ else:
+ conn.send_eol("2")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.send_eol("1")
+ else:
+ conn.send_eol(options["--switch"])
+
+ while True:
+ exp_result = conn.log_expect(
+ ["Press <ENTER>"] + options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+ show_re = re.compile(r'(^|\x0D)\s*(\d+)- (.*?)\s+(ON|OFF)\s*')
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ outlets[res.group(2)] = (res.group(3), res.group(4))
+ conn.send_eol("")
+ if exp_result != 0:
+ break
+ conn.send(chr(03))
+ conn.log_expect("- Logout", int(options["--shell-timeout"]))
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ try:
+ (_, status) = outlets[options["--plug"]]
+ return status.lower().strip()
+ except KeyError:
+ fail(EC_STATUS)
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "1",
+ 'off': "2"
+ }[options["--action"]]
+
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ version = 0
+ admin2 = 0
+ admin3 = 0
+ switch = 0
+
+ if None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before):
+ switch = 1
+ ## MasterSwitch has different schema for on/off actions
+ action = {
+ 'on' : "1",
+ 'off': "3"
+ }[options["--action"]]
+ if None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before):
+ if not options.has_key("--switch"):
+ fail_usage("Failed: You have to enter physical switch number")
+ else:
+ if not options.has_key("--switch"):
+ options["--switch"] = 1
+
+ if None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before):
+ version = 2
+ else:
+ version = 3
+
+ if None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before):
+ admin2 = 0
+ else:
+ admin2 = 1
+
+ if switch == 0:
+ if version == 2:
+ if admin2 == 0:
+ conn.send_eol("2")
+ else:
+ conn.send_eol("3")
+ else:
+ conn.send_eol("2")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ if None == re.compile('.*2- Outlet Restriction.*', re.IGNORECASE | re.S).match(conn.before):
+ admin3 = 0
+ else:
+ admin3 = 1
+ conn.send_eol("1")
+ else:
+ conn.send_eol(options["--switch"])
+
+ while 0 == conn.log_expect(
+ ["Press <ENTER>"] + options["--command-prompt"], int(options["--shell-timeout"])):
+ conn.send_eol("")
+
+ conn.send_eol(options["--plug"]+"")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ if switch == 0:
+ if admin2 == 1:
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ if admin3 == 1:
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ else:
+ conn.send_eol("1")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ conn.send_eol(action)
+ conn.log_expect("Enter 'YES' to continue or <ENTER> to cancel :", int(options["--shell-timeout"]))
+ conn.send_eol("YES")
+ conn.log_expect("Press <ENTER> to continue...", int(options["--power-timeout"]))
+ conn.send_eol("")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ conn.send(chr(03))
+ conn.log_expect("- Logout", int(options["--shell-timeout"]))
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_power_status5(conn, options):
+ outlets = {}
+
+ conn.send_eol("olStatus all")
+
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+
+ show_re = re.compile(r'^\s*(\d+): (.*): (On|Off)\s*$', re.IGNORECASE)
+
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ outlets[res.group(1)] = (res.group(2), res.group(3))
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ try:
+ (_, status) = outlets[options["--plug"]]
+ return status.lower().strip()
+ except KeyError:
+ fail(EC_STATUS)
+
+def set_power_status5(conn, options):
+ action = {
+ 'on' : "olOn",
+ 'off': "olOff"
+ }[options["--action"]]
+
+ conn.send_eol(action + " " + options["--plug"])
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "switch", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["\n>", "\napc>"]
+ all_opt["ssh_options"]["default"] = "-1 -c blowfish"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for APC over telnet/ssh"
+ docs["longdesc"] = "fence_apc is an I/O Fencing agent \
+which can be used with the APC network power switch. It logs into device \
+via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections \
+should be avoided while a GFS cluster is running because the connection \
+will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.apc.com"
+ show_docs(options, docs)
+
+ ## Support for --plug [switch]:[plug] notation that was used before
+ if (options.has_key("--plug") == 1) and (-1 != options["--plug"].find(":")):
+ (switch, plug) = options["--plug"].split(":", 1)
+ options["--switch"] = switch
+ options["--plug"] = plug
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+
+ ## Detect firmware version (ASCII menu vs command-line interface)
+ ## and continue with proper action
+ ####
+ result = -1
+ firmware_version = re.compile(r'\s*v(\d)*\.').search(conn.before)
+ if (firmware_version != None) and (firmware_version.group(1) in [ "5", "6" ]):
+ result = fence_action(conn, options, set_power_status5, get_power_status5, get_power_status5)
+ else:
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+
+ fence_logout(conn, "4")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/autodetect/fence_bladecenter.py b/agents/autodetect/fence_bladecenter.py
new file mode 100644
index 0000000..d72c07f
--- /dev/null
+++ b/agents/autodetect/fence_bladecenter.py
@@ -0,0 +1,111 @@
+#!/usr/bin/python -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Model Firmware
+## +--------------------+---------------------------+
+## (1) Main application BRET85K, rev 16
+## Boot ROM BRBR67D, rev 16
+## Remote Control BRRG67D, rev 16
+##
+#####
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS, EC_GENERIC_ERROR
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION="New Bladecenter Agent - test release on steroids"
+REDHAT_COPYRIGHT=""
+BUILD_DATE="March, 2008"
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+ node_cmd = r"system:blade\[" + options["--plug"] + r"\]>"
+
+ conn.send_eol("env -T system:blade[" + options["--plug"] + "]")
+ i = conn.log_expect([node_cmd, "system>"], int(options["--shell-timeout"]))
+ if i == 1:
+ ## Given blade number does not exist
+ if options.has_key("--missing-as-off"):
+ return "off"
+ else:
+ fail(EC_STATUS)
+ conn.send_eol("power -state")
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+ status = conn.before.splitlines()[-1]
+ conn.send_eol("env -T system")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ return status.lower().strip()
+
+def set_power_status(conn, options):
+ node_cmd = r"system:blade\[" + options["--plug"] + r"\]>"
+
+ conn.send_eol("env -T system:blade[" + options["--plug"] + "]")
+ i = conn.log_expect([node_cmd, "system>"], int(options["--shell-timeout"]))
+ if i == 1:
+ ## Given blade number does not exist
+ if options.has_key("--missing-as-off"):
+ return
+ else:
+ fail(EC_GENERIC_ERROR)
+
+ conn.send_eol("power -"+options["--action"])
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+ conn.send_eol("env -T system")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_blades_list(conn, options):
+ outlets = {}
+
+ node_cmd = "system>"
+
+ conn.send_eol("env -T system")
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+ conn.send_eol("list -l 2")
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+
+ lines = conn.before.split("\r\n")
+ filter_re = re.compile(r"^\s*blade\[(\d+)\]\s+(.*?)\s*$")
+ for blade_line in lines:
+ res = filter_re.search(blade_line)
+ if res != None:
+ outlets[res.group(1)] = (res.group(2), "")
+
+ return outlets
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "missing_as_off", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["power_wait"]["default"] = "10"
+ all_opt["cmd_prompt"]["default"] = ["system>"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM BladeCenter"
+ docs["longdesc"] = "fence_bladecenter is an I/O Fencing agent \
+which can be used with IBM Bladecenters with recent enough firmware that \
+includes telnet support. It logs into a Brocade chasis via telnet or ssh \
+and uses the command line interface to power on and off blades."
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ######
+ conn = fence_login(options, "(username\s*:\s*)")
+ result = fence_action(conn, options, set_power_status, get_power_status, get_blades_list)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/autodetect/fence_brocade.py b/agents/autodetect/fence_brocade.py
new file mode 100644
index 0000000..5257bcc
--- /dev/null
+++ b/agents/autodetect/fence_brocade.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python -tt
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION="New Brocade Agent - test release on steroids"
+REDHAT_COPYRIGHT=""
+BUILD_DATE="March, 20013"
+#END_VERSION_GENERATION
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "portCfgPersistentEnable",
+ 'off': "portCfgPersistentDisable"
+ }[options["--action"]]
+
+ conn.send_eol(action + " " + options["--plug"])
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def get_power_status(conn, options):
+ line_re = re.compile(r'=========', re.IGNORECASE)
+ outlets = {}
+ in_index = False
+
+ conn.send_eol("switchshow")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ for line in str(conn.before).split("\n"):
+ if line_re.search(line):
+ in_index = True
+ elif in_index and line.lstrip()[0].isdigit():
+ tokens = line.lstrip().split()
+ status = "off" if len(tokens) > 7 and tokens[7] == "Disabled" else "on"
+ outlets[tokens[0]] = ("", status)
+
+ if ["list", "monitor"].count(options["--action"]) == 0:
+ (_, status) = outlets[options["--plug"]]
+ return status
+ else:
+ return outlets
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "fabric_fencing", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["> "]
+
+ options = check_input(device_opt, process_input(device_opt))
+ options["eol"] = "\n"
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP Brocade over telnet/ssh"
+ docs["longdesc"] = "fence_brocade is an I/O Fencing agent which can be used with Brocade FC switches. \
+It logs into a Brocade switch via telnet and disables a specified port. Disabling the port which a machine is \
+connected to effectively fences that machine. Lengthy telnet connections to the switch should be avoided while \
+a GFS cluster is running because the connection will block any necessary fencing actions. \
+\
+After a fence operation has taken place the fenced machine can no longer connect to the Brocade FC switch. \
+When the fenced machine is ready to be brought back into the GFS cluster (after reboot) the port on the Brocade \
+FC switch needs to be enabled. This can be done by running fence_brocade and specifying the enable action"
+ docs["vendorurl"] = "http://www.brocade.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/autodetect/fence_ilo_moonshot.py b/agents/autodetect/fence_ilo_moonshot.py
new file mode 100644
index 0000000..e161ac6
--- /dev/null
+++ b/agents/autodetect/fence_ilo_moonshot.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python -tt
+
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=""
+REDHAT_COPYRIGHT=""
+BUILD_DATE=""
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+ conn.send_eol("show node list")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ nodes = {}
+ for line in conn.before.splitlines():
+ if len(line.split()) == 10:
+ nodes[line.split()[1]] = ("", line.split()[8].lower().strip())
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return nodes
+ else:
+ try:
+ (_, status) = nodes[options["--plug"]]
+ return status.lower()
+ except KeyError:
+ fail(EC_STATUS)
+
+def set_power_status(conn, options):
+ if options["--action"] == "on":
+ conn.send_eol("set node power on %s" % (options["--plug"]))
+ else:
+ conn.send_eol("set node power off force %s" % (options["--plug"]))
+
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ return
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", "port"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["secure"]["default"] = "1"
+ all_opt["cmd_prompt"]["default"] = ["MP>", "hpiLO->"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP Moonshot iLO"
+ docs["longdesc"] = ""
+ docs["vendorurl"] = "http://www.hp.com"
+ show_docs(options, docs)
+
+ conn = fence_login(options)
+
+ ##
+ ## Fence operations
+ ####
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/autodetect/fence_lpar.py b/agents/autodetect/fence_lpar.py
new file mode 100644
index 0000000..6676e1c
--- /dev/null
+++ b/agents/autodetect/fence_lpar.py
@@ -0,0 +1,159 @@
+#!/usr/bin/python -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Version
+## +---------------------------------------------+
+## Tested on HMC
+##
+#####
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, EC_STATUS_HMC
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION=""
+REDHAT_COPYRIGHT=""
+BUILD_DATE=""
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+ if options["--hmc-version"] == "3":
+ conn.send("lssyscfg -r lpar -m " + options["--managed"] + " -n " + options["--plug"] + " -F name,state\n")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ try:
+ status = re.compile("^" + options["--plug"] + ",(.*?),.*$",
+ re.IGNORECASE | re.MULTILINE).search(conn.before).group(1)
+ except AttributeError:
+ fail(EC_STATUS_HMC)
+ elif options["--hmc-version"] == "4":
+ conn.send("lssyscfg -r lpar -m "+ options["--managed"] +
+ " --filter 'lpar_names=" + options["--plug"] + "'\n")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ try:
+ status = re.compile(",state=(.*?),", re.IGNORECASE).search(conn.before).group(1)
+ except AttributeError:
+ fail(EC_STATUS_HMC)
+
+ ##
+ ## Transformation to standard ON/OFF status if possible
+ if status in ["Running", "Open Firmware", "Shutting Down", "Starting"]:
+ status = "on"
+ else:
+ status = "off"
+
+ return status
+
+def set_power_status(conn, options):
+ if options["--hmc-version"] == "3":
+ conn.send("chsysstate -o " + options["--action"] + " -r lpar -m " + options["--managed"]
+ + " -n " + options["--plug"] + "\n")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ elif options["--hmc-version"] == "4":
+ if options["--action"] == "on":
+ conn.send("chsysstate -o on -r lpar -m " + options["--managed"] +
+ " -n " + options["--plug"] +
+ " -f `lssyscfg -r lpar -F curr_profile " +
+ " -m " + options["--managed"] +
+ " --filter \"lpar_names=" + options["--plug"] + "\"`\n")
+ else:
+ conn.send("chsysstate -o shutdown -r lpar --immed" +
+ " -m " + options["--managed"] + " -n " + options["--plug"] + "\n")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def get_lpar_list(conn, options):
+ outlets = {}
+ if options["--hmc-version"] == "3":
+ conn.send("query_partition_names -m " + options["--managed"] + "\n")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ ## We have to remove first 3 lines (command + header) and last line (part of new prompt)
+ ####
+ res = re.search("^.+?\n(.+?\n){2}(.*)\n.*$", conn.before, re.S)
+
+ if res == None:
+ fail_usage("Unable to parse output of list command")
+
+ lines = res.group(2).split("\n")
+ for outlet_line in lines:
+ outlets[outlet_line.rstrip()] = ("", "")
+ elif options["--hmc-version"] == "4":
+ conn.send("lssyscfg -r lpar -m " + options["--managed"] +
+ " -F name:state\n")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ ## We have to remove first line (command) and last line (part of new prompt)
+ ####
+ res = re.search("^.+?\n(.*)\n.*$", conn.before, re.S)
+
+ if res == None:
+ fail_usage("Unable to parse output of list command")
+
+ lines = res.group(1).split("\n")
+ for outlet_line in lines:
+ (port, status) = outlet_line.split(":")
+ outlets[port] = ("", status)
+
+ return outlets
+
+def define_new_opts():
+ all_opt["managed"] = {
+ "getopt" : "s:",
+ "longopt" : "managed",
+ "help" : "-s, --managed=[id] Name of the managed system",
+ "required" : "0",
+ "shortdesc" : "Managed system name",
+ "order" : 1}
+ all_opt["hmc_version"] = {
+ "getopt" : "H:",
+ "longopt" : "hmc-version",
+ "help" : "-H, --hmc-version=[version] Force HMC version to use: (3|4) (default: 4)",
+ "required" : "0",
+ "shortdesc" : "Force HMC version to use",
+ "default" : "4",
+ "choices" : ["3", "4"],
+ "order" : 1}
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", \
+ "port", "managed", "hmc_version"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["login_timeout"]["default"] = "15"
+ all_opt["secure"]["default"] = "1"
+ all_opt["cmd_prompt"]["default"] = [r":~>", r"]\$", r"\$ "]
+
+ options = check_input(device_opt, process_input(device_opt), other_conditions = True)
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM LPAR"
+ docs["longdesc"] = ""
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ if not options.has_key("--managed"):
+ fail_usage("Failed: You have to enter name of managed system")
+
+ if options["--action"] == "validate-all":
+ sys.exit(0)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_lpar_list)
+ fence_logout(conn, "quit\r\n")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/autodetect/fencing.py b/agents/autodetect/fencing.py
new file mode 100644
index 0000000..ea21ace
--- /dev/null
+++ b/agents/autodetect/fencing.py
@@ -0,0 +1,1393 @@
+#!/usr/bin/python -tt
+
+import sys, getopt, time, os, uuid, pycurl, stat
+import pexpect, re, syslog
+import logging
+import subprocess
+import threading
+import shlex
+import exceptions
+import socket
+import textwrap
+import __main__
+
+## do not add code here.
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION="4.0.21.23-eaa13"
+BUILD_DATE="(built Wed Nov 4 13:28:43 CET 2015)"
+REDHAT_COPYRIGHT="Copyright (C) Red Hat, Inc. 2004-2010 All rights reserved."
+#END_VERSION_GENERATION
+
+__all__ = ['atexit_handler', 'check_input', 'process_input', 'all_opt', 'show_docs',
+ 'fence_login', 'fence_action', 'fence_logout']
+
+EC_OK = 0
+EC_GENERIC_ERROR = 1
+EC_BAD_ARGS = 2
+EC_LOGIN_DENIED = 3
+EC_CONNECTION_LOST = 4
+EC_TIMED_OUT = 5
+EC_WAITING_ON = 6
+EC_WAITING_OFF = 7
+EC_STATUS = 8
+EC_STATUS_HMC = 9
+EC_PASSWORD_MISSING = 10
+EC_INVALID_PRIVILEGES = 11
+
+all_opt = {
+ "help" : {
+ "getopt" : "h",
+ "longopt" : "help",
+ "help" : "-h, --help Display this help and exit",
+ "required" : "0",
+ "shortdesc" : "Display help and exit",
+ "order" : 54},
+ "version" : {
+ "getopt" : "V",
+ "longopt" : "version",
+ "help" : "-V, --version Display version information and exit",
+ "required" : "0",
+ "shortdesc" : "Display version information and exit",
+ "order" : 53},
+ "verbose" : {
+ "getopt" : "v",
+ "longopt" : "verbose",
+ "help" : "-v, --verbose Verbose mode",
+ "required" : "0",
+ "order" : 51},
+ "debug" : {
+ "getopt" : "D:",
+ "longopt" : "debug-file",
+ "help" : "-D, --debug-file=[debugfile] Debugging to output file",
+ "required" : "0",
+ "shortdesc" : "Write debug information to given file",
+ "order" : 52},
+ "delay" : {
+ "getopt" : ":",
+ "longopt" : "delay",
+ "help" : "--delay=[seconds] Wait X seconds before fencing is started",
+ "required" : "0",
+ "default" : "0",
+ "order" : 200},
+ "agent" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "web" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "force_on" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "action" : {
+ "getopt" : "o:",
+ "longopt" : "action",
+ "help" : "-o, --action=[action] Action: status, reboot (default), off or on",
+ "required" : "1",
+ "shortdesc" : "Fencing action",
+ "default" : "reboot",
+ "order" : 1},
+ "fabric_fencing" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "ipaddr" : {
+ "getopt" : "a:",
+ "longopt" : "ip",
+ "help" : "-a, --ip=[ip] IP address or hostname of fencing device",
+ "required" : "1",
+ "order" : 1},
+ "ipport" : {
+ "getopt" : "u:",
+ "longopt" : "ipport",
+ "help" : "-u, --ipport=[port] TCP/UDP port to use for connection",
+ "required" : "0",
+ "shortdesc" : "TCP/UDP port to use for connection with device",
+ "order" : 1},
+ "login" : {
+ "getopt" : "l:",
+ "longopt" : "username",
+ "help" : "-l, --username=[name] Login name",
+ "required" : "?",
+ "order" : 1},
+ "no_login" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_password" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_port" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_status" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_on" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_off" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "telnet" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : ""},
+ "passwd" : {
+ "getopt" : "p:",
+ "longopt" : "password",
+ "help" : "-p, --password=[password] Login password or passphrase",
+ "required" : "0",
+ "order" : 1},
+ "passwd_script" : {
+ "getopt" : "S:",
+ "longopt" : "password-script",
+ "help" : "-S, --password-script=[script] Script to run to retrieve password",
+ "required" : "0",
+ "order" : 1},
+ "identity_file" : {
+ "getopt" : "k:",
+ "longopt" : "identity-file",
+ "help" : "-k, --identity-file=[filename] Identity file (private key) for SSH",
+ "required" : "0",
+ "order" : 1},
+ "cmd_prompt" : {
+ "getopt" : "c:",
+ "longopt" : "command-prompt",
+ "help" : "-c, --command-prompt=[prompt] Force Python regex for command prompt",
+ "required" : "0",
+ "order" : 1},
+ "secure" : {
+ "getopt" : "x",
+ "longopt" : "ssh",
+ "help" : "-x, --ssh Use SSH connection",
+ "required" : "0",
+ "order" : 1},
+ "ssh_options" : {
+ "getopt" : ":",
+ "longopt" : "ssh-options",
+ "help" : "--ssh-options=[options] SSH options to use",
+ "required" : "0",
+ "order" : 1},
+ "ssl" : {
+ "getopt" : "z",
+ "longopt" : "ssl",
+ "help" : "-z, --ssl Use SSL connection with verifying certificate",
+ "required" : "0",
+ "order" : 1},
+ "ssl_insecure" : {
+ "getopt" : "",
+ "longopt" : "ssl-insecure",
+ "help" : "--ssl-insecure Use SSL connection without verifying certificate",
+ "required" : "0",
+ "order" : 1},
+ "ssl_secure" : {
+ "getopt" : "",
+ "longopt" : "ssl-secure",
+ "help" : "--ssl-secure Use SSL connection with verifying certificate",
+ "required" : "0",
+ "order" : 1},
+ "notls" : {
+ "getopt" : "t",
+ "longopt" : "notls",
+ "help" : "-t, --notls "
+ "Disable TLS negotiation and force SSL3.0. "
+ "This should only be used for devices that do not support TLS1.0 and up.",
+ "required" : "0",
+ "order" : 1},
+ "tls1.0" : {
+ "getopt" : "",
+ "longopt" : "tls1.0",
+ "help" : "--tls1.0 "
+ "Disable TLS negotiation and force TLS1.0. "
+ "This should only be used for devices that do not support TLS1.1 and up.",
+ "required" : "0",
+ "order" : 1},
+ "port" : {
+ "getopt" : "n:",
+ "longopt" : "plug",
+ "help" : "-n, --plug=[id] "
+ "Physical plug number on device, UUID or identification of machine",
+ "required" : "1",
+ "order" : 1},
+ "switch" : {
+ "getopt" : "s:",
+ "longopt" : "switch",
+ "help" : "-s, --switch=[id] Physical switch number on device",
+ "required" : "0",
+ "order" : 1},
+ "exec" : {
+ "getopt" : "e:",
+ "longopt" : "exec",
+ "help" : "-e, --exec=[command] Command to execute",
+ "required" : "0",
+ "order" : 1},
+ "vmware_type" : {
+ "getopt" : "d:",
+ "longopt" : "vmware_type",
+ "help" : "-d, --vmware_type=[type] Type of VMware to connect",
+ "required" : "0",
+ "order" : 1},
+ "vmware_datacenter" : {
+ "getopt" : "s:",
+ "longopt" : "vmware-datacenter",
+ "help" : "-s, --vmware-datacenter=[dc] VMWare datacenter filter",
+ "required" : "0",
+ "order" : 2},
+ "snmp_version" : {
+ "getopt" : "d:",
+ "longopt" : "snmp-version",
+ "help" : "-d, --snmp-version=[version] Specifies SNMP version to use (1|2c|3)",
+ "required" : "0",
+ "shortdesc" : "Specifies SNMP version to use",
+ "choices" : ["1", "2c", "3"],
+ "order" : 1},
+ "community" : {
+ "getopt" : "c:",
+ "longopt" : "community",
+ "help" : "-c, --community=[community] Set the community string",
+ "required" : "0",
+ "order" : 1},
+ "snmp_auth_prot" : {
+ "getopt" : "b:",
+ "longopt" : "snmp-auth-prot",
+ "help" : "-b, --snmp-auth-prot=[prot] Set authentication protocol (MD5|SHA)",
+ "required" : "0",
+ "shortdesc" : "Set authentication protocol",
+ "choices" : ["MD5", "SHA"],
+ "order" : 1},
+ "snmp_sec_level" : {
+ "getopt" : "E:",
+ "longopt" : "snmp-sec-level",
+ "help" : "-E, --snmp-sec-level=[level] "
+ "Set security level (noAuthNoPriv|authNoPriv|authPriv)",
+ "required" : "0",
+ "shortdesc" : "Set security level",
+ "choices" : ["noAuthNoPriv", "authNoPriv", "authPriv"],
+ "order" : 1},
+ "snmp_priv_prot" : {
+ "getopt" : "B:",
+ "longopt" : "snmp-priv-prot",
+ "help" : "-B, --snmp-priv-prot=[prot] Set privacy protocol (DES|AES)",
+ "required" : "0",
+ "shortdesc" : "Set privacy protocol",
+ "choices" : ["DES", "AES"],
+ "order" : 1},
+ "snmp_priv_passwd" : {
+ "getopt" : "P:",
+ "longopt" : "snmp-priv-passwd",
+ "help" : "-P, --snmp-priv-passwd=[pass] Set privacy protocol password",
+ "required" : "0",
+ "order" : 1},
+ "snmp_priv_passwd_script" : {
+ "getopt" : "R:",
+ "longopt" : "snmp-priv-passwd-script",
+ "help" : "-R, --snmp-priv-passwd-script Script to run to retrieve privacy password",
+ "required" : "0",
+ "order" : 1},
+ "inet4_only" : {
+ "getopt" : "4",
+ "longopt" : "inet4-only",
+ "help" : "-4, --inet4-only Forces agent to use IPv4 addresses only",
+ "required" : "0",
+ "order" : 1},
+ "inet6_only" : {
+ "getopt" : "6",
+ "longopt" : "inet6-only",
+ "help" : "-6, --inet6-only Forces agent to use IPv6 addresses only",
+ "required" : "0",
+ "order" : 1},
+ "separator" : {
+ "getopt" : "C:",
+ "longopt" : "separator",
+ "help" : "-C, --separator=[char] Separator for CSV created by 'list' operation",
+ "default" : ",",
+ "required" : "0",
+ "order" : 100},
+ "login_timeout" : {
+ "getopt" : ":",
+ "longopt" : "login-timeout",
+ "help" : "--login-timeout=[seconds] Wait X seconds for cmd prompt after login",
+ "default" : "5",
+ "required" : "0",
+ "order" : 200},
+ "shell_timeout" : {
+ "getopt" : ":",
+ "longopt" : "shell-timeout",
+ "help" : "--shell-timeout=[seconds] Wait X seconds for cmd prompt after issuing command",
+ "default" : "3",
+ "required" : "0",
+ "order" : 200},
+ "power_timeout" : {
+ "getopt" : ":",
+ "longopt" : "power-timeout",
+ "help" : "--power-timeout=[seconds] Test X seconds for status change after ON/OFF",
+ "default" : "20",
+ "required" : "0",
+ "order" : 200},
+ "power_wait" : {
+ "getopt" : ":",
+ "longopt" : "power-wait",
+ "help" : "--power-wait=[seconds] Wait X seconds after issuing ON/OFF",
+ "default" : "0",
+ "required" : "0",
+ "order" : 200},
+ "missing_as_off" : {
+ "getopt" : "",
+ "longopt" : "missing-as-off",
+ "help" : "--missing-as-off Missing port returns OFF instead of failure",
+ "required" : "0",
+ "order" : 200},
+ "retry_on" : {
+ "getopt" : ":",
+ "longopt" : "retry-on",
+ "help" : "--retry-on=[attempts] Count of attempts to retry power on",
+ "default" : "1",
+ "required" : "0",
+ "order" : 201},
+ "session_url" : {
+ "getopt" : "s:",
+ "longopt" : "session-url",
+ "help" : "-s, --session-url URL to connect to XenServer on",
+ "required" : "1",
+ "order" : 1},
+ "sudo" : {
+ "getopt" : "",
+ "longopt" : "use-sudo",
+ "help" : "--use-sudo Use sudo (without password) when calling 3rd party software",
+ "required" : "0",
+ "order" : 205},
+ "method" : {
+ "getopt" : "m:",
+ "longopt" : "method",
+ "help" : "-m, --method=[method] Method to fence (onoff|cycle) (Default: onoff)",
+ "required" : "0",
+ "shortdesc" : "Method to fence",
+ "default" : "onoff",
+ "choices" : ["onoff", "cycle"],
+ "order" : 1},
+ "telnet_path" : {
+ "getopt" : ":",
+ "longopt" : "telnet-path",
+ "help" : "--telnet-path=[path] Path to telnet binary",
+ "required" : "0",
+ "default" : "/usr/bin/telnet",
+ "order": 300},
+ "ssh_path" : {
+ "getopt" : ":",
+ "longopt" : "ssh-path",
+ "help" : "--ssh-path=[path] Path to ssh binary",
+ "required" : "0",
+ "default" : "/usr/bin/ssh",
+ "order": 300},
+ "gnutlscli_path" : {
+ "getopt" : ":",
+ "longopt" : "gnutlscli-path",
+ "help" : "--gnutlscli-path=[path] Path to gnutls-cli binary",
+ "required" : "0",
+ "default" : "/usr/bin/gnutls-cli",
+ "order": 300},
+ "sudo_path" : {
+ "getopt" : ":",
+ "longopt" : "sudo-path",
+ "help" : "--sudo-path=[path] Path to sudo binary",
+ "required" : "0",
+ "default" : "/usr/bin/sudo",
+ "order": 300},
+ "snmpwalk_path" : {
+ "getopt" : ":",
+ "longopt" : "snmpwalk-path",
+ "help" : "--snmpwalk-path=[path] Path to snmpwalk binary",
+ "required" : "0",
+ "default" : "/usr/bin/snmpwalk",
+ "order" : 300},
+ "snmpset_path" : {
+ "getopt" : ":",
+ "longopt" : "snmpset-path",
+ "help" : "--snmpset-path=[path] Path to snmpset binary",
+ "required" : "0",
+ "default" : "/usr/bin/snmpset",
+ "order" : 300},
+ "snmpget_path" : {
+ "getopt" : ":",
+ "longopt" : "snmpget-path",
+ "help" : "--snmpget-path=[path] Path to snmpget binary",
+ "required" : "0",
+ "default" : "/usr/bin/snmpget",
+ "order" : 300},
+ "snmp": {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "port_as_ip": {
+ "getopt" : "",
+ "longopt" : "port-as-ip",
+ "help" : "--port-as-ip Make \"port/plug\" to be an alias to IP address",
+ "required" : "0",
+ "order" : 200},
+ "on_target": {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "quiet": {
+ "getopt" : "q",
+ "longopt": "quiet",
+ "help" : "-q, --quiet Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.",
+ "required" : "0",
+ "order" : 50}
+}
+
+# options which are added automatically if 'key' is encountered ("default" is always added)
+DEPENDENCY_OPT = {
+ "default" : ["help", "debug", "verbose", "version", "action", "agent", \
+ "power_timeout", "shell_timeout", "login_timeout", "power_wait", "retry_on", \
+ "delay", "quiet"],
+ "passwd" : ["passwd_script"],
+ "sudo" : ["sudo_path"],
+ "secure" : ["identity_file", "ssh_options", "ssh_path"],
+ "telnet" : ["telnet_path"],
+ "ipaddr" : ["ipport", "inet4_only", "inet6_only"],
+ "port" : ["separator"],
+ "ssl" : ["ssl_secure", "ssl_insecure", "gnutlscli_path"],
+ "snmp" : ["snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", \
+ "snmp_priv_passwd", "snmp_priv_passwd_script", "community", \
+ "snmpset_path", "snmpget_path", "snmpwalk_path"]
+ }
+
+class fspawn(pexpect.spawn):
+ def __init__(self, options, command):
+ logging.info("Running command: %s", command)
+ pexpect.spawn.__init__(self, command)
+ self.opt = options
+
+ def log_expect(self, pattern, timeout):
+ result = self.expect(pattern, timeout)
+ logging.debug("Received: %s", str(self.before) + str(self.after))
+ return result
+
+ def send(self, message):
+ logging.debug("Sent: %s", message)
+ return pexpect.spawn.send(self, message)
+
+ # send EOL according to what was detected in login process (telnet)
+ def send_eol(self, message):
+ return self.send(message + self.opt["eol"])
+
+def atexit_handler():
+ try:
+ sys.stdout.close()
+ os.close(1)
+ except IOError:
+ logging.error("%s failed to close standard output\n", sys.argv[0])
+ sys.exit(EC_GENERIC_ERROR)
+
+def _add_dependency_options(options):
+ ## Add also options which are available for every fence agent
+ added_opt = []
+ for opt in options + ["default"]:
+ if DEPENDENCY_OPT.has_key(opt):
+ added_opt.extend([y for y in DEPENDENCY_OPT[opt] if options.count(y) == 0])
+
+ if not "port" in (options + added_opt) and \
+ not "nodename" in (options + added_opt) and \
+ "ipaddr" in (options + added_opt):
+ added_opt.append("port_as_ip")
+ all_opt["port"]["help"] = "-n, --plug=[ip] IP address or hostname of fencing device " \
+ "(together with --port-as-ip)"
+
+ return added_opt
+
+def fail_usage(message="", stop=True):
+ if len(message) > 0:
+ logging.error("%s\n", message)
+ if stop:
+ logging.error("Please use '-h' for usage\n")
+ sys.exit(EC_GENERIC_ERROR)
+
+def fail(error_code):
+ message = {
+ EC_LOGIN_DENIED : "Unable to connect/login to fencing device",
+ EC_CONNECTION_LOST : "Connection lost",
+ EC_TIMED_OUT : "Connection timed out",
+ EC_WAITING_ON : "Failed: Timed out waiting to power ON",
+ EC_WAITING_OFF : "Failed: Timed out waiting to power OFF",
+ EC_STATUS : "Failed: Unable to obtain correct plug status or plug is not available",
+ EC_STATUS_HMC : "Failed: Either unable to obtain correct plug status, "
+ "partition is not available or incorrect HMC version used",
+ EC_PASSWORD_MISSING : "Failed: You have to set login password",
+ EC_INVALID_PRIVILEGES : "Failed: The user does not have the correct privileges to do the requested action."
+ }[error_code] + "\n"
+ logging.error("%s\n", message)
+ sys.exit(EC_GENERIC_ERROR)
+
+def usage(avail_opt):
+ print "Usage:"
+ print "\t" + os.path.basename(sys.argv[0]) + " [options]"
+ print "Options:"
+
+ sorted_list = [(key, all_opt[key]) for key in avail_opt]
+ sorted_list.sort(lambda x, y: cmp(x[1]["order"], y[1]["order"]))
+
+ for key, value in sorted_list:
+ if len(value["help"]) != 0:
+ print " " + _join_wrap([value["help"]], first_indent=3)
+
+def metadata(avail_opt, docs):
+ # avail_opt has to be unique, if there are duplicities then they should be removed
+ sorted_list = [(key, all_opt[key]) for key in list(set(avail_opt))]
+ sorted_list.sort(lambda x, y: cmp(x[0], y[0]))
+ sorted_list.sort(lambda x, y: cmp(x[1]["order"], y[1]["order"]))
+
+ print "<?xml version=\"1.0\" ?>"
+ print "<resource-agent name=\"" + os.path.basename(sys.argv[0]) + \
+ "\" shortdesc=\"" + docs["shortdesc"] + "\" >"
+ for (symlink, desc) in docs.get("symlink", []):
+ print "<symlink name=\"" + symlink + "\" shortdesc=\"" + desc + "\"/>"
+ print "<longdesc>" + docs["longdesc"] + "</longdesc>"
+ print "<vendor-url>" + docs["vendorurl"] + "</vendor-url>"
+ print "<parameters>"
+ for option, _ in sorted_list:
+ if all_opt[option].has_key("help") and len(all_opt[option]["help"]) > 0:
+ print "\t<parameter name=\"" + option + "\" unique=\"0\" required=\"" + all_opt[option]["required"] + "\">"
+
+ default = ""
+ if all_opt[option].has_key("default"):
+ default = "default=\"" + _encode_html_entities(str(all_opt[option]["default"])) + "\" "
+
+ mixed = all_opt[option]["help"]
+ ## split it between option and help text
+ res = re.compile(r"^(.*?--\S+)\s+", re.IGNORECASE | re.S).search(mixed)
+ if None != res:
+ mixed = res.group(1)
+ mixed = _encode_html_entities(mixed)
+
+ if not "shortdesc" in all_opt[option]:
+ shortdesc = re.sub("\s\s+", " ", all_opt[option]["help"][31:])
+ else:
+ shortdesc = all_opt[option]["shortdesc"]
+
+ print "\t\t<getopt mixed=\"" + mixed + "\" />"
+ if all_opt[option].has_key("choices"):
+ print "\t\t<content type=\"select\" "+default+" >"
+ for choice in all_opt[option]["choices"]:
+ print "\t\t\t<option value=\"%s\" />" % (choice)
+ print "\t\t</content>"
+ elif all_opt[option]["getopt"].count(":") > 0:
+ print "\t\t<content type=\"string\" "+default+" />"
+ else:
+ print "\t\t<content type=\"boolean\" "+default+" />"
+ print "\t\t<shortdesc lang=\"en\">" + shortdesc + "</shortdesc>"
+ print "\t</parameter>"
+ print "</parameters>"
+ print "<actions>"
+
+ (available_actions, _) = _get_available_actions(avail_opt)
+
+ if "on" in available_actions:
+ available_actions.remove("on")
+ on_target = ' on_target="1"' if avail_opt.count("on_target") else ''
+ print "\t<action name=\"on\"%s automatic=\"%d\"/>" % (on_target, avail_opt.count("fabric_fencing"))
+
+ for action in available_actions:
+ print "\t<action name=\"%s\" />" % (action)
+ print "</actions>"
+ print "</resource-agent>"
+
+def process_input(avail_opt):
+ avail_opt.extend(_add_dependency_options(avail_opt))
+
+ # @todo: this should be put elsewhere?
+ os.putenv("LANG", "C")
+ os.putenv("LC_ALL", "C")
+
+ if "port_as_ip" in avail_opt:
+ avail_opt.append("port")
+
+ if len(sys.argv) > 1:
+ opt = _parse_input_cmdline(avail_opt)
+ else:
+ opt = _parse_input_stdin(avail_opt)
+
+ if "--port-as-ip" in opt and "--plug" in opt:
+ opt["--ip"] = opt["--plug"]
+
+ return opt
+
+##
+## This function checks input and answers if we want to have same answers
+## in each of the fencing agents. It looks for possible errors and run
+## password script to set a correct password
+######
+def check_input(device_opt, opt, other_conditions = False):
+ device_opt.extend(_add_dependency_options(device_opt))
+
+ options = dict(opt)
+ options["device_opt"] = device_opt
+
+ _update_metadata(options)
+ options = _set_default_values(options)
+ options["--action"] = options["--action"].lower()
+
+ ## In special cases (show help, metadata or version) we don't need to check anything
+ #####
+ # OCF compatibility
+ if options["--action"] == "meta-data":
+ options["--action"] = "metadata"
+
+ if options["--action"] == "metadata" or any(options.has_key(k) for k in ("--help", "--version")):
+ return options
+
+ if options.has_key("--verbose"):
+ logging.getLogger().setLevel(logging.DEBUG)
+
+ ## add logging to syslog
+ logging.getLogger().addHandler(SyslogLibHandler())
+ if not options.has_key("--quiet"):
+ ## add logging to stderr
+ logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))
+
+ (acceptable_actions, _) = _get_available_actions(device_opt)
+
+ if 1 == device_opt.count("fabric_fencing"):
+ acceptable_actions.extend(["enable", "disable"])
+
+ if 0 == acceptable_actions.count(options["--action"]):
+ fail_usage("Failed: Unrecognised action '" + options["--action"] + "'")
+
+ ## Compatibility layer
+ #####
+ if options["--action"] == "enable":
+ options["--action"] = "on"
+ if options["--action"] == "disable":
+ options["--action"] = "off"
+
+
+ if options["--action"] == "validate-all" and not other_conditions:
+ _validate_input(options, False)
+ sys.exit(EC_OK)
+ else:
+ _validate_input(options, True)
+
+ if options.has_key("--debug-file"):
+ try:
+ debug_file = logging.FileHandler(options["--debug-file"])
+ debug_file.setLevel(logging.DEBUG)
+ logging.getLogger().addHandler(debug_file)
+ except IOError:
+ logging.error("Unable to create file %s", options["--debug-file"])
+ fail_usage("Failed: Unable to create file " + options["--debug-file"])
+
+ if options.has_key("--snmp-priv-passwd-script"):
+ options["--snmp-priv-passwd"] = os.popen(options["--snmp-priv-passwd-script"]).read().rstrip()
+
+ if options.has_key("--password-script"):
+ options["--password"] = os.popen(options["--password-script"]).read().rstrip()
+
+ return options
+
+## Obtain a power status from possibly more than one plug
+## "on" is returned if at least one plug is ON
+######
+def get_multi_power_fn(connection, options, get_power_fn):
+ status = "off"
+ plugs = options["--plugs"] if options.has_key("--plugs") else [""]
+
+ for plug in plugs:
+ try:
+ options["--uuid"] = str(uuid.UUID(plug))
+ except ValueError:
+ pass
+ except KeyError:
+ pass
+
+ options["--plug"] = plug
+ plug_status = get_power_fn(connection, options)
+ if plug_status != "off":
+ status = plug_status
+
+ return status
+
+def set_multi_power_fn(connection, options, set_power_fn, get_power_fn, retry_attempts=1):
+ plugs = options["--plugs"] if options.has_key("--plugs") else [""]
+
+ for _ in range(retry_attempts):
+ for plug in plugs:
+ try:
+ options["--uuid"] = str(uuid.UUID(plug))
+ except ValueError:
+ pass
+ except KeyError:
+ pass
+
+ options["--plug"] = plug
+ set_power_fn(connection, options)
+ time.sleep(int(options["--power-wait"]))
+
+ for _ in xrange(int(options["--power-timeout"])):
+ if get_multi_power_fn(connection, options, get_power_fn) != options["--action"]:
+ time.sleep(1)
+ else:
+ return True
+ return False
+
+def show_docs(options, docs=None):
+ device_opt = options["device_opt"]
+
+ if docs == None:
+ docs = {}
+ docs["shortdesc"] = "Fence agent"
+ docs["longdesc"] = ""
+
+ if options.has_key("--help"):
+ usage(device_opt)
+ sys.exit(0)
+
+ if options.get("--action", "") == "metadata":
+ if "port_as_ip" in device_opt:
+ device_opt.remove("separator")
+ metadata(device_opt, docs)
+ sys.exit(0)
+
+ if options.has_key("--version"):
+ print __main__.RELEASE_VERSION, __main__.BUILD_DATE
+ print __main__.REDHAT_COPYRIGHT
+ sys.exit(0)
+
+def fence_action(connection, options, set_power_fn, get_power_fn, get_outlet_list=None, reboot_cycle_fn=None):
+ result = 0
+
+ try:
+ if options.has_key("--plug"):
+ options["--plugs"] = options["--plug"].split(",")
+
+ ## Process options that manipulate fencing device
+ #####
+ if (options["--action"] in ["list", "list-status"]) or \
+ ((options["--action"] == "monitor") and 1 == options["device_opt"].count("port") and \
+ 0 == options["device_opt"].count("port_as_ip")):
+
+ if 0 == options["device_opt"].count("port"):
+ print "N/A"
+ elif get_outlet_list == None:
+ ## @todo: exception?
+ ## This is just temporal solution, we will remove default value
+ ## None as soon as all existing agent will support this operation
+ print "NOTICE: List option is not working on this device yet"
+ else:
+ options["--original-action"] = options["--action"]
+ options["--action"] = "list"
+ outlets = get_outlet_list(connection, options)
+ options["--action"] = options["--original-action"]
+ del options["--original-action"]
+
+ ## keys can be numbers (port numbers) or strings (names of VM, UUID)
+ for outlet_id in outlets.keys():
+ (alias, status) = outlets[outlet_id]
+ if status is None or (not status.upper() in ["ON", "OFF"]):
+ status = "UNKNOWN"
+ status = status.upper()
+
+ if options["--action"] == "list":
+ print outlet_id + options["--separator"] + alias
+ elif options["--action"] == "list-status":
+ print outlet_id + options["--separator"] + alias + options["--separator"] + status
+
+ return
+
+ if options["--action"] == "monitor" and not "port" in options["device_opt"] and "no_status" in options["device_opt"]:
+ # Unable to do standard monitoring because 'status' action is not available
+ return 0
+
+ status = None
+ if not "no_status" in options["device_opt"]:
+ status = get_multi_power_fn(connection, options, get_power_fn)
+ if status != "on" and status != "off":
+ fail(EC_STATUS)
+
+ if options["--action"] == status:
+ if not (status == "on" and "force_on" in options["device_opt"]):
+ print "Success: Already %s" % (status.upper())
+ return 0
+
+ if options["--action"] == "on":
+ if set_multi_power_fn(connection, options, set_power_fn, get_power_fn, 1 + int(options["--retry-on"])):
+ print "Success: Powered ON"
+ else:
+ fail(EC_WAITING_ON)
+ elif options["--action"] == "off":
+ if set_multi_power_fn(connection, options, set_power_fn, get_power_fn):
+ print "Success: Powered OFF"
+ else:
+ fail(EC_WAITING_OFF)
+ elif options["--action"] == "reboot":
+ power_on = False
+ if options.get("--method", "").lower() == "cycle" and reboot_cycle_fn is not None:
+ for _ in range(1, 1 + int(options["--retry-on"])):
+ if reboot_cycle_fn(connection, options):
+ power_on = True
+ break
+
+ if not power_on:
+ fail(EC_TIMED_OUT)
+
+ else:
+ if status != "off":
+ options["--action"] = "off"
+ if not set_multi_power_fn(connection, options, set_power_fn, get_power_fn):
+ fail(EC_WAITING_OFF)
+
+ options["--action"] = "on"
+
+ try:
+ power_on = set_multi_power_fn(connection, options, set_power_fn, get_power_fn, int(options["--retry-on"]))
+ except Exception, ex:
+ # an error occured during power ON phase in reboot
+ # fence action was completed succesfully even in that case
+ logging.warning("%s", str(ex))
+
+ if power_on == False:
+ # this should not fail as node was fenced succesfully
+ logging.error('Timed out waiting to power ON\n')
+
+ print "Success: Rebooted"
+ elif options["--action"] == "status":
+ print "Status: " + status.upper()
+ if status.upper() == "OFF":
+ result = 2
+ elif options["--action"] == "monitor":
+ pass
+ except pexpect.EOF:
+ fail(EC_CONNECTION_LOST)
+ except pexpect.TIMEOUT:
+ fail(EC_TIMED_OUT)
+ except pycurl.error, ex:
+ logging.error("%s\n", str(ex))
+ fail(EC_TIMED_OUT)
+ except socket.timeout, ex:
+ logging.error("%s\n", str(ex))
+ fail(EC_TIMED_OUT)
+
+ return result
+
+def fence_login(options, re_login_string=r"(login\s*: )|((?!Last )Login Name: )|(username: )|(User Name :)"):
+ run_delay(options)
+
+ if not options.has_key("eol"):
+ options["eol"] = "\r\n"
+
+ if options.has_key("--command-prompt") and type(options["--command-prompt"]) is not list:
+ options["--command-prompt"] = [options["--command-prompt"]]
+
+ try:
+ if options.has_key("--ssl"):
+ conn = _open_ssl_connection(options)
+ elif options.has_key("--ssh") and not options.has_key("--identity-file"):
+ conn = _login_ssh_with_password(options, re_login_string)
+ elif options.has_key("--ssh") and options.has_key("--identity-file"):
+ conn = _login_ssh_with_identity_file(options)
+ else:
+ conn = _login_telnet(options, re_login_string)
+ except pexpect.EOF, exception:
+ logging.debug("%s", str(exception))
+ fail(EC_LOGIN_DENIED)
+ except pexpect.TIMEOUT, exception:
+ logging.debug("%s", str(exception))
+ fail(EC_LOGIN_DENIED)
+ return conn
+
+def is_executable(path):
+ if os.path.exists(path):
+ stats = os.stat(path)
+ if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
+ return True
+ return False
+
+def run_command(options, command, timeout=None, env=None, log_command=None):
+ if timeout is None and "--power-timeout" in options:
+ timeout = options["--power-timeout"]
+ if timeout is not None:
+ timeout = float(timeout)
+
+ logging.info("Executing: %s\n", log_command or command)
+
+ try:
+ process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+ except OSError:
+ fail_usage("Unable to run %s\n" % command)
+
+ thread = threading.Thread(target=process.wait)
+ thread.start()
+ thread.join(timeout)
+ if thread.is_alive():
+ process.kill()
+ fail(EC_TIMED_OUT)
+
+ status = process.wait()
+
+ (pipe_stdout, pipe_stderr) = process.communicate()
+ process.stdout.close()
+ process.stderr.close()
+
+ logging.debug("%s %s %s\n", str(status), str(pipe_stdout), str(pipe_stderr))
+
+ return (status, pipe_stdout, pipe_stderr)
+
+def run_delay(options):
+ ## Delay is important for two-node clusters fencing but we do not need to delay 'status' operations
+ if options["--action"] in ["off", "reboot"]:
+ logging.info("Delay %s second(s) before logging in to the fence device", options["--delay"])
+ time.sleep(int(options["--delay"]))
+
+def fence_logout(conn, logout_string, sleep=0):
+ # Logout is not required part of fencing but we should attempt to do it properly
+ # In some cases our 'exit' command is faster and we can not close connection as it
+ # was already closed by fencing device
+ try:
+ conn.send_eol(logout_string)
+ time.sleep(sleep)
+ conn.close()
+ except exceptions.OSError:
+ pass
+ except pexpect.ExceptionPexpect:
+ pass
+
+# Convert array of format [[key1, value1], [key2, value2], ... [keyN, valueN]] to dict, where key is
+# in format a.b.c.d...z and returned dict has key only z
+def array_to_dict(array):
+ return dict([[x[0].split(".")[-1], x[1]] for x in array])
+
+## Own logger handler that uses old-style syslog handler as otherwise everything is sourced
+## from /dev/syslog
+class SyslogLibHandler(logging.StreamHandler):
+ """
+ A handler class that correctly push messages into syslog
+ """
+ def emit(self, record):
+ syslog_level = {
+ logging.CRITICAL:syslog.LOG_CRIT,
+ logging.ERROR:syslog.LOG_ERR,
+ logging.WARNING:syslog.LOG_WARNING,
+ logging.INFO:syslog.LOG_INFO,
+ logging.DEBUG:syslog.LOG_DEBUG,
+ logging.NOTSET:syslog.LOG_DEBUG,
+ }[record.levelno]
+
+ msg = self.format(record)
+
+ # syslos.syslog can not have 0x00 character inside or exception is thrown
+ syslog.syslog(syslog_level, msg.replace("\x00", "\n"))
+ return
+
+def _open_ssl_connection(options):
+ gnutls_opts = ""
+ ssl_opts = ""
+
+ if options.has_key("--notls"):
+ gnutls_opts = "--priority \"NORMAL:-VERS-TLS1.2:-VERS-TLS1.1:-VERS-TLS1.0:+VERS-SSL3.0\""
+ elif options.has_key("--tls1.0"):
+ gnutls_opts = "--priority \"NORMAL:-VERS-TLS1.2:-VERS-TLS1.1:+VERS-TLS1.0:%LATEST_RECORD_VERSION\""
+
+ # --ssl is same as the --ssl-secure; it means we want to verify certificate in these cases
+ if options.has_key("--ssl-insecure"):
+ ssl_opts = "--insecure"
+
+ command = '%s %s %s --crlf -p %s %s' % \
+ (options["--gnutlscli-path"], gnutls_opts, ssl_opts, options["--ipport"], options["--ip"])
+ try:
+ conn = fspawn(options, command)
+ except pexpect.ExceptionPexpect, ex:
+ logging.error("%s\n", str(ex))
+ sys.exit(EC_GENERIC_ERROR)
+
+ return conn
+
+def _login_ssh_with_identity_file(options):
+ if options.has_key("--inet6-only"):
+ force_ipvx = "-6 "
+ elif options.has_key("--inet4-only"):
+ force_ipvx = "-4 "
+ else:
+ force_ipvx = ""
+
+ command = '%s %s %s@%s -i %s -p %s' % \
+ (options["--ssh-path"], force_ipvx, options["--username"], options["--ip"], \
+ options["--identity-file"], options["--ipport"])
+ if options.has_key("--ssh-options"):
+ command += ' ' + options["--ssh-options"]
+
+ conn = fspawn(options, command)
+
+ result = conn.log_expect(["Enter passphrase for key '" + options["--identity-file"] + "':", \
+ "Are you sure you want to continue connecting (yes/no)?"] + \
+ options["--command-prompt"], int(options["--login-timeout"]))
+ if result == 1:
+ conn.sendline("yes")
+ result = conn.log_expect(
+ ["Enter passphrase for key '" + options["--identity-file"]+"':"] + \
+ options["--command-prompt"], int(options["--login-timeout"]))
+ if result == 0:
+ if options.has_key("--password"):
+ conn.sendline(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--login-timeout"]))
+ else:
+ fail_usage("Failed: You have to enter passphrase (-p) for identity file")
+
+ return conn
+
+def _login_telnet(options, re_login_string):
+ re_login = re.compile(re_login_string, re.IGNORECASE)
+ re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
+
+ conn = fspawn(options, options["--telnet-path"])
+ conn.send("set binary\n")
+ conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
+
+ conn.log_expect(re_login, int(options["--login-timeout"]))
+ conn.send_eol(options["--username"])
+
+ ## automatically change end of line separator
+ screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ if re_login.search(screen) != None:
+ options["eol"] = "\n"
+ conn.send_eol(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ elif re_pass.search(screen) == None:
+ conn.log_expect(re_pass, int(options["--shell-timeout"]))
+
+ try:
+ conn.send_eol(options["--password"])
+ valid_password = conn.log_expect([re_login] + \
+ options["--command-prompt"], int(options["--shell-timeout"]))
+ if valid_password == 0:
+ ## password is invalid or we have to change EOL separator
+ options["eol"] = "\r"
+ conn.send_eol("")
+ screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ ## after sending EOL the fence device can either show 'Login' or 'Password'
+ if re_login.search(conn.after + screen) != None:
+ conn.send_eol("")
+ conn.send_eol(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ conn.send_eol(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--login-timeout"]))
+ except KeyError:
+ fail(EC_PASSWORD_MISSING)
+
+ return conn
+
+def _login_ssh_with_password(options, re_login_string):
+ re_login = re.compile(re_login_string, re.IGNORECASE)
+ re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
+
+ if options.has_key("--inet6-only"):
+ force_ipvx = "-6 "
+ elif options.has_key("--inet4-only"):
+ force_ipvx = "-4 "
+ else:
+ force_ipvx = ""
+
+ command = '%s %s %s@%s -p %s -o PubkeyAuthentication=no' % \
+ (options["--ssh-path"], force_ipvx, options["--username"], options["--ip"], options["--ipport"])
+ if options.has_key("--ssh-options"):
+ command += ' ' + options["--ssh-options"]
+
+ conn = fspawn(options, command)
+
+ if options.has_key("telnet_over_ssh"):
+ # This is for stupid ssh servers (like ALOM) which behave more like telnet
+ # (ignore name and display login prompt)
+ result = conn.log_expect( \
+ [re_login, "Are you sure you want to continue connecting (yes/no)?"],
+ int(options["--login-timeout"]))
+ if result == 1:
+ conn.sendline("yes") # Host identity confirm
+ conn.log_expect(re_login, int(options["--login-timeout"]))
+
+ conn.sendline(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ else:
+ result = conn.log_expect( \
+ ["ssword:", "Are you sure you want to continue connecting (yes/no)?"],
+ int(options["--login-timeout"]))
+ if result == 1:
+ conn.sendline("yes")
+ conn.log_expect("ssword:", int(options["--login-timeout"]))
+
+ conn.sendline(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--login-timeout"]))
+
+ return conn
+
+#
+# To update metadata, we change values in all_opt
+def _update_metadata(options):
+ device_opt = options["device_opt"]
+
+ if device_opt.count("login") and device_opt.count("no_login") == 0:
+ all_opt["login"]["required"] = "1"
+ else:
+ all_opt["login"]["required"] = "0"
+
+ if device_opt.count("port_as_ip"):
+ all_opt["ipaddr"]["required"] = "0"
+ all_opt["port"]["required"] = "0"
+
+ (available_actions, default_value) = _get_available_actions(device_opt)
+ all_opt["action"]["default"] = default_value
+
+ actions_with_default = \
+ [x if not x == all_opt["action"]["default"] else x + " (default)" for x in available_actions]
+ all_opt["action"]["help"] = \
+ "-o, --action=[action] Action: %s" % (_join_wrap(actions_with_default, last_separator=" or "))
+
+ if device_opt.count("ipport"):
+ default_value = None
+ default_string = None
+
+ if all_opt["ipport"].has_key("default"):
+ default_value = all_opt["ipport"]["default"]
+ elif device_opt.count("web") and device_opt.count("ssl"):
+ default_value = "80"
+ default_string = "(default 80, 443 if --ssl option is used)"
+ elif device_opt.count("telnet") and device_opt.count("secure"):
+ default_value = "23"
+ default_string = "(default 23, 22 if --ssh option is used)"
+ else:
+ tcp_ports = {"community" : "161", "secure" : "22", "telnet" : "23", "web" : "80", "ssl" : "443"}
+ # all cases where next command returns multiple results are covered by previous blocks
+ protocol = [x for x in ["community", "secure", "ssl", "web", "telnet"] if device_opt.count(x)][0]
+ default_value = tcp_ports[protocol]
+
+ if default_string is None:
+ all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default %s)" % \
+ (default_value)
+ else:
+ all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use\n" + " "*40 + default_string
+
+def _set_default_values(options):
+ if "ipport" in options["device_opt"]:
+ if not "--ipport" in options:
+ if "default" in all_opt["ipport"]:
+ options["--ipport"] = all_opt["ipport"]["default"]
+ elif "community" in options["device_opt"]:
+ options["--ipport"] = "161"
+ elif "--ssh" in options or all_opt["secure"].get("default", "0") == "1":
+ options["--ipport"] = "22"
+ elif "--ssl" in options or all_opt["ssl"].get("default", "0") == "1":
+ options["--ipport"] = "443"
+ elif "--ssl-secure" in options or all_opt["ssl_secure"].get("default", "0") == "1":
+ options["--ipport"] = "443"
+ elif "--ssl-insecure" in options or all_opt["ssl_insecure"].get("default", "0") == "1":
+ options["--ipport"] = "443"
+ elif "web" in options["device_opt"]:
+ options["--ipport"] = "80"
+ elif "telnet" in options["device_opt"]:
+ options["--ipport"] = "23"
+
+ if "--ipport" in options:
+ all_opt["ipport"]["default"] = options["--ipport"]
+
+ for opt in options["device_opt"]:
+ if all_opt[opt].has_key("default") and not opt == "ipport":
+ getopt_long = "--" + all_opt[opt]["longopt"]
+ if not options.has_key(getopt_long):
+ options[getopt_long] = all_opt[opt]["default"]
+
+ return options
+
+# stop = True/False : exit fence agent when problem is encountered
+def _validate_input(options, stop = True):
+ device_opt = options["device_opt"]
+ valid_input = True
+
+ if not options.has_key("--username") and \
+ device_opt.count("login") and (device_opt.count("no_login") == 0):
+ valid_input = False
+ fail_usage("Failed: You have to set login name", stop)
+
+ if device_opt.count("ipaddr") and not options.has_key("--ip") and not options.has_key("--managed"):
+ valid_input = False
+ fail_usage("Failed: You have to enter fence address", stop)
+
+ if device_opt.count("no_password") == 0:
+ if 0 == device_opt.count("identity_file"):
+ if not (options.has_key("--password") or options.has_key("--password-script")):
+ valid_input = False
+ fail_usage("Failed: You have to enter password or password script", stop)
+ else:
+ if not (options.has_key("--password") or \
+ options.has_key("--password-script") or options.has_key("--identity-file")):
+ valid_input = False
+ fail_usage("Failed: You have to enter password, password script or identity file", stop)
+
+ if not options.has_key("--ssh") and options.has_key("--identity-file"):
+ valid_input = False
+ fail_usage("Failed: You have to use identity file together with ssh connection (-x)", stop)
+
+ if options.has_key("--identity-file") and not os.path.isfile(options["--identity-file"]):
+ valid_input = False
+ fail_usage("Failed: Identity file " + options["--identity-file"] + " does not exist", stop)
+
+ if (0 == ["list", "list-status", "monitor"].count(options["--action"])) and \
+ not options.has_key("--plug") and device_opt.count("port") and \
+ device_opt.count("no_port") == 0 and not device_opt.count("port_as_ip"):
+ valid_input = False
+ fail_usage("Failed: You have to enter plug number or machine identification", stop)
+
+ if options.has_key("--plug") and len(options["--plug"].split(",")) > 1 and \
+ options.has_key("--method") and options["--method"] == "cycle":
+ valid_input = False
+ fail_usage("Failed: Cannot use --method cycle for more than 1 plug", stop)
+
+ for failed_opt in _get_opts_with_invalid_choices(options):
+ valid_input = False
+ fail_usage("Failed: You have to enter a valid choice for %s from the valid values: %s" % \
+ ("--" + all_opt[failed_opt]["longopt"], str(all_opt[failed_opt]["choices"])), stop)
+
+ return valid_input
+
+def _encode_html_entities(text):
+ return text.replace("&", "&amp;").replace('"', "&quot;").replace('<', "&lt;"). \
+ replace('>', "&gt;").replace("'", "&apos;")
+
+def _prepare_getopt_args(options):
+ getopt_string = ""
+ longopt_list = []
+ for k in options:
+ if all_opt.has_key(k) and all_opt[k]["getopt"] != ":":
+ # getopt == ":" means that opt is without short getopt, but has value
+ getopt_string += all_opt[k]["getopt"]
+ elif not all_opt.has_key(k):
+ fail_usage("Parse error: unknown option '"+k+"'")
+
+ if all_opt.has_key(k) and all_opt[k].has_key("longopt"):
+ if all_opt[k]["getopt"].endswith(":"):
+ longopt_list.append(all_opt[k]["longopt"] + "=")
+ else:
+ longopt_list.append(all_opt[k]["longopt"])
+
+ return (getopt_string, longopt_list)
+
+def _parse_input_stdin(avail_opt):
+ opt = {}
+ name = ""
+ for line in sys.stdin.readlines():
+ line = line.strip()
+ if (line.startswith("#")) or (len(line) == 0):
+ continue
+
+ (name, value) = (line + "=").split("=", 1)
+ value = value[:-1]
+
+ if avail_opt.count(name) == 0 and name in ["nodename"]:
+ continue
+ elif avail_opt.count(name) == 0:
+ logging.warning("Parse error: Ignoring unknown option '%s'\n", line)
+ continue
+
+ if all_opt[name]["getopt"].endswith(":"):
+ opt["--"+all_opt[name]["longopt"].rstrip(":")] = value
+ elif value.lower() in ["1", "yes", "on", "true"]:
+ opt["--"+all_opt[name]["longopt"]] = "1"
+ else:
+ logging.warning("Parse error: Ignoring option '%s' because it does not have value\n", name)
+ return opt
+
+def _parse_input_cmdline(avail_opt):
+ filtered_opts = {}
+ _verify_unique_getopt(avail_opt)
+ (getopt_string, longopt_list) = _prepare_getopt_args(avail_opt)
+
+ try:
+ (entered_opt, left_arg) = getopt.gnu_getopt(sys.argv[1:], getopt_string, longopt_list)
+ if len(left_arg) > 0:
+ logging.warning("Unused arguments on command line: %s" % (str(left_arg)))
+ except getopt.GetoptError, error:
+ fail_usage("Parse error: " + error.msg)
+
+ for opt in avail_opt:
+ filtered_opts.update({opt : all_opt[opt]})
+
+ # Short and long getopt names are changed to consistent "--" + long name (e.g. --username)
+ long_opts = {}
+ for arg_name in dict(entered_opt).keys():
+ all_key = [key for (key, value) in filtered_opts.items() \
+ if "--" + value.get("longopt", "") == arg_name or "-" + value.get("getopt", "").rstrip(":") == arg_name][0]
+ long_opts["--" + filtered_opts[all_key]["longopt"]] = dict(entered_opt)[arg_name]
+
+ # This test is specific because it does not apply to input on stdin
+ if "port_as_ip" in avail_opt and not "--port-as-ip" in long_opts and "--plug" in long_opts:
+ fail_usage("Parser error: option -n/--plug is not recognized")
+
+ return long_opts
+
+# for ["John", "Mary", "Eli"] returns "John, Mary and Eli"
+def _join2(words, normal_separator=", ", last_separator=" and "):
+ if len(words) <= 1:
+ return "".join(words)
+ else:
+ return last_separator.join([normal_separator.join(words[:-1]), words[-1]])
+
+def _join_wrap(words, normal_separator=", ", last_separator=" and ", first_indent=42):
+ x = _join2(words, normal_separator, last_separator)
+ wrapper = textwrap.TextWrapper()
+ wrapper.initial_indent = " "*first_indent
+ wrapper.subsequent_indent = " "*40
+ wrapper.width = 85
+ wrapper.break_on_hyphens = False
+ wrapper.break_long_words = False
+ wrapped_text = ""
+ for line in wrapper.wrap(x):
+ wrapped_text += line + "\n"
+ return wrapped_text.lstrip().rstrip("\n")
+
+def _get_opts_with_invalid_choices(options):
+ options_failed = []
+ device_opt = options["device_opt"]
+
+ for opt in device_opt:
+ if all_opt[opt].has_key("choices"):
+ longopt = "--" + all_opt[opt]["longopt"]
+ possible_values_upper = [y.upper() for y in all_opt[opt]["choices"]]
+ if options.has_key(longopt):
+ options[longopt] = options[longopt].upper()
+ if not options["--" + all_opt[opt]["longopt"]] in possible_values_upper:
+ options_failed.append(opt)
+ return options_failed
+
+def _verify_unique_getopt(avail_opt):
+ used_getopt = set()
+
+ for opt in avail_opt:
+ getopt_value = all_opt[opt].get("getopt", "").rstrip(":")
+ if getopt_value and getopt_value in used_getopt:
+ fail_usage("Short getopt for %s (-%s) is not unique" % (opt, getopt_value))
+ else:
+ used_getopt.add(getopt_value)
+
+def _get_available_actions(device_opt):
+ available_actions = ["on", "off", "reboot", "status", "list", "list-status", \
+ "monitor", "metadata", "validate-all"]
+ default_value = "reboot"
+
+ if device_opt.count("fabric_fencing"):
+ available_actions.remove("reboot")
+ default_value = "off"
+ if device_opt.count("no_status"):
+ available_actions.remove("status")
+ if device_opt.count("no_on"):
+ available_actions.remove("on")
+ if device_opt.count("no_off"):
+ available_actions.remove("off")
+ if not device_opt.count("separator"):
+ available_actions.remove("list")
+ available_actions.remove("list-status")
+
+ return (available_actions, default_value)
diff --git a/agents/aws/fence_aws.py b/agents/aws/fence_aws.py
new file mode 100644
index 0000000..c947bf2
--- /dev/null
+++ b/agents/aws/fence_aws.py
@@ -0,0 +1,223 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, run_delay, EC_STATUS, SyslogLibHandler
+
+import requests
+from requests import HTTPError
+
+try:
+ import boto3
+ from botocore.exceptions import ConnectionError, ClientError, EndpointConnectionError, NoRegionError
+except ImportError:
+ pass
+
+logger = logging.getLogger("fence_aws")
+logger.propagate = False
+logger.setLevel(logging.INFO)
+logger.addHandler(SyslogLibHandler())
+logging.getLogger('botocore.vendored').propagate = False
+
+def get_instance_id():
+ try:
+ token = requests.put('http://169.254.169.254/latest/api/token', headers={"X-aws-ec2-metadata-token-ttl-seconds" : "21600"}).content.decode("UTF-8")
+ r = requests.get('http://169.254.169.254/latest/meta-data/instance-id', headers={"X-aws-ec2-metadata-token" : token}).content.decode("UTF-8")
+ return r
+ except HTTPError as http_err:
+ logger.error('HTTP error occurred while trying to access EC2 metadata server: %s', http_err)
+ except Exception as err:
+ logger.error('A fatal error occurred while trying to access EC2 metadata server: %s', err)
+ return None
+
+
+def get_nodes_list(conn, options):
+ logger.info("Starting monitor operation")
+ result = {}
+ try:
+ if "--filter" in options:
+ filter_key = options["--filter"].split("=")[0].strip()
+ filter_value = options["--filter"].split("=")[1].strip()
+ filter = [{ "Name": filter_key, "Values": [filter_value] }]
+ for instance in conn.instances.filter(Filters=filter):
+ result[instance.id] = ("", None)
+ else:
+ for instance in conn.instances.all():
+ result[instance.id] = ("", None)
+ except ClientError:
+ fail_usage("Failed: Incorrect Access Key or Secret Key.")
+ except EndpointConnectionError:
+ fail_usage("Failed: Incorrect Region.")
+ except ConnectionError as e:
+ fail_usage("Failed: Unable to connect to AWS: " + str(e))
+ except Exception as e:
+ logger.error("Failed to get node list: %s", e)
+ logger.debug("Monitor operation OK: %s",result)
+ return result
+
+def get_power_status(conn, options):
+ logger.debug("Starting status operation")
+ try:
+ instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [options["--plug"]]}])
+ state = list(instance)[0].state["Name"]
+ logger.info("Status operation for EC2 instance %s returned state: %s",options["--plug"],state.upper())
+ if state == "running":
+ return "on"
+ elif state == "stopped":
+ return "off"
+ else:
+ return "unknown"
+
+ except ClientError:
+ fail_usage("Failed: Incorrect Access Key or Secret Key.")
+ except EndpointConnectionError:
+ fail_usage("Failed: Incorrect Region.")
+ except IndexError:
+ fail(EC_STATUS)
+ except Exception as e:
+ logging.error("Failed to get power status: %s", e)
+ fail(EC_STATUS)
+
+def get_self_power_status(conn, instance_id):
+ try:
+ instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [instance_id]}])
+ state = list(instance)[0].state["Name"]
+ if state == "running":
+ logging.debug("Captured my (%s) state and it %s - returning OK - Proceeding with fencing",instance_id,state.upper())
+ return "ok"
+ else:
+ logging.debug("Captured my (%s) state it is %s - returning Alert - Unable to fence other nodes",instance_id,state.upper())
+ return "alert"
+
+ except ClientError:
+ fail_usage("Failed: Incorrect Access Key or Secret Key.")
+ except EndpointConnectionError:
+ fail_usage("Failed: Incorrect Region.")
+ except IndexError:
+ return "fail"
+
+def set_power_status(conn, options):
+ my_instance = get_instance_id()
+ try:
+ if (options["--action"]=="off"):
+ if (get_self_power_status(conn,my_instance) == "ok"):
+ conn.instances.filter(InstanceIds=[options["--plug"]]).stop(Force=True)
+ logger.info("Called StopInstance API call for %s", options["--plug"])
+ else:
+ logger.info("Skipping fencing as instance is not in running status")
+ elif (options["--action"]=="on"):
+ conn.instances.filter(InstanceIds=[options["--plug"]]).start()
+ except Exception as e:
+ logger.error("Failed to power %s %s: %s", \
+ options["--action"], options["--plug"], e)
+
+def define_new_opts():
+ all_opt["region"] = {
+ "getopt" : "r:",
+ "longopt" : "region",
+ "help" : "-r, --region=[region] Region, e.g. us-east-1",
+ "shortdesc" : "Region.",
+ "required" : "0",
+ "order" : 2
+ }
+ all_opt["access_key"] = {
+ "getopt" : "a:",
+ "longopt" : "access-key",
+ "help" : "-a, --access-key=[key] Access Key",
+ "shortdesc" : "Access Key.",
+ "required" : "0",
+ "order" : 3
+ }
+ all_opt["secret_key"] = {
+ "getopt" : "s:",
+ "longopt" : "secret-key",
+ "help" : "-s, --secret-key=[key] Secret Key",
+ "shortdesc" : "Secret Key.",
+ "required" : "0",
+ "order" : 4
+ }
+ all_opt["filter"] = {
+ "getopt" : ":",
+ "longopt" : "filter",
+ "help" : "--filter=[key=value] Filter (e.g. vpc-id=[vpc-XXYYZZAA]",
+ "shortdesc": "Filter for list-action",
+ "required": "0",
+ "order": 5
+ }
+ all_opt["boto3_debug"] = {
+ "getopt" : "b:",
+ "longopt" : "boto3_debug",
+ "help" : "-b, --boto3_debug=[option] Boto3 and Botocore library debug logging",
+ "shortdesc": "Boto Lib debug",
+ "required": "0",
+ "default": "False",
+ "order": 6
+ }
+
+# Main agent method
+def main():
+ conn = None
+
+ device_opt = ["port", "no_password", "region", "access_key", "secret_key", "filter", "boto3_debug"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["power_timeout"]["default"] = "60"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for AWS (Amazon Web Services)"
+ docs["longdesc"] = "fence_aws is an I/O Fencing agent for AWS (Amazon Web\
+Services). It uses the boto3 library to connect to AWS.\
+\n.P\n\
+boto3 can be configured with AWS CLI or by creating ~/.aws/credentials.\n\
+For instructions see: https://boto3.readthedocs.io/en/latest/guide/quickstart.html#configuration"
+ docs["vendorurl"] = "http://www.amazon.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if options.get("--verbose") is not None:
+ lh = logging.FileHandler('/var/log/fence_aws_debug.log')
+ logger.addHandler(lh)
+ lhf = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ lh.setFormatter(lhf)
+ logger.setLevel(logging.DEBUG)
+
+ if options["--boto3_debug"].lower() not in ["1", "yes", "on", "true"]:
+ boto3.set_stream_logger('boto3',logging.INFO)
+ boto3.set_stream_logger('botocore',logging.CRITICAL)
+ logging.getLogger('botocore').propagate = False
+ logging.getLogger('boto3').propagate = False
+ else:
+ log_format = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
+ logging.getLogger('botocore').propagate = False
+ logging.getLogger('boto3').propagate = False
+ fdh = logging.FileHandler('/var/log/fence_aws_boto3.log')
+ fdh.setFormatter(log_format)
+ logging.getLogger('boto3').addHandler(fdh)
+ logging.getLogger('botocore').addHandler(fdh)
+ logging.debug("Boto debug level is %s and sending debug info to /var/log/fence_aws_boto3.log", options["--boto3_debug"])
+
+ region = options.get("--region")
+ access_key = options.get("--access-key")
+ secret_key = options.get("--secret-key")
+ try:
+ conn = boto3.resource('ec2', region_name=region,
+ aws_access_key_id=access_key,
+ aws_secret_access_key=secret_key)
+ except Exception as e:
+ fail_usage("Failed: Unable to connect to AWS: " + str(e))
+
+ # Operate the fencing device
+ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/azure_arm/fence_azure_arm.py b/agents/azure_arm/fence_azure_arm.py
new file mode 100755
index 0000000..6908169
--- /dev/null
+++ b/agents/azure_arm/fence_azure_arm.py
@@ -0,0 +1,260 @@
+#!@PYTHON@ -tt
+
+import sys, re, pexpect
+import logging
+import atexit
+import xml.etree.ElementTree as ET
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, run_command, run_delay
+import azure_fence
+
+def get_nodes_list(clients, options):
+ result = {}
+
+ if clients:
+ compute_client = clients[0]
+ rgName = options["--resourceGroup"]
+ vms = compute_client.virtual_machines.list(rgName)
+ try:
+ for vm in vms:
+ result[vm.name] = ("", None)
+ except Exception as e:
+ fail_usage("Failed: %s" % e)
+
+ return result
+
+def check_unfence(clients, options):
+ if clients:
+ compute_client = clients[0]
+ network_client = clients[1]
+ rgName = options["--resourceGroup"]
+
+ try:
+ vms = compute_client.virtual_machines.list(rgName)
+ except Exception as e:
+ fail_usage("Failed: %s" % e)
+
+ for vm in vms:
+ vmName = vm.name
+ if azure_fence.get_network_state(compute_client, network_client, rgName, vmName) == "off":
+ logging.info("Found fenced node " + vmName)
+ # dont return "off" based on network-fencing status
+ options.pop("--network-fencing", None)
+ options["--plug"] = vmName
+ if get_power_status(clients, options) == "off":
+ logging.info("Unfencing " + vmName)
+ options["--network-fencing"] = ""
+ options["--action"] = "on"
+ set_power_status(clients, options)
+ options["--action"] = "monitor"
+
+def get_power_status(clients, options):
+ vmstate = { "running": "on",
+ "deallocated": "off",
+ "stopped": "off" }
+ logging.info("getting power status for VM " + options["--plug"])
+
+ if clients:
+ compute_client = clients[0]
+ rgName = options["--resourceGroup"]
+ vmName = options["--plug"]
+
+ if "--network-fencing" in options:
+ network_client = clients[1]
+ netState = azure_fence.get_network_state(compute_client, network_client, rgName, vmName)
+ logging.info("Found network state of VM: " + netState)
+
+ # return off quickly once network is fenced instead of waiting for vm state to change
+ if options["--action"] == "off" and netState == "off":
+ logging.info("Network fenced for " + vmName)
+ return netState
+
+ powerState = "unknown"
+ try:
+ vmStatus = compute_client.virtual_machines.get(rgName, vmName, "instanceView")
+ except Exception as e:
+ fail_usage("Failed: %s" % e)
+
+ for status in vmStatus.instance_view.statuses:
+ if status.code.startswith("PowerState"):
+ powerState = status.code.split("/")[1]
+ break
+
+ vmState = vmstate.get(powerState, "unknown")
+ logging.info("Found power state of VM: %s (%s)" % (vmState, powerState))
+
+ if "--network-fencing" in options and netState == "off":
+ return "off"
+
+ if options["--action"] != "on" and vmState != "off":
+ return "on"
+
+ if vmState == "on":
+ return "on"
+
+ return "off"
+
+def set_power_status(clients, options):
+ logging.info("setting power status for VM " + options["--plug"] + " to " + options["--action"])
+
+ if clients:
+ compute_client = clients[0]
+ rgName = options["--resourceGroup"]
+ vmName = options["--plug"]
+
+ if "--network-fencing" in options:
+ network_client = clients[1]
+
+ if (options["--action"]=="off"):
+ logging.info("Fencing network for " + vmName)
+ azure_fence.set_network_state(compute_client, network_client, rgName, vmName, "block")
+ elif (options["--action"]=="on"):
+ logging.info("Unfencing network for " + vmName)
+ azure_fence.set_network_state(compute_client, network_client, rgName, vmName, "unblock")
+
+ if (options["--action"]=="off"):
+ logging.info("Poweroff " + vmName + " in resource group " + rgName)
+ try:
+ # try new API version first
+ compute_client.virtual_machines.begin_power_off(rgName, vmName, skip_shutdown=True)
+ except AttributeError:
+ # use older API verson if it fails
+ logging.debug("Poweroff " + vmName + " did not work via 'virtual_machines.begin_power_off. Trying virtual_machines.power_off'.")
+ compute_client.virtual_machines.power_off(rgName, vmName, skip_shutdown=True)
+ elif (options["--action"]=="on"):
+ logging.info("Starting " + vmName + " in resource group " + rgName)
+ try:
+ # try new API version first
+ compute_client.virtual_machines.begin_start(rgName, vmName)
+ except AttributeError:
+ # use older API verson if it fails
+ logging.debug("Starting " + vmName + " did not work via 'virtual_machines.begin_start. Trying virtual_machines.start'.")
+ compute_client.virtual_machines.start(rgName, vmName)
+
+
+def define_new_opts():
+ all_opt["resourceGroup"] = {
+ "getopt" : ":",
+ "longopt" : "resourceGroup",
+ "help" : "--resourceGroup=[name] Name of the resource group",
+ "shortdesc" : "Name of resource group. Metadata service is used if the value is not provided.",
+ "required" : "0",
+ "order" : 2
+ }
+ all_opt["tenantId"] = {
+ "getopt" : ":",
+ "longopt" : "tenantId",
+ "help" : "--tenantId=[name] Id of the Azure Active Directory tenant",
+ "shortdesc" : "Id of Azure Active Directory tenant.",
+ "required" : "0",
+ "order" : 3
+ }
+ all_opt["subscriptionId"] = {
+ "getopt" : ":",
+ "longopt" : "subscriptionId",
+ "help" : "--subscriptionId=[name] Id of the Azure subscription",
+ "shortdesc" : "Id of the Azure subscription. Metadata service is used if the value is not provided.",
+ "required" : "0",
+ "order" : 4
+ }
+ all_opt["network-fencing"] = {
+ "getopt" : "",
+ "longopt" : "network-fencing",
+ "help" : "--network-fencing Use network fencing. See NOTE-section of\n\
+ metadata for required Subnet/Network Security\n\
+ Group configuration.",
+ "shortdesc" : "Use network fencing. See NOTE-section for configuration.",
+ "required" : "0",
+ "order" : 5
+ }
+ all_opt["msi"] = {
+ "getopt" : "",
+ "longopt" : "msi",
+ "help" : "--msi Use Managed Service Identity instead of\n\
+ username and password. If specified,\n\
+ parameters tenantId, login and passwd are not\n\
+ allowed.",
+ "shortdesc" : "Determines if Managed Service Identity should be used.",
+ "required" : "0",
+ "order" : 6
+ }
+ all_opt["cloud"] = {
+ "getopt" : ":",
+ "longopt" : "cloud",
+ "help" : "--cloud=[name] Name of the cloud you want to use. Supported\n\
+ values are china, germany or usgov. Do not use\n\
+ this parameter if you want to use public\n\
+ Azure.",
+ "shortdesc" : "Name of the cloud you want to use.",
+ "required" : "0",
+ "order" : 7
+ }
+
+# Main agent method
+def main():
+ compute_client = None
+ network_client = None
+
+ device_opt = ["login", "no_login", "no_password", "passwd", "port", "resourceGroup", "tenantId", "subscriptionId", "network-fencing", "msi", "cloud"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["power_timeout"]["default"] = "150"
+
+ all_opt["login"]["help"] = "-l, --username=[appid] Application ID"
+ all_opt["passwd"]["help"] = "-p, --password=[authkey] Authentication key"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Azure Resource Manager"
+ docs["longdesc"] = "fence_azure_arm is an I/O Fencing agent for Azure Resource Manager. It uses Azure SDK for Python to connect to Azure.\
+\n.P\n\
+For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal\
+\n.P\n\
+Username and password are application ID and authentication key from \"App registrations\".\
+\n.P\n\
+NOTE: NETWORK FENCING\n.br\n\
+Network fencing requires an additional Subnet named \"fence-subnet\" for the Virtual Network using a Network Security Group with the following rules:\n.br\n\
++-----------+-----+-------------------------+------+------+-----+-----+--------+\n.br\n\
+| DIRECTION | PRI | NAME | PORT | PROT | SRC | DST | ACTION |\n.br\n\
++-----------+-----+-------------------------+------+------+-----+-----+--------+\n.br\n\
+| Inbound | 100 | FENCE_DENY_ALL_INBOUND | Any | Any | Any | Any | Deny |\n.br\n\
+| Outbound | 100 | FENCE_DENY_ALL_OUTBOUND | Any | Any | Any | Any | Deny |\n.br\n\
++-----------+-----+-------------------------+------+------+-----+-----+--------+\
+\n.P\n\
+When using network fencing the reboot-action will cause a quick-return once the network has been fenced (instead of waiting for the off-action to succeed). It will check the status during the monitor-action, and request power-on when the shutdown operation is complete."
+ docs["vendorurl"] = "http://www.microsoft.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ try:
+ config = azure_fence.get_azure_config(options)
+ options["--resourceGroup"] = config.RGName
+ compute_client = azure_fence.get_azure_compute_client(config)
+ if "--network-fencing" in options:
+ network_client = azure_fence.get_azure_network_client(config)
+ except ImportError:
+ fail_usage("Azure Resource Manager Python SDK not found or not accessible")
+ except Exception as e:
+ fail_usage("Failed: %s" % re.sub("^, ", "", str(e)))
+
+ if "--network-fencing" in options:
+ # use off-action to quickly return off once network is fenced instead of
+ # waiting for vm state to change
+ if options["--action"] == "reboot":
+ options["--action"] = "off"
+ # check for devices to unfence in monitor-action
+ elif options["--action"] == "monitor":
+ check_unfence([compute_client, network_client], options)
+
+ # Operate the fencing device
+ result = fence_action([compute_client, network_client], options, set_power_status, get_power_status, get_nodes_list)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/bladecenter/fence_bladecenter.py b/agents/bladecenter/fence_bladecenter.py
new file mode 100644
index 0000000..d670367
--- /dev/null
+++ b/agents/bladecenter/fence_bladecenter.py
@@ -0,0 +1,105 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Model Firmware
+## +--------------------+---------------------------+
+## (1) Main application BRET85K, rev 16
+## Boot ROM BRBR67D, rev 16
+## Remote Control BRRG67D, rev 16
+##
+#####
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS, EC_GENERIC_ERROR
+
+def get_power_status(conn, options):
+ node_cmd = r"system:blade\[" + options["--plug"] + r"\]>"
+
+ conn.send_eol("env -T system:blade[" + options["--plug"] + "]")
+ i = conn.log_expect([node_cmd, "system>"], int(options["--shell-timeout"]))
+ if i == 1:
+ ## Given blade number does not exist
+ if "--missing-as-off" in options:
+ return "off"
+ else:
+ fail(EC_STATUS)
+ conn.send_eol("power -state")
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+ status = conn.before.splitlines()[-1]
+ conn.send_eol("env -T system")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ return status.lower().strip()
+
+def set_power_status(conn, options):
+ node_cmd = r"system:blade\[" + options["--plug"] + r"\]>"
+
+ conn.send_eol("env -T system:blade[" + options["--plug"] + "]")
+ i = conn.log_expect([node_cmd, "system>"], int(options["--shell-timeout"]))
+ if i == 1:
+ ## Given blade number does not exist
+ if "--missing-as-off" in options:
+ return
+ else:
+ fail(EC_GENERIC_ERROR)
+
+ conn.send_eol("power -"+options["--action"])
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+ conn.send_eol("env -T system")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_blades_list(conn, options):
+ outlets = {}
+
+ node_cmd = "system>"
+
+ conn.send_eol("env -T system")
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+ conn.send_eol("list -l 2")
+ conn.log_expect(node_cmd, int(options["--shell-timeout"]))
+
+ lines = conn.before.split("\r\n")
+ filter_re = re.compile(r"^\s*blade\[(\d+)\]\s+(.*?)\s*$")
+ for blade_line in lines:
+ res = filter_re.search(blade_line)
+ if res != None:
+ outlets[res.group(1)] = (res.group(2), "")
+
+ return outlets
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "missing_as_off", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["power_wait"]["default"] = "10"
+ all_opt["cmd_prompt"]["default"] = ["system>"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM BladeCenter"
+ docs["longdesc"] = "fence_bladecenter is an I/O Fencing agent \
+which can be used with IBM Bladecenters with recent enough firmware that \
+includes telnet support. It logs into a Brocade chasis via telnet or ssh \
+and uses the command line interface to power on and off blades."
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ######
+ conn = fence_login(options, "(username\s*:\s*)")
+ result = fence_action(conn, options, set_power_status, get_power_status, get_blades_list)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/brocade/fence_brocade.py b/agents/brocade/fence_brocade.py
new file mode 100644
index 0000000..9f413db
--- /dev/null
+++ b/agents/brocade/fence_brocade.py
@@ -0,0 +1,72 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "portCfgPersistentEnable",
+ 'off': "portCfgPersistentDisable"
+ }[options["--action"]]
+
+ conn.send_eol(action + " " + options["--plug"])
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def get_power_status(conn, options):
+ line_re = re.compile(r'=========', re.IGNORECASE)
+ outlets = {}
+ in_index = False
+
+ conn.send_eol("switchshow")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ for line in str(conn.before).split("\n"):
+ if line_re.search(line):
+ in_index = True
+ elif in_index and line.lstrip()[0].isdigit():
+ tokens = line.lstrip().split()
+ status = "off" if len(tokens) > 7 and tokens[7] == "Disabled" else "on"
+ outlets[tokens[0]] = ("", status)
+
+ if ["list", "monitor"].count(options["--action"]) == 0:
+ (_, status) = outlets[options["--plug"]]
+ return status
+ else:
+ return outlets
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "fabric_fencing", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["> "]
+
+ options = check_input(device_opt, process_input(device_opt))
+ options["eol"] = "\n"
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP Brocade over telnet/ssh"
+ docs["longdesc"] = "fence_brocade is an I/O Fencing agent which can be used with Brocade FC switches. \
+It logs into a Brocade switch via telnet and disables a specified port. Disabling the port which a machine is \
+connected to effectively fences that machine. Lengthy telnet connections to the switch should be avoided while \
+a GFS cluster is running because the connection will block any necessary fencing actions. \
+\
+After a fence operation has taken place the fenced machine can no longer connect to the Brocade FC switch. \
+When the fenced machine is ready to be brought back into the GFS cluster (after reboot) the port on the Brocade \
+FC switch needs to be enabled. This can be done by running fence_brocade and specifying the enable action"
+ docs["vendorurl"] = "http://www.brocade.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/cdu/fence_cdu.py b/agents/cdu/fence_cdu.py
new file mode 100644
index 0000000..483ac51
--- /dev/null
+++ b/agents/cdu/fence_cdu.py
@@ -0,0 +1,176 @@
+#!@PYTHON@ -tt
+# fence_cdu - fence agent for a Sentry Switch CDU.
+#
+# Copyright (C) 2012 Canonical Ltd.
+# Copyright (C) 2021 SUSE Linux GmbH <trenn@suse.de>
+#
+# Authors: Andres Rodriguez <andres.rodriguez@canonical.com>
+# Thomas Renninger <trenn@suse.de>
+#
+# 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, version 3 of the License.
+#
+# 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/>.
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Model Firmware
+## +---------------------------------------------+
+## Sentry Switched CDU 6a
+## Sentry Switched CDU 7.1c <trenn@suse.de>
+## Sentry Switched CDU 7.1f <trenn@suse.de>
+## Sentry Switched PDU 8.0i <trenn@suse.de>
+##
+##
+#####
+
+import sys, re, pexpect, atexit, logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_TIMED_OUT, run_command, frun, EC_STATUS
+
+def get_power_status(conn, options):
+ exp_result = 0
+ outlets = {}
+ try:
+ if options["api-version"] == "8":
+ conn.send("STATUS ALL\r\n")
+ else:
+ conn.send("STATUS\r\n")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+ if options["api-version"] == "8":
+ # AA13 Arm-Console3 Wake On On Normal
+ # AA14 Master_Outlet_14 Wake On On Normal
+ show_re = re.compile('(\w+)\s+(\S+)\s+(On|Idle On|Off|Wake On)\s+(On|Off)')
+ else:
+ # .A12 TowerA_Outlet12 On Idle On
+ # .A12 test-01 On Idle On
+ show_re = re.compile('(\.\w+)\s+(\w+|\w+\W\w+)\s+(On|Off)\s+(On|Idle On|Off|Wake On)')
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ plug_id = res.group(1)
+ plug_name = res.group(2)
+ print(plug_name)
+ plug_state = res.group(3)
+ if options["api-version"] == "8":
+ plug_state = res.group(4)
+ outlets[plug_name] = (plug_id, plug_state)
+ except pexpect.EOF:
+ fail(EC_CONNECTION_LOST)
+ except pexpect.TIMEOUT:
+ fail(EC_TIMED_OUT)
+ try:
+ (_, status) = outlets[options["--plug"]]
+ return status.lower().strip()
+ except KeyError:
+ fail(EC_STATUS)
+
+def set_power_status(conn, options):
+ outlets = {}
+ action = { 'on' : "on", 'off': "off" }[options["--action"]]
+ try:
+ conn.send("LIST OUTLETS\r\n")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+ # if options["api-version"] == "8":
+ # AA13 Arm-Console3
+ # AA14 Master_Outlet_14
+ # else:
+ # .A12 TowerA_Outlet12
+ # .A12 test-01
+ show_re = re.compile('(\S+)\s+(\w+|\w+\W\w+)\s+')
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ outlets[res.group(2)] = (res.group(1))
+ conn.send(action + " " + outlets[options["--plug"]] + "\r\n")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ except pexpect.EOF:
+ fail(EC_CONNECTION_LOST)
+ except pexpect.TIMEOUT:
+ fail(EC_TIMED_OUT)
+
+def disconnect(conn):
+ conn.sendline("LOGOUT")
+ conn.close()
+
+def get_version(conn, options):
+ api_ver = "6"
+ sub = "a"
+ minor = ""
+ conn.send("VERSION\r\n")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+ show_re = re.compile('Sentry Switched [PC]DU Version (\d)(.\d|)(\w)\r')
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ api_ver = res.group(1)
+ if res.group(2):
+ sub = res.group(2).lstrip(".")
+ minor = res.group(3)
+ return (api_ver, sub, minor)
+
+def main():
+ device_opt = [ "ipaddr", "login", "port", "switch", "passwd", "telnet" ]
+
+ atexit.register(atexit_handler)
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ ##
+ ## Fence agent specific defaults
+ #####
+ options["--command-prompt"] = "Switched [PC]DU: "
+
+ docs = { }
+ docs["shortdesc"] = "Fence agent for a Sentry Switch CDU over telnet"
+ docs["longdesc"] = "fence_cdu is an I/O Fencing agent \
+which can be used with the Sentry Switch CDU. It logs into the device \
+via telnet and power's on/off an outlet."
+ docs["vendorurl"] = "http://www.servertech.com"
+ show_docs(options, docs)
+
+ ## Support for --plug [switch]:[plug] notation that was used before
+ opt_n = options.get("--plug")
+ if opt_n and (-1 != opt_n.find(":")):
+ (switch, plug) = opt_n.split(":", 1)
+ options["--switch"] = switch;
+ options["--plug"] = plug;
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ (api_ver, sub, minor) = get_version(conn, options)
+ options["api-version"] = api_ver
+ logging.debug("Using API version: %s" % api_ver)
+ if api_ver == "7":
+ # disable output paging
+ conn.sendline("set option more disabled")
+ conn.log_expect(options["--command-prompt"], int(options["--login-timeout"]))
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ ##
+ ## Logout from system
+ ##
+ ## In some special unspecified cases it is possible that
+ ## connection will be closed before we run close(). This is not
+ ## a problem because everything is checked before.
+ ######
+ atexit.register(disconnect, conn)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/cisco_mds/fence_cisco_mds.py b/agents/cisco_mds/fence_cisco_mds.py
new file mode 100644
index 0000000..fbb876a
--- /dev/null
+++ b/agents/cisco_mds/fence_cisco_mds.py
@@ -0,0 +1,94 @@
+#!@PYTHON@ -tt
+
+# The Following agent has been tested on:
+# - Cisco MDS UROS 9134 FC (1 Slot) Chassis ("1/2/4 10 Gbps FC/Supervisor-2") Motorola, e500v2
+# with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c)
+# - Cisco MDS 9124 (1 Slot) Chassis ("1/2/4 Gbps FC/Supervisor-2") Motorola, e500
+# with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c)
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, array_to_dict
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# Cisco admin status
+PORT_ADMIN_STATUS_OID = ".1.3.6.1.2.1.75.1.2.2.1.1"
+
+# IF-MIB trees for alias, status and port
+ALIASES_OID = ".1.3.6.1.2.1.31.1.1.1.18"
+PORTS_OID = ".1.3.6.1.2.1.2.2.1.2"
+
+### GLOBAL VARIABLES ###
+# OID converted from fc port name (fc(x)/(y))
+PORT_OID = ""
+
+### FUNCTIONS ###
+
+# Convert cisco port name (fc(x)/(y)) to OID
+def cisco_port2oid(port):
+ port = port.lower()
+
+ nums = re.match(r'^fc(\d+)/(\d+)$', port)
+
+ if nums and len(nums.groups()) == 2:
+ return "%s.%d.%d"% (PORT_ADMIN_STATUS_OID, int(nums.group(1))+21, int(nums.group(2))-1)
+ else:
+ fail_usage("Mangled port number: %s"%(port))
+
+def get_power_status(conn, options):
+ (_, status) = conn.get(PORT_OID)
+ return status == "1" and "on" or "off"
+
+def set_power_status(conn, options):
+ conn.set(PORT_OID, (options["--action"] == "on" and 1 or 2))
+
+def get_outlets_status(conn, options):
+ result = {}
+
+ res_fc = conn.walk(PORTS_OID, 30)
+ res_aliases = array_to_dict(conn.walk(ALIASES_OID, 30))
+
+ fc_re = re.compile(r'^"fc\d+/\d+"$')
+
+ for x in res_fc:
+ if fc_re.match(x[1]):
+ port_num = x[0].split('.')[-1]
+
+ port_name = x[1].strip('"')
+ port_alias = (port_num in res_aliases and res_aliases[port_num].strip('"') or "")
+ port_status = ""
+ result[port_name] = (port_alias, port_status)
+
+ return result
+
+# Main agent method
+def main():
+ global PORT_OID
+
+ device_opt = ["fabric_fencing", "ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Cisco MDS"
+ docs["longdesc"] = "fence_cisco_mds is an I/O Fencing agent \
+which can be used with any Cisco MDS 9000 series with SNMP enabled device."
+ docs["vendorurl"] = "http://www.cisco.com"
+ show_docs(options, docs)
+
+ if not options["--action"] in ["list", "monitor"]:
+ PORT_OID = cisco_port2oid(options["--plug"])
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/cisco_ucs/fence_cisco_ucs.py b/agents/cisco_ucs/fence_cisco_ucs.py
new file mode 100644
index 0000000..b85379a
--- /dev/null
+++ b/agents/cisco_ucs/fence_cisco_ucs.py
@@ -0,0 +1,198 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import pycurl, io
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS, EC_LOGIN_DENIED, run_delay
+
+RE_COOKIE = re.compile("<aaaLogin .* outCookie=\"(.*?)\"", re.IGNORECASE)
+RE_STATUS = re.compile("<lsPower .*? state=\"(.*?)\"", re.IGNORECASE)
+RE_GET_DN = re.compile(" dn=\"(.*?)\"", re.IGNORECASE)
+RE_GET_PNDN = re.compile(" pndn=\"(.*?)\"", re.IGNORECASE)
+RE_GET_DESC = re.compile(" descr=\"(.*?)\"", re.IGNORECASE)
+RE_GET_OPERPOWER = re.compile(" operPower=\"(.*?)\"", re.IGNORECASE)
+RE_GET_PRESENCE = re.compile(" presence=\"(.*?)\"", re.IGNORECASE)
+
+options_global = None
+
+def get_power_status(conn, options):
+ del conn
+
+ res = send_command(options, "<configResolveDn cookie=\"" + options["cookie"] +
+ "\" inHierarchical=\"false\" dn=\"org-root" + options["--suborg"] + "/ls-" +
+ options["--plug"] + "\"/>", int(options["--shell-timeout"]))
+
+ result = RE_GET_PNDN.search(res)
+ if result == None:
+ pndn = ""
+ else:
+ pndn = result.group(1)
+
+ if pndn.strip() == "":
+ if "--missing-as-off" in options:
+ return "off"
+ else:
+ fail(EC_STATUS)
+
+ res = send_command(options, "<configResolveDn cookie=\"" + options["cookie"] +
+ "\" inHierarchical=\"false\" dn=\"" + pndn +
+ "\"/>", int(options["--shell-timeout"]))
+
+ result = RE_GET_PRESENCE.search(res)
+ if result == None:
+ fail(EC_STATUS)
+ else:
+ presence_status = result.group(1)
+
+ if presence_status in ["missing", "mismatch"]:
+ return "off"
+ else:
+ result = RE_GET_OPERPOWER.search(res)
+ if result == None:
+ fail(EC_STATUS)
+ else:
+ power_status = result.group(1)
+
+ if power_status == "on":
+ return "on"
+ else:
+ return "off"
+
+def set_power_status(conn, options):
+ del conn
+
+ action = {
+ 'on' : "admin-up",
+ 'off' : "admin-down"
+ }[options["--action"]]
+
+ send_command(options, "<configConfMos cookie=\"" + options["cookie"] + "\" inHierarchical=\"no\">" +
+ "<inConfigs><pair key=\"org-root" + options["--suborg"] + "/ls-" + options["--plug"] +
+ "/power\">" + "<lsPower dn=\"org-root/ls-" + options["--plug"] + "/power\" state=\"" +
+ action + "\" status=\"modified\" />" + "</pair></inConfigs></configConfMos>",
+ int(options["--shell-timeout"]))
+
+ return
+
+def get_list(conn, options):
+ del conn
+ outlets = {}
+
+ try:
+ res = send_command(options, "<configResolveClass cookie=\"" + options["cookie"] +
+ "\" inHierarchical=\"false\" classId=\"lsServer\"/>", int(options["--shell-timeout"]))
+
+ lines = res.split("<lsServer ")
+ for i in range(1, len(lines)):
+ node_name = RE_GET_DN.search(lines[i]).group(1)
+ desc = RE_GET_DESC.search(lines[i]).group(1)
+ outlets[node_name] = (desc, None)
+ except AttributeError:
+ return {}
+ except IndexError:
+ return {}
+
+ return outlets
+
+def send_command(opt, command, timeout):
+ ## setup correct URL
+ if "--ssl-secure" in opt or "--ssl-insecure" in opt:
+ url = "https:"
+ else:
+ url = "http:"
+
+ url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + "/nuova"
+
+ ## send command through pycurl
+ conn = pycurl.Curl()
+ web_buffer = io.BytesIO()
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+ conn.setopt(pycurl.HTTPHEADER, ["Content-type: text/xml"])
+ conn.setopt(pycurl.POSTFIELDS, command.encode("ascii"))
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+ conn.setopt(pycurl.TIMEOUT, timeout)
+
+ if "--ssl-secure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ elif "--ssl-insecure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+
+ conn.perform()
+ result = web_buffer.getvalue().decode()
+
+ logging.debug("%s\n", command)
+ logging.debug("%s\n", result)
+
+ return result
+
+def define_new_opts():
+ all_opt["suborg"] = {
+ "getopt" : ":",
+ "longopt" : "suborg",
+ "help" : "--suborg=[path] Additional path needed to access suborganization",
+ "required" : "0",
+ "shortdesc" : "Additional path needed to access suborganization",
+ "default" : "",
+ "order" : 1}
+
+def logout():
+ ### Logout; we do not care about result as we will end in any case
+ try:
+ send_command(options_global, "<aaaLogout inCookie=\"" + options_global["cookie"] + "\" />",
+ int(options_global["--shell-timeout"]))
+ except Exception:
+ pass
+
+def main():
+ global options_global
+ device_opt = ["ipaddr", "login", "passwd", "ssl", "notls", "port", "web", "suborg", "missing_as_off"]
+
+ atexit.register(atexit_handler)
+ atexit.register(logout)
+
+ define_new_opts()
+
+ options_global = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Cisco UCS"
+ docs["longdesc"] = "fence_cisco_ucs is an I/O Fencing agent which can be \
+used with Cisco UCS to fence machines."
+ docs["vendorurl"] = "http://www.cisco.com"
+ show_docs(options_global, docs)
+
+ run_delay(options_global)
+ ### Login
+ try:
+ res = send_command(options_global, "<aaaLogin inName=\"" + options_global["--username"] +
+ "\" inPassword=\"" + options_global["--password"] + "\" />", int(options_global["--login-timeout"]))
+ result = RE_COOKIE.search(res)
+ if result == None:
+ ## Cookie is absenting in response
+ fail(EC_LOGIN_DENIED)
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_LOGIN_DENIED)
+
+ options_global["cookie"] = result.group(1)
+
+ ##
+ ## Modify suborg to format /suborg
+ if options_global["--suborg"] != "":
+ options_global["--suborg"] = "/" + options_global["--suborg"].lstrip("/").rstrip("/")
+
+ ##
+ ## Fence operations
+ ####
+ result = fence_action(None, options_global, set_power_status, get_power_status, get_list)
+
+ ## Logout is done every time at atexit phase
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/compute/fence_compute.py b/agents/compute/fence_compute.py
new file mode 100644
index 0000000..f53b97d
--- /dev/null
+++ b/agents/compute/fence_compute.py
@@ -0,0 +1,516 @@
+#!@PYTHON@ -tt
+
+import sys
+import time
+import atexit
+import logging
+import inspect
+import requests.exceptions
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, is_executable, run_command, run_delay
+
+override_status = ""
+
+EVACUABLE_TAG = "evacuable"
+TRUE_TAGS = ['true']
+
+def get_power_status(connection, options):
+
+ if len(override_status):
+ logging.debug("Pretending we're " + override_status)
+ return override_status
+
+ status = "unknown"
+ logging.debug("get action: " + options["--action"])
+
+ if connection:
+ try:
+ services = connection.services.list(host=options["--plug"], binary="nova-compute")
+ for service in services:
+ logging.debug("Status of %s on %s is %s, %s" % (service.binary, options["--plug"], service.state, service.status))
+ if service.state == "up" and service.status == "enabled":
+ # Up and operational
+ status = "on"
+
+ elif service.state == "down" and service.status == "disabled":
+ # Down and fenced
+ status = "off"
+
+ elif service.state == "down":
+ # Down and requires fencing
+ status = "failed"
+
+ elif service.state == "up":
+ # Up and requires unfencing
+ status = "running"
+ else:
+ logging.warning("Unknown status detected from nova for %s: %s, %s" % (options["--plug"], service.state, service.status))
+ status = "%s %s" % (service.state, service.status)
+ break
+ except requests.exception.ConnectionError as err:
+ logging.warning("Nova connection failed: " + str(err))
+ logging.debug("Final status of %s is %s" % (options["--plug"], status))
+ return status
+
+def get_power_status_simple(connection, options):
+ status = get_power_status(connection, options)
+ if status in [ "off" ]:
+ return status
+ return "on"
+
+def set_attrd_status(host, status, options):
+ logging.debug("Setting fencing status for %s to %s" % (host, status))
+ run_command(options, "attrd_updater -p -n evacuate -Q -N %s -U %s" % (host, status))
+
+def get_attrd_status(host, options):
+ (status, pipe_stdout, pipe_stderr) = run_command(options, "attrd_updater -p -n evacuate -Q -N %s" % (host))
+ fields = pipe_stdout.split('"')
+ if len(fields) > 6:
+ return fields[5]
+ logging.debug("Got %s: o:%s e:%s n:%d" % (status, pipe_stdout, pipe_stderr, len(fields)))
+ return ""
+
+def set_power_status_on(connection, options):
+ # Wait for any evacuations to complete
+ while True:
+ current = get_attrd_status(options["--plug"], options)
+ if current in ["no", ""]:
+ logging.info("Evacuation complete for: %s '%s'" % (options["--plug"], current))
+ break
+ else:
+ logging.info("Waiting for %s to complete evacuations: %s" % (options["--plug"], current))
+ time.sleep(2)
+
+ status = get_power_status(connection, options)
+ # Should we do it for 'failed' too?
+ if status in [ "off", "running", "failed" ]:
+ try:
+ # Forcing the host back up
+ logging.info("Forcing nova-compute back up on "+options["--plug"])
+ connection.services.force_down(options["--plug"], "nova-compute", force_down=False)
+ logging.info("Forced nova-compute back up on "+options["--plug"])
+ except Exception as e:
+ # In theory, if force_down=False fails, that's for the exact
+ # same possible reasons that below with force_down=True
+ # eg. either an incompatible version or an old client.
+ # Since it's about forcing back to a default value, there is
+ # no real worries to just consider it's still okay even if the
+ # command failed
+ logging.warn("Exception from attempt to force "
+ "host back up via nova API: "
+ "%s: %s" % (e.__class__.__name__, e))
+
+ # Forcing the service back up in case it was disabled
+ logging.info("Enabling nova-compute on "+options["--plug"])
+ connection.services.enable(options["--plug"], 'nova-compute')
+
+ # Pretend we're 'on' so that the fencing library doesn't loop forever waiting for the node to boot
+ override_status = "on"
+ elif status not in ["on"]:
+ # Not safe to unfence, don't waste time looping to see if the status changes to "on"
+ options["--power-timeout"] = "0"
+
+def set_power_status_off(connection, options):
+ status = get_power_status(connection, options)
+ if status in [ "off" ]:
+ return
+
+ try:
+ # Until 2.53
+ connection.services.force_down(
+ options["--plug"], "nova-compute", force_down=True)
+ connection.services.disable(options["--plug"], 'nova-compute')
+ except Exception as e:
+ # Something went wrong when we tried to force the host down.
+ # That could come from either an incompatible API version
+ # eg. UnsupportedVersion or VersionNotFoundForAPIMethod
+ # or because novaclient is old and doesn't include force_down yet
+ # eg. AttributeError
+ # In that case, fallbacking to wait for Nova to catch the right state.
+
+ logging.error("Exception from attempt to force host down via nova API: "
+ "%s: %s" % (e.__class__.__name__, e))
+ # need to wait for nova to update its internal status or we
+ # cannot call host-evacuate
+ while get_power_status(connection, options) not in ["off"]:
+ # Loop forever if need be.
+ #
+ # Some callers (such as Pacemaker) will have a timer
+ # running and kill us if necessary
+ logging.debug("Waiting for nova to update its internal state for %s" % options["--plug"])
+ time.sleep(1)
+
+ set_attrd_status(options["--plug"], "yes", options)
+
+def set_power_status(connection, options):
+ global override_status
+
+ override_status = ""
+ logging.debug("set action: " + options["--action"])
+
+ if not connection:
+ return
+
+ if options["--action"] in ["off", "reboot"]:
+ set_power_status_off(connection, options)
+ else:
+ set_power_status_on(connection, options)
+ logging.debug("set action passed: " + options["--action"])
+ sys.exit(0)
+
+def fix_domain(connection, options):
+ domains = {}
+ last_domain = None
+
+ if connection:
+ # Find it in nova
+
+ services = connection.services.list(binary="nova-compute")
+ for service in services:
+ shorthost = service.host.split('.')[0]
+
+ if shorthost == service.host:
+ # Nova is not using FQDN
+ calculated = ""
+ else:
+ # Compute nodes are named as FQDN, strip off the hostname
+ calculated = service.host.replace(shorthost+".", "")
+
+ if calculated == last_domain:
+ # Avoid complaining for each compute node with the same name
+ # One hopes they don't appear interleaved as A.com B.com A.com B.com
+ logging.debug("Calculated the same domain from: %s" % service.host)
+ continue
+
+ domains[calculated] = service.host
+ last_domain = calculated
+
+ if "--domain" in options and options["--domain"] != calculated:
+ # Warn in case nova isn't available at some point
+ logging.warning("Supplied domain '%s' does not match the one calculated from: %s"
+ % (options["--domain"], service.host))
+
+ if len(domains) == 0 and "--domain" not in options:
+ logging.error("Could not calculate the domain names used by compute nodes in nova")
+
+ elif len(domains) == 1 and "--domain" not in options:
+ options["--domain"] = last_domain
+
+ elif len(domains) == 1 and options["--domain"] != last_domain:
+ logging.error("Overriding supplied domain '%s' as it does not match the one calculated from: %s"
+ % (options["--domain"], domains[last_domain]))
+ options["--domain"] = last_domain
+
+ elif len(domains) > 1:
+ logging.error("The supplied domain '%s' did not match any used inside nova: %s"
+ % (options["--domain"], repr(domains)))
+ sys.exit(1)
+
+ return last_domain
+
+def fix_plug_name(connection, options):
+ if options["--action"] == "list":
+ return
+
+ if "--plug" not in options:
+ return
+
+ calculated = fix_domain(connection, options)
+ if calculated is None or "--domain" not in options:
+ # Nothing supplied and nova not available... what to do... nothing
+ return
+
+ short_plug = options["--plug"].split('.')[0]
+ logging.debug("Checking target '%s' against calculated domain '%s'"% (options["--plug"], calculated))
+
+ if options["--domain"] == "":
+ # Ensure any domain is stripped off since nova isn't using FQDN
+ options["--plug"] = short_plug
+
+ elif options["--plug"].endswith(options["--domain"]):
+ # Plug already uses the domain, don't re-add
+ return
+
+ else:
+ # Add the domain to the plug
+ options["--plug"] = short_plug + "." + options["--domain"]
+
+def get_plugs_list(connection, options):
+ result = {}
+
+ if connection:
+ services = connection.services.list(binary="nova-compute")
+ for service in services:
+ longhost = service.host
+ shorthost = longhost.split('.')[0]
+ result[longhost] = ("", None)
+ result[shorthost] = ("", None)
+ return result
+
+def create_nova_connection(options):
+ nova = None
+
+ try:
+ from novaclient import client
+ from novaclient.exceptions import NotAcceptable
+ except ImportError:
+ fail_usage("Nova not found or not accessible")
+
+ from keystoneauth1 import loading
+ from keystoneauth1 import session
+ from keystoneclient import discover
+
+ # Prefer the oldest and strip the leading 'v'
+ keystone_versions = discover.available_versions(options["--auth-url"])
+ keystone_version = keystone_versions[0]['id'][1:]
+ kwargs = dict(
+ auth_url=options["--auth-url"],
+ username=options["--username"],
+ password=options["--password"]
+ )
+
+ if discover.version_match("2", keystone_version):
+ kwargs["tenant_name"] = options["--tenant-name"]
+
+ elif discover.version_match("3", keystone_version):
+ kwargs["project_name"] = options["--tenant-name"]
+ kwargs["user_domain_name"] = options["--user-domain"]
+ kwargs["project_domain_name"] = options["--project-domain"]
+
+ loader = loading.get_plugin_loader('password')
+ keystone_auth = loader.load_from_options(**kwargs)
+ keystone_session = session.Session(auth=keystone_auth, verify=not "--insecure" in options)
+
+ nova_versions = [ "2.11", "2" ]
+ for version in nova_versions:
+ clientargs = inspect.getargspec(client.Client).varargs
+ # Some versions of Openstack prior to Ocata only
+ # supported positional arguments for username,
+ # password, and tenant.
+ #
+ # Versions since Ocata only support named arguments.
+ #
+ # So we need to use introspection to figure out how to
+ # create a Nova client.
+ #
+ # Happy days
+ #
+ if clientargs:
+ # OSP < 11
+ # ArgSpec(args=['version', 'username', 'password', 'project_id', 'auth_url'],
+ # varargs=None,
+ # keywords='kwargs', defaults=(None, None, None, None))
+ nova = client.Client(version,
+ None, # User
+ None, # Password
+ None, # Tenant
+ None, # Auth URL
+ insecure="--insecure" in options,
+ region_name=options["--region-name"],
+ endpoint_type=options["--endpoint-type"],
+ session=keystone_session, auth=keystone_auth,
+ http_log_debug="--verbose" in options)
+ else:
+ # OSP >= 11
+ # ArgSpec(args=['version'], varargs='args', keywords='kwargs', defaults=None)
+ nova = client.Client(version,
+ region_name=options["--region-name"],
+ endpoint_type=options["--endpoint-type"],
+ session=keystone_session, auth=keystone_auth,
+ http_log_debug="--verbose" in options)
+
+ try:
+ nova.hypervisors.list()
+ return nova
+
+ except NotAcceptable as e:
+ logging.warning(e)
+
+ except Exception as e:
+ logging.warning("Nova connection failed. %s: %s" % (e.__class__.__name__, e))
+
+ logging.warning("Couldn't obtain a supported connection to nova, tried: %s\n" % repr(nova_versions))
+ return None
+
+def define_new_opts():
+ all_opt["endpoint_type"] = {
+ "getopt" : "e:",
+ "longopt" : "endpoint-type",
+ "help" : "-e, --endpoint-type=[endpoint] Nova Endpoint type (publicURL, internalURL, adminURL)",
+ "required" : "0",
+ "shortdesc" : "Nova Endpoint type",
+ "default" : "internalURL",
+ "order": 1,
+ }
+ all_opt["tenant_name"] = {
+ "getopt" : "t:",
+ "longopt" : "tenant-name",
+ "help" : "-t, --tenant-name=[name] Keystone v2 Tenant or v3 Project Name",
+ "required" : "0",
+ "shortdesc" : "Keystone Admin Tenant or v3 Project",
+ "default" : "",
+ "order": 1,
+ }
+ all_opt["user-domain"] = {
+ "getopt" : "u:",
+ "longopt" : "user-domain",
+ "help" : "-u, --user-domain=[name] Keystone v3 User Domain",
+ "required" : "0",
+ "shortdesc" : "Keystone v3 User Domain",
+ "default" : "Default",
+ "order": 2,
+ }
+ all_opt["project-domain"] = {
+ "getopt" : "P:",
+ "longopt" : "project-domain",
+ "help" : "-P, --project-domain=[name] Keystone v3 Project Domain",
+ "required" : "0",
+ "shortdesc" : "Keystone v3 Project Domain",
+ "default" : "Default",
+ "order": 2,
+ }
+ all_opt["auth_url"] = {
+ "getopt" : "k:",
+ "longopt" : "auth-url",
+ "help" : "-k, --auth-url=[url] Keystone Admin Auth URL",
+ "required" : "0",
+ "shortdesc" : "Keystone Admin Auth URL",
+ "default" : "",
+ "order": 1,
+ }
+ all_opt["region_name"] = {
+ "getopt" : ":",
+ "longopt" : "region-name",
+ "help" : "--region-name=[region] Region Name",
+ "required" : "0",
+ "shortdesc" : "Region Name",
+ "default" : "",
+ "order": 1,
+ }
+ all_opt["insecure"] = {
+ "getopt" : "",
+ "longopt" : "insecure",
+ "help" : "--insecure Explicitly allow agent to perform \"insecure\" TLS (https) requests",
+ "required" : "0",
+ "shortdesc" : "Allow Insecure TLS Requests",
+ "order": 2,
+ }
+ all_opt["domain"] = {
+ "getopt" : "d:",
+ "longopt" : "domain",
+ "help" : "-d, --domain=[string] DNS domain in which hosts live, useful when the cluster uses short names and nova uses FQDN",
+ "required" : "0",
+ "shortdesc" : "DNS domain in which hosts live",
+ "order": 5,
+ }
+ all_opt["record_only"] = {
+ "getopt" : "r:",
+ "longopt" : "record-only",
+ "help" : "--record-only Record the target as needing evacuation but as yet do not intiate it",
+ "required" : "0",
+ "shortdesc" : "Only record the target as needing evacuation",
+ "default" : "False",
+ "order": 5,
+ }
+ all_opt["instance_filtering"] = {
+ "getopt" : "",
+ "longopt" : "instance-filtering",
+ "help" : "--instance-filtering Allow instances created from images and flavors with evacuable=true to be evacuated (or all if no images/flavors have been tagged)",
+ "required" : "0",
+ "shortdesc" : "Allow instances to be evacuated",
+ "default" : "True",
+ "order": 5,
+ }
+ all_opt["no_shared_storage"] = {
+ "getopt" : "",
+ "longopt" : "no-shared-storage",
+ "help" : "--no-shared-storage Disable functionality for shared storage",
+ "required" : "0",
+ "shortdesc" : "Disable functionality for dealing with shared storage",
+ "default" : "False",
+ "order": 5,
+ }
+ all_opt["compute-domain"] = {
+ "getopt" : ":",
+ "longopt" : "compute-domain",
+ "help" : "--compute-domain=[string] Replaced by --domain",
+ "required" : "0",
+ "shortdesc" : "Replaced by domain",
+ "order": 6,
+ }
+
+def set_multi_power_fn(connection, options, set_power_fn, get_power_fn, retry_attempts=1):
+ for _ in range(retry_attempts):
+ set_power_fn(connection, options)
+ time.sleep(int(options["--power-wait"]))
+
+ for _ in range(int(options["--power-timeout"])):
+ if get_power_fn(connection, options) != options["--action"]:
+ time.sleep(1)
+ else:
+ return True
+ return False
+
+def main():
+ global override_status
+ atexit.register(atexit_handler)
+
+ device_opt = ["login", "passwd", "tenant_name", "auth_url", "fabric_fencing", "no_login",
+ "no_password", "port", "domain", "compute-domain", "project-domain",
+ "user-domain", "no_shared_storage", "endpoint_type", "record_only",
+ "instance_filtering", "insecure", "region_name"]
+ define_new_opts()
+ all_opt["shell_timeout"]["default"] = "180"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for the automatic resurrection of OpenStack compute instances"
+ docs["longdesc"] = "Used to tell Nova that compute nodes are down and to reschedule flagged instances"
+ docs["vendorurl"] = ""
+
+ show_docs(options, docs)
+
+ if options["--record-only"] in [ "2", "Disabled", "disabled" ]:
+ sys.exit(0)
+
+ run_delay(options)
+
+ # workaround to avoid regressions
+ if "--compute-domain" in options and options["--compute-domain"]:
+ options["--domain"] = options["--compute-domain"]
+ del options["--domain"]
+
+ # Disable insecure-certificate-warning message
+ if "--insecure" in options:
+ import urllib3
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+ logging.debug("Running "+options["--action"])
+ connection = create_nova_connection(options)
+
+ if options["--action"] in ["off", "on", "reboot", "status"]:
+ fix_plug_name(connection, options)
+
+
+ if options["--action"] in ["reboot"]:
+ options["--action"]="off"
+
+ if options["--action"] in ["off", "on"]:
+ # No status first, call our own version
+ result = not set_multi_power_fn(connection, options, set_power_status, get_power_status_simple,
+ 1 + int(options["--retry-on"]))
+ elif options["--action"] in ["monitor"]:
+ result = 0
+ else:
+ result = fence_action(connection, options, set_power_status, get_power_status_simple, get_plugs_list, None)
+
+ logging.debug("Result for "+options["--action"]+": "+repr(result))
+ if result == None:
+ result = 0
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/crosslink/README.md b/agents/crosslink/README.md
new file mode 100644
index 0000000..990b790
--- /dev/null
+++ b/agents/crosslink/README.md
@@ -0,0 +1,44 @@
+# Two node cross-link fence agent
+
+The problem that this fence agents tries to solve is the following:
+
+Given a two-node cluster with a direct crosslink ethernet cable
+between the two nodes (in addition to the normal networking setup), we want to
+be able to maintain quorum on node (A) when node (B) lost power.
+The loss of power on node (B) in this case implies its BMC/IPMI is also
+not available which would be normally used in fencing in this case.
+
+Note: An external PDU would be preferrable and would solve this
+situation more elegantly. The assumption here is that something
+like that won't be available in this environment.
+
+This works by creating a stonith level composed of a BMC/IPMI
+fencing at level 1 and then the fence_crosslink agent at level 2.
+
+In case node (A) has lost power, then node (B) will do the following:
+1. Try to fence node (B) via IPMI, which will fail since the node has no
+power and the BMC is unavailable
+2. Check via fence_crosslink the cross-cable interconnect. If the cross cable
+IP is not reachable, then we know for "sure" (this is a potentially broad
+assumption) that the node is really down and fence_crosslink tells pacemaker
+that the fencing was successful, so pacemaker can work with that new
+information.
+
+Here are some example configuration commands:
+~~~
+pcs stonith create crosslink-controller-1 fence_crosslink crosscableip=1.1.1.2 pcmk_host_list=controller-1 pcmk_reboot_action=off
+pcs stonith create crosslink-controller-0 fence_crosslink crosscableip=1.1.1.1 pcmk_host_list=controller-0 pcmk_reboot_action=off
+# We make sure the stonith resource do not run on the same node as the fencing target
+pcs constraint location crosslink-controller-1 avoids controller-1
+pcs constraint location crosslink-controller-0 avoids controller-0
+pcs stonith level add 2 controller-0 crosslink-controller-0
+pcs stonith level add 2 controller-1 crosslink-controller-1
+~~~
+
+Testing done:
+- Simulate power outage by turning off the controller-1 VM and its IPMI interface and leaving the crosslink intact.
+
+ * Expected Outcome:
+ We should retain quorum on controller-0 and all services should be running on controller-0. No UNCLEAN resources should be observed on controller-0.
+ * Actual Outcome:
+ Matched the expected outcome.
diff --git a/agents/crosslink/fence_crosslink.py b/agents/crosslink/fence_crosslink.py
new file mode 100755
index 0000000..7cfc90c
--- /dev/null
+++ b/agents/crosslink/fence_crosslink.py
@@ -0,0 +1,113 @@
+#!@PYTHON@ -tt
+
+# Copyright (c) 2020 Red Hat
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import atexit
+import logging
+import sys
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import (all_opt, atexit_handler, check_input, # noqa: E402
+ fence_action, process_input, run_command, run_delay,
+ show_docs)
+
+logger = logging.getLogger(__name__)
+logger.setLevel("WARNING")
+
+
+def get_power_status(conn, options):
+ logger.debug("get_power_status(): %s" % options)
+ ip = options['--crosscableip']
+ timeout = options['--timeout']
+ # This returns 'off' if not a single ICMP packet gets answered during the
+ # whole timeout window. (the ping executable will return 1 in such case and
+ # 0 if even a single packet gets replied to)
+ (status, stdout, stderr) = run_command(options, "ping -w%s -n %s" %
+ (timeout, ip))
+ logger.debug("get_power_status(): %s - Stdout: %s - Stderr: %s" %
+ (status, stdout, stderr))
+ if status == 0:
+ return "on"
+ else:
+ return "off"
+
+
+def set_power_status(conn, options):
+ logger.debug("set_power_status(): %s" % options)
+ # If we got here it means the previous call to get_power_status() returned
+ # on At this point we've been invoked but the node is still reachable over
+ # the cross connect, so we can just error out.
+ ip = options['--crosscableip']
+ if options['--action'] == 'off':
+ logger.error("We've been asked to turn off the node at %s but the "
+ "cross-cable link is up so erroring out" % ip)
+ sys.exit(1)
+ elif options['--action'] == 'on':
+ logger.error("We've been asked to turn on the node at %s but the "
+ "cross-cable link is off so erroring out" % ip)
+ sys.exit(1)
+ else:
+ logger.error("set_power_status() was called with action %s which "
+ "is not supported" % options['--action'])
+ sys.exit(1)
+
+
+def define_new_opts():
+ all_opt["crosscableip"] = {
+ "getopt": "a:",
+ "longopt": "crosscableip",
+ "help": "-a, --crosscableip=[IP] IP over the cross-cable link",
+ "required": "1",
+ "shortdesc": "Cross-cable IP",
+ "order": 1
+ }
+ all_opt["timeout"] = {
+ "getopt": "T:",
+ "longopt": "timeout",
+ "help": "-T, --timeout=[seconds] timeout in seconds",
+ "required": "0",
+ "shortdesc": "No ICMP reply in 5 seconds -> Node is considered dead",
+ "default": "5",
+ "order": 1
+ }
+
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["crosscableip", "timeout", "no_password", "no_login", "port"]
+ define_new_opts()
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for cross-link two-node clusters"
+ docs["longdesc"] = "This agent helps two-node clusters to tackle the " \
+ "situation where one node lost power, cannot be " \
+ "fenced by telling pacemaker that if the node is not " \
+ "reachable over the crosslink cable, we can assume " \
+ "it is dead"
+ docs["vendorurl"] = ""
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ result = fence_action(None, options, set_power_status, get_power_status)
+ sys.exit(result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/cyberpower_ssh/fence_cyberpower_ssh.py b/agents/cyberpower_ssh/fence_cyberpower_ssh.py
new file mode 100755
index 0000000..f0695d6
--- /dev/null
+++ b/agents/cyberpower_ssh/fence_cyberpower_ssh.py
@@ -0,0 +1,70 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## Fence agent for CyberPower based SSH-capable power strip
+## Tested with CyberPower model PDU41001, ePDU Firmware version 1.2.0
+##
+#####
+
+import sys, re, time
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS
+
+def set_power_status(conn, options):
+ conn.send_eol("oltctrl index " + options["--plug"] + " act delay" + options["--action"])
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_power_status(conn, options):
+ outlets = {}
+ conn.send_eol("oltsta show")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ lines = conn.before.split("\n")
+ show_re = re.compile(r'(\s*)(\d)\s*(.*)\s*(On|Off)\s*')
+ for line in lines:
+ res = show_re.search(line)
+ if res != None:
+ outlets[res.group(2)] = (res.group(3), res.group(4))
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ try:
+ (_,status) = outlets[options["--plug"]]
+ return status.lower().strip()
+ except KeyError:
+ fail(EC_STATUS)
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["\n>", "\nCyberPower >"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for CyberPower over ssh"
+ docs["longdesc"] = "fence_cyberpower_ssh is an I/O Fencing agent \
+which can be used with the CyberPower network power switch. It logs into \
+device via ssh and reboots a specified outlet. Lengthy ssh connections \
+should be avoided while a GFS cluster is running because the connection \
+will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.cyberpower.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/docker/fence_docker.py b/agents/docker/fence_docker.py
new file mode 100644
index 0000000..0044025
--- /dev/null
+++ b/agents/docker/fence_docker.py
@@ -0,0 +1,161 @@
+#!@PYTHON@ -tt
+
+import atexit
+import sys
+import io
+import logging
+import pycurl
+import json
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import fail_usage, all_opt, fence_action, atexit_handler, check_input, process_input, show_docs, run_delay
+
+def get_power_status(conn, options):
+ del conn
+ status = send_cmd(options, "containers/%s/json" % options["--plug"])
+ if status is None:
+ return None
+ return "on" if status["State"]["Running"] else "off"
+
+
+def set_power_status(conn, options):
+ del conn
+ if options["--action"] == "on":
+ send_cmd(options, "containers/%s/start" % options["--plug"], True)
+ else:
+ send_cmd(options, "containers/%s/kill" % options["--plug"], True)
+ return
+
+
+def reboot_cycle(conn, options):
+ del conn
+ send_cmd(options, "containers/%s/restart" % options["--plug"], True)
+ return get_power_status(conn, options)
+
+
+def get_list(conn, options):
+ del conn
+ output = send_cmd(options, "containers/json?all=1")
+ containers = {}
+ for container in output:
+ containers[container["Id"]] = ({True:container["Names"][0][1:], False: container["Names"][0]}[container["Names"][0][0:1] == '/'], {True:"off", False: "on"}[container["Status"][:4].lower() == "exit"])
+ return containers
+
+
+def send_cmd(options, cmd, post = False):
+ url = "http%s://%s:%s/v%s/%s" % ("s" if "--ssl-secure" in options or "--ssl-insecure" in options else "", options["--ip"], options["--ipport"], options["--api-version"], cmd)
+ conn = pycurl.Curl()
+ output_buffer = io.BytesIO()
+ if logging.getLogger().getEffectiveLevel() < logging.WARNING:
+ conn.setopt(pycurl.VERBOSE, True)
+ conn.setopt(pycurl.HTTPGET, 1)
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+ if post:
+ conn.setopt(pycurl.POST, 1)
+ conn.setopt(pycurl.POSTFIELDSIZE, 0)
+ conn.setopt(pycurl.WRITEFUNCTION, output_buffer.write)
+ conn.setopt(pycurl.TIMEOUT, int(options["--shell-timeout"]))
+
+ if "--ssl-secure" in options:
+ if not (set(("--tlscert", "--tlskey", "--tlscacert")) <= set(options)):
+ fail_usage("Failed. If --ssl option is used, You have to also \
+specify: --tlscert, --tlskey and --tlscacert")
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSLCERT, options["--tlscert"])
+ conn.setopt(pycurl.SSLKEY, options["--tlskey"])
+ conn.setopt(pycurl.CAINFO, options["--tlscacert"])
+ elif "--ssl-insecure" in options:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+
+ logging.debug("URL: " + url)
+
+ try:
+ conn.perform()
+ result = output_buffer.getvalue().decode()
+ return_code = conn.getinfo(pycurl.RESPONSE_CODE)
+
+ logging.debug("RESULT [" + str(return_code) + \
+ "]: " + result)
+ conn.close()
+ if return_code == 200:
+ return json.loads(result)
+ except pycurl.error:
+ logging.error("Connection failed")
+ except:
+ if result is not None:
+ logging.error(result)
+ logging.error("Cannot parse json")
+ return None
+
+
+def main():
+ atexit.register(atexit_handler)
+
+ all_opt["tlscert"] = {
+ "getopt" : ":",
+ "longopt" : "tlscert",
+ "help" : "--tlscert "
+ "Path to client certificate for TLS authentication",
+ "required" : "0",
+ "shortdesc" : "Path to client certificate (PEM format) \
+for TLS authentication. Required if --ssl option is used.",
+ "order": 2
+ }
+
+ all_opt["tlskey"] = {
+ "getopt" : ":",
+ "longopt" : "tlskey",
+ "help" : "--tlskey "
+ "Path to client key for TLS authentication",
+ "required" : "0",
+ "shortdesc" : "Path to client key (PEM format) for TLS \
+authentication. Required if --ssl option is used.",
+ "order": 2
+ }
+
+ all_opt["tlscacert"] = {
+ "getopt" : ":",
+ "longopt" : "tlscacert",
+ "help" : "--tlscacert "
+ "Path to CA certificate for TLS authentication",
+ "required" : "0",
+ "shortdesc" : "Path to CA certificate (PEM format) for \
+TLS authentication. Required if --ssl option is used.",
+ "order": 2
+ }
+
+ all_opt["api_version"] = {
+ "getopt" : ":",
+ "longopt" : "api-version",
+ "help" : "--api-version "
+ "Version of Docker Remote API (default: 1.11)",
+ "required" : "0",
+ "order" : 2,
+ "default" : "1.11",
+ }
+
+ device_opt = ["ipaddr", "no_password", "no_login", "port", "method", "web", "tlscert", "tlskey", "tlscacert", "ssl", "api_version"]
+
+ all_opt["ssl"]["default"] = "1"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = { }
+ docs["shortdesc"] = "Fence agent for Docker"
+ docs["longdesc"] = "fence_docker is I/O fencing agent which \
+can be used with the Docker Engine containers. You can use this \
+fence-agent without any authentication, or you can use TLS authentication \
+(use --ssl option, more info about TLS authentication in docker: \
+http://docs.docker.com/examples/https/)."
+ docs["vendorurl"] = "www.docker.io"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ result = fence_action(None, options, set_power_status, get_power_status, get_list, reboot_cycle)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/drac/fence_drac.py b/agents/drac/fence_drac.py
new file mode 100644
index 0000000..be3e9a5
--- /dev/null
+++ b/agents/drac/fence_drac.py
@@ -0,0 +1,62 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+def get_power_status(conn, options):
+ conn.send_eol("getmodinfo")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ status = re.compile(r"\s+(on|off)\s+", re.IGNORECASE).search(conn.before).group(1)
+ return status.lower().strip()
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "powerup",
+ 'off': "powerdown"
+ }[options["--action"]]
+
+ conn.send_eol("serveraction -d 0 " + action)
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ opt = process_input(device_opt)
+ if "--username" in opt:
+ all_opt["cmd_prompt"]["default"] = ["\\[" + opt["--username"] + "\\]# "]
+ else:
+ all_opt["cmd_prompt"]["default"] = ["\\[" "username" + "\\]# "]
+
+ options = check_input(device_opt, opt)
+
+ docs = {}
+ docs["shortdesc"] = "I/O Fencing agent for Dell DRAC IV"
+ docs["longdesc"] = "fence_drac is an I/O Fencing agent which can be used with \
+the Dell Remote Access Card (DRAC). This card provides remote access to controlling \
+power to a server. It logs into the DRAC through the telnet interface of the card. By \
+default, the telnet interface is not enabled. To enable the interface, you will need \
+to use the racadm command in the racser-devel rpm available from Dell. \
+\
+To enable telnet on the DRAC: \
+\
+[root]# racadm config -g cfgSerial -o cfgSerialTelnetEnable 1 \
+\
+[root]# racadm racreset \
+"
+ docs["vendorurl"] = "http://www.dell.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, None)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/drac5/fence_drac5.py b/agents/drac5/fence_drac5.py
new file mode 100644
index 0000000..648ecd9
--- /dev/null
+++ b/agents/drac5/fence_drac5.py
@@ -0,0 +1,147 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## DRAC Version Firmware
+## +-----------------+---------------------------+
+## DRAC 5 1.0 (Build 06.05.12)
+## DRAC 5 1.21 (Build 07.05.04)
+##
+## @note: drac_version was removed
+#####
+
+import sys, re, time
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage
+
+def get_power_status(conn, options):
+ if options["--drac-version"] == "DRAC MC":
+ (_, status) = get_list_devices(conn, options)[options["--plug"]]
+ else:
+ if options["--drac-version"] == "DRAC CMC":
+ conn.send_eol("racadm serveraction powerstatus -m " + options["--plug"])
+ elif options["--drac-version"] == "DRAC 5":
+ conn.send_eol("racadm serveraction powerstatus")
+
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ status = re.compile(r"(^|: )(ON|OFF|Powering ON|Powering OFF)\s*$",
+ re.IGNORECASE | re.MULTILINE).search(conn.before).group(2)
+
+ if status.lower().strip() in ["on", "powering on", "powering off"]:
+ return "on"
+ else:
+ return "off"
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "powerup",
+ 'off': "powerdown"
+ }[options["--action"]]
+
+ if options["--drac-version"] == "DRAC CMC":
+ conn.send_eol("racadm serveraction " + action + " -m " + options["--plug"])
+ elif options["--drac-version"] == "DRAC 5":
+ conn.send_eol("racadm serveraction " + action)
+ elif options["--drac-version"] == "DRAC MC":
+ conn.send_eol("racadm serveraction -s " + options["--plug"] + " " + action)
+
+ ## Fix issue with double-enter [CR/LF]
+ ## We need to read two additional command prompts (one from get + one from set command)
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ if len(conn.before.strip()) == 0:
+ options["eol"] = options["eol"][:-1]
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def get_list_devices(conn, options):
+ outlets = {}
+
+ if options["--drac-version"] == "DRAC CMC":
+ conn.send_eol("getmodinfo")
+
+ list_re = re.compile(r"^([^\s]*?)\s+Present\s*(ON|OFF)\s*.*$")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ for line in conn.before.splitlines():
+ if list_re.search(line):
+ outlets[list_re.search(line).group(1)] = ("", list_re.search(line).group(2))
+ elif options["--drac-version"] == "DRAC MC":
+ conn.send_eol("getmodinfo")
+
+ list_re = re.compile(r"^\s*([^\s]*)\s*---->\s*(.*?)\s+Present\s*(ON|OFF)\s*.*$")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ for line in conn.before.splitlines():
+ if list_re.search(line):
+ outlets[list_re.search(line).group(2)] = ("", list_re.search(line).group(3))
+ elif options["--drac-version"] == "DRAC 5":
+ ## DRAC 5 can be used only for one computer
+ ## standard fence library can't handle correctly situation
+ ## when some fence devices supported by fence agent
+ ## works with 'list' and other should returns 'N/A'
+ print("N/A")
+
+ return outlets
+
+def define_new_opts():
+ all_opt["drac_version"] = {
+ "getopt" : "d:",
+ "longopt" : "drac-version",
+ "help" : "-d, --drac-version=[version] Force DRAC version to use (DRAC 5|DRAC CMC|DRAC MC)",
+ "required" : "0",
+ "shortdesc" : "Force DRAC version to use",
+ "choices" : ["DRAC CMC", "DRAC MC", "DRAC 5"],
+ "order" : 1}
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "drac_version", "port", "no_port", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["cmd_prompt"]["default"] = [r"\$", r"DRAC\/MC:"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Dell DRAC CMC/5"
+ docs["longdesc"] = "fence_drac5 is an I/O Fencing agent \
+which can be used with the Dell Remote Access Card v5 or CMC (DRAC). \
+This device provides remote access to controlling power to a server. \
+It logs into the DRAC through the telnet/ssh interface of the card. \
+By default, the telnet interface is not enabled."
+ docs["vendorurl"] = "http://www.dell.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ######
+ conn = fence_login(options)
+
+ if "--drac-version" not in options:
+ ## autodetect from text issued by fence device
+ if conn.before.find("CMC") >= 0:
+ options["--drac-version"] = "DRAC CMC"
+ elif conn.before.find("DRAC 5") >= 0:
+ options["--drac-version"] = "DRAC 5"
+ elif conn.after.find("DRAC/MC") >= 0:
+ options["--drac-version"] = "DRAC MC"
+ else:
+ ## Assume this is DRAC 5 by default as we don't want to break anything
+ options["--drac-version"] = "DRAC 5"
+
+ if options["--drac-version"] in ["DRAC MC", "DRAC CMC"]:
+ if "--plug" not in options and 0 == ["monitor", "list"].count(options["--action"]):
+ fail_usage("Failed: You have to enter module name (-n)")
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_list_devices)
+ fence_logout(conn, "exit", 1)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/dummy/fence_dummy.py b/agents/dummy/fence_dummy.py
new file mode 100644
index 0000000..8fa2d9a
--- /dev/null
+++ b/agents/dummy/fence_dummy.py
@@ -0,0 +1,133 @@
+#!@PYTHON@ -tt
+
+import sys, random
+import logging
+import time
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, run_delay
+
+plug_status = "on"
+
+def get_power_status_file(conn, options):
+ del conn
+
+ try:
+ status_file = open(options["--status-file"], 'r')
+ except Exception:
+ return "off"
+
+ status = status_file.read()
+ status_file.close()
+
+ return status.lower()
+
+def set_power_status_file(conn, options):
+ del conn
+
+ if not (options["--action"] in ["on", "off"]):
+ return
+
+ status_file = open(options["--status-file"], 'w')
+ status_file.write(options["--action"])
+ status_file.close()
+
+def get_power_status_fail(conn, options):
+ outlets = get_outlets_fail(conn, options)
+
+ if len(outlets) == 0 or "--plug" not in options:
+ fail_usage("Failed: You have to enter existing machine!")
+ else:
+ return outlets[options["--plug"]][0]
+
+def set_power_status_fail(conn, options):
+ global plug_status
+ del conn
+
+ plug_status = "unknown"
+ if options["--action"] == "on":
+ plug_status = "off"
+
+def get_outlets_fail(conn, options):
+ del conn
+
+ result = {}
+ global plug_status
+
+ if options["--action"] == "on":
+ plug_status = "off"
+
+ # This fake agent has no port data to list, so we have to make
+ # something up for the list action.
+ if options.get("--action", None) == "list":
+ result["fake_port_1"] = [plug_status, "fake"]
+ result["fake_port_2"] = [plug_status, "fake"]
+ elif "--plug" not in options:
+ fail_usage("Failed: You have to enter existing machine!")
+ else:
+ port = options["--plug"]
+ result[port] = [plug_status, "fake"]
+
+ return result
+
+def main():
+ device_opt = ["no_password", "status_file", "random_sleep_range", "type", "no_port"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["status_file"] = {
+ "getopt" : ":",
+ "longopt" : "status-file",
+ "help":"--status-file=[file] Name of file that holds current status",
+ "required" : "0",
+ "shortdesc" : "File with status",
+ "default" : "/tmp/fence_dummy.status",
+ "order": 1
+ }
+
+ all_opt["random_sleep_range"] = {
+ "getopt" : ":",
+ "longopt" : "random_sleep_range",
+ "help":"--random_sleep_range=[seconds] Issue a sleep between 1 and [seconds]",
+ "required" : "0",
+ "shortdesc" : "Issue a sleep between 1 and X seconds. Used for testing.",
+ "order": 1
+ }
+
+ all_opt["type"] = {
+ "getopt" : ":",
+ "longopt" : "type",
+ "help":"--type=[type] Possible types are: file and fail",
+ "required" : "0",
+ "shortdesc" : "Type of the dummy fence agent",
+ "default" : "file",
+ "order": 1
+ }
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Dummy fence agent"
+ docs["longdesc"] = "fence_dummy"
+ docs["vendorurl"] = "http://www.example.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # random sleep for testing
+ if "--random_sleep_range" in options:
+ val = int(options["--random_sleep_range"])
+ ran = random.randint(1, val)
+ logging.info("Random sleep for %d seconds\n", ran)
+ time.sleep(ran)
+
+ if options["--type"] == "fail":
+ result = fence_action(None, options, set_power_status_fail, get_power_status_fail, get_outlets_fail)
+ else:
+ result = fence_action(None, options, set_power_status_file, get_power_status_file, None)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/eaton_snmp/README b/agents/eaton_snmp/README
new file mode 100644
index 0000000..82619d7
--- /dev/null
+++ b/agents/eaton_snmp/README
@@ -0,0 +1,20 @@
+This is an snmp based fence agent for Eaton power distribution units to be used
+with RHEL4 Red Hat Cluster Suite.
+
+In order to use this agent, you will need to have net-snmp-utils installed
+on every node in your cluster. net-snmp-utils is scheduled for inclusion
+in the base RHEL distribution for Update 4, and is yummable in FC5.
+
+To use the agent, cp the agent to the /sbin directory on every
+cluster node.
+
+Then define a <fencedevice> in the cluster.conf file with
+agent="fence_eaton_snmp" as an attribute, and use it that way.
+Note, please, that the GUI does not support this agent yet, and you will have
+to edit your cluster.conf by hand and then propagate it yourself. If you need
+help with this, email me at the address below.
+
+The interface for the fence_eaton_snmp agent is identical to the existing
+fence_apc_snmp agent, upon which it has been derived.
+
+--Arnaud Quette - ArnaudQuette@Eaton.com
diff --git a/agents/eaton_snmp/fence_eaton_snmp.py b/agents/eaton_snmp/fence_eaton_snmp.py
new file mode 100644
index 0000000..9fbc056
--- /dev/null
+++ b/agents/eaton_snmp/fence_eaton_snmp.py
@@ -0,0 +1,229 @@
+#!@PYTHON@ -tt
+
+# The Following agent has been tested on:
+# - Eaton ePDU Managed - SNMP v1
+# EATON | Powerware ePDU model: Managed ePDU (PW104MA0UB99), firmware: 01.01.01
+# - Eaton ePDU Switched - SNMP v1
+# EATON | Powerware ePDU model: Switched ePDU (IPV3600), firmware: 2.0.K
+
+import sys
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# oid defining fence device
+OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0'
+
+### GLOBAL VARIABLES ###
+# Device - see EatonManagedePDU, EatonSwitchedePDU
+device = None
+
+# Port ID
+port_id = None
+# Switch ID
+switch_id = None
+
+# Did we issue a set before get (to adjust OID with Switched ePDU)
+after_set = False
+
+# Classes describing Device params
+# Managed ePDU
+class EatonManagedePDU(object):
+ status_oid = '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.3.%d'
+ control_oid = '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.3.%d'
+ outlet_table_oid = '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.1'
+ ident_str = "Eaton Managed ePDU"
+ state_off = 0
+ state_on = 1
+ state_cycling = 2 # FIXME: not usable with fence-agents
+ turn_off = 0
+ turn_on = 1
+ turn_cycle = 2 # FIXME: not usable with fence-agents
+ has_switches = False
+
+# Switched ePDU (Pulizzi 2)
+# NOTE: sysOID reports "20677.1", while data are actually at "20677.2"
+class EatonSwitchedePDU(object):
+ status_oid = '.1.3.6.1.4.1.20677.2.6.3.%d.0'
+ control_oid = '.1.3.6.1.4.1.20677.2.6.2.%d.0'
+ outlet_table_oid = '.1.3.6.1.4.1.20677.2.6.3'
+ ident_str = "Eaton Switched ePDU"
+ state_off = 2
+ state_on = 1
+ state_cycling = 0 # Note: this status doesn't exist on this device
+ turn_off = 2
+ turn_on = 1
+ turn_cycle = 3 # FIXME: not usable with fence-agents
+ has_switches = False
+
+### FUNCTIONS ###
+def eaton_set_device(conn):
+ global device
+
+ agents_dir = {'.1.3.6.1.4.1.534.6.6.6':EatonManagedePDU,
+ '.1.3.6.1.4.1.20677.1':EatonSwitchedePDU,
+ '.1.3.6.1.4.1.20677.2':EatonSwitchedePDU}
+
+ # First resolve type of Eaton
+ eaton_type = conn.walk(OID_SYS_OBJECT_ID)
+
+ if not ((len(eaton_type) == 1) and (eaton_type[0][1] in agents_dir)):
+ eaton_type = [[None, None]]
+
+ device = agents_dir[eaton_type[0][1]]
+
+ logging.debug("Trying %s"%(device.ident_str))
+
+def eaton_resolv_port_id(conn, options):
+ global port_id, switch_id
+
+ if device == None:
+ eaton_set_device(conn)
+
+ # Restore the increment, that was removed in main for ePDU Managed
+ if device.ident_str == "Eaton Switched ePDU":
+ options["--plug"] = str(int(options["--plug"]) + 1)
+
+ # Now we resolv port_id/switch_id
+ if options["--plug"].isdigit() and ((not device.has_switches) or (options["--switch"].isdigit())):
+ port_id = int(options["--plug"])
+
+ if device.has_switches:
+ switch_id = int(options["--switch"])
+ else:
+ table = conn.walk(device.outlet_table_oid, 30)
+
+ for x in table:
+ if x[1].strip('"') == options["--plug"]:
+ t = x[0].split('.')
+ if device.has_switches:
+ port_id = int(t[len(t)-1])
+ switch_id = int(t[len(t)-3])
+ else:
+ if device.ident_str == "Eaton Switched ePDU":
+ port_id = int(t[len(t)-3])
+ else:
+ port_id = int(t[len(t)-1])
+
+ if port_id == None:
+ # Restore index offset, to provide a valid error output on Managed ePDU
+ if device.ident_str != "Eaton Switched ePDU":
+ options["--plug"] = str(int(options["--plug"]) + 1)
+ fail_usage("Can't find port with name %s!"%(options["--plug"]))
+
+def get_power_status(conn, options):
+ global port_id, after_set
+
+ if port_id == None:
+ eaton_resolv_port_id(conn, options)
+
+ # Ajust OID for Switched ePDU when the get is after a set
+ if after_set and device.ident_str == "Eaton Switched ePDU":
+ port_id -= 1
+ after_set = False
+
+ oid = ((device.has_switches) and device.status_oid%(switch_id, port_id) or device.status_oid%(port_id))
+
+ try:
+ (oid, status) = conn.get(oid)
+ if status == str(device.state_on):
+ return "on"
+ elif status == str(device.state_off):
+ return "off"
+ else:
+ return None
+ except Exception:
+ return None
+
+def set_power_status(conn, options):
+ global port_id, after_set
+
+ after_set = True
+
+ if port_id == None:
+ eaton_resolv_port_id(conn, options)
+
+ # Controls start at #2 on Switched ePDU, since #1 is the global command
+ if device.ident_str == "Eaton Switched ePDU":
+ port_id = int(port_id)+1
+
+ oid = ((device.has_switches) and device.control_oid%(switch_id, port_id) or device.control_oid%(port_id))
+
+ conn.set(oid, (options["--action"] == "on" and device.turn_on or device.turn_off))
+
+
+def get_outlets_status(conn, options):
+ outletCount = 0
+ result = {}
+
+ if device == None:
+ eaton_set_device(conn)
+
+ res_ports = conn.walk(device.outlet_table_oid, 30)
+
+ for x in res_ports:
+ outletCount += 1
+ status = x[1]
+ t = x[0].split('.')
+
+ # Plug indexing start from zero, so we substract '1' from the
+ # user's given plug number
+ if device.ident_str == "Eaton Managed ePDU":
+ port_num = str(int(((device.has_switches) and
+ "%s:%s"%(t[len(t)-3], t[len(t)-1]) or "%s"%(t[len(t)-1]))) + 1)
+
+ # Plug indexing start from zero, so we add '1'
+ # for the user's exposed plug number
+ port_name = str(int(x[1].strip('"')) + 1)
+ port_status = ""
+ result[port_num] = (port_name, port_status)
+ else:
+ # Switched ePDU do not propose an outletCount OID!
+ # Invalid status (ie value == '0'), retrieved via the walk,
+ # means the outlet is absent
+ port_num = str(outletCount)
+ port_name = str(outletCount)
+ port_status = ""
+ if status != '0':
+ result[port_num] = (port_name, port_status)
+
+ return result
+
+# Main agent method
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["switch"]["default"] = 1
+ all_opt["power_wait"]["default"] = 2
+ all_opt["snmp_version"]["default"] = "1"
+ all_opt["community"]["default"] = "private"
+ options = check_input(device_opt, process_input(device_opt))
+
+ # Plug indexing start from zero on ePDU Managed, so we substract '1' from
+ # the user's given plug number.
+ # For Switched ePDU, we will add this back again later.
+ if "--plug" in options and options["--plug"].isdigit():
+ options["--plug"] = str(int(options["--plug"]) - 1)
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Eaton over SNMP"
+ docs["longdesc"] = "fence_eaton_snmp is an I/O Fencing agent \
+which can be used with the Eaton network power switch. It logs \
+into a device via SNMP and reboots a specified outlet. It supports \
+SNMP v1 and v3 with all combinations of authenticity/privacy settings."
+ docs["vendorurl"] = "http://powerquality.eaton.com"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+if __name__ == "__main__":
+ main()
diff --git a/agents/ecloud/fence_ecloud.py b/agents/ecloud/fence_ecloud.py
new file mode 100644
index 0000000..0707e10
--- /dev/null
+++ b/agents/ecloud/fence_ecloud.py
@@ -0,0 +1,169 @@
+#!@PYTHON@ -tt
+#
+# Fence agent for eCloud and eCloud VPC
+# https://www.ans.co.uk/cloud-and-infrastructure/ecloud/
+#
+# Copyright (c) 2022 ANS Group Limited
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import sys
+import time
+import atexit
+import logging
+import requests
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import run_delay, fail_usage, fail, EC_TIMED_OUT
+
+API_BASE = "https://api.ukfast.io/ecloud"
+API_MONITOR = API_BASE + "/ping"
+API_VPC_INSTANCE_DATA = API_BASE + "/v2/instances/:ID"
+API_VPC_POWER_ON = API_BASE + "/v2/instances/:ID/power-on"
+API_VPC_POWER_OFF = API_BASE + "/v2/instances/:ID/power-off"
+API_V1_INSTANCE_DATA = API_BASE + "/v1/vms/:ID"
+API_V1_POWER_ON = API_BASE + "/v1/vms/:ID/power-on"
+API_V1_POWER_OFF = API_BASE + "/v1/vms/:ID/power-off"
+
+
+def set_power_fn(conn, options):
+ logging.debug("setting power {}".format(options['--action']))
+ del conn
+
+ action = options['--action']
+ vpc = options['--ecloud-vpc']
+ plug = options['--plug']
+
+ url = fence_url(vpc, action, plug)
+ hdrs = headers(options['--apikey'])
+
+ logging.info("executing '{}' action on '{}'".format(action, plug))
+
+ retries = 0
+ while True:
+ resp = requests.put(url, headers=hdrs)
+ if resp.status_code == 409:
+ # If we attempt to power the instance back on too soon after powering it off,
+ # e.g. during a reboot, the API will return a 409 because while the power status
+ # has changed, the task is still executing. Retry the action until we exceed
+ # retries or get a different status code.
+ if retries >= 6:
+ logging.error("timed out trying to execute '{}' action after repeated 409 codes from API", action)
+ fail(EC_TIMED_OUT)
+
+ time.sleep(2)
+ retries += 1
+ continue
+
+ if resp.status_code != 202:
+ logging.error("unexpected status code '{}' from endpoint '{}': {}".format(
+ resp.status_code, url, resp.text
+ ))
+
+ break
+
+
+def get_power_fn(conn, options):
+ logging.debug("getting power state")
+ del conn
+
+ vpc = options['--ecloud-vpc']
+ plug = options['--plug']
+
+ url = instance_data_url(vpc, plug)
+ hdrs = headers(options['--apikey'])
+
+ resp = requests.get(url, headers=hdrs)
+ if resp.status_code != 200:
+ logging.error("unexpected status code ('{}') from endpoint '{}': {}".format(
+ resp.status_code, url, resp.text
+ ))
+ return "bad status {}".format(resp.status_code)
+
+ instance = resp.json()['data']
+ if vpc:
+ logging.debug("power state return value: {}".format(instance['online']))
+ return "on" if instance['online'] else "off"
+ else:
+ if instance['power_status'] == "Online":
+ return "on"
+ elif instance['power_status'] == "Offline":
+ return "off"
+ else:
+ # Could be 'Unknown' or other value
+ return instance['power_status']
+
+
+def headers(apikey):
+ return {
+ "Authorization": apikey,
+ "User-Agent": "fence_ecloud"
+ }
+
+
+def itp(url, plug):
+ return url.replace(':ID', plug)
+
+
+def fence_url(vpc, action, plug):
+ if action == "on":
+ return itp(API_VPC_POWER_ON, plug) if vpc else itp(API_V1_POWER_ON, plug)
+ if action == "off":
+ return itp(API_VPC_POWER_OFF, plug) if vpc else itp(API_V1_POWER_OFF, plug)
+
+ fail_usage("no available API configured for action '{}'".format(action))
+
+
+def instance_data_url(vpc, plug):
+ return itp(API_VPC_INSTANCE_DATA, plug) if vpc else itp(API_V1_INSTANCE_DATA, plug)
+
+
+def main():
+ device_opt = ["apikey", "port", "no_login", "no_password"]
+
+ all_opt["apikey"] = {
+ "getopt": ":",
+ "longopt": "apikey",
+ "help": "--apikey=[key] eCloud API Key",
+ "required": "1",
+ "shortdesc": "API Key",
+ "order": 0,
+ }
+ all_opt["port"]["help"] = "-n, --plug=[instance] Instance ID (VPC) or server ID (v1)"
+
+ atexit.register(atexit_handler)
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence Agent for ANS eCloud"
+ docs["longdesc"] = "fence_ecloud is a fence agent for use with the ANS \
+eCloud platform which is compatible with eCloud VPC and eCloud v1."
+ docs["vendorurl"] = "https://www.ans.co.uk"
+ show_docs(options, docs)
+
+ if options['--action'] in ['on', 'off', 'reboot', 'status']:
+ plug = options['--plug']
+
+ options['--ecloud-vpc'] = True
+ if not plug.startswith("i-"):
+ options['--ecloud-vpc'] = False
+
+ run_delay(options)
+ fence_action(None, options, set_power_fn, get_power_fn)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/agents/emerson/fence_emerson.py b/agents/emerson/fence_emerson.py
new file mode 100644
index 0000000..2e65cda
--- /dev/null
+++ b/agents/emerson/fence_emerson.py
@@ -0,0 +1,62 @@
+#!@PYTHON@ -tt
+
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+STATUSES_OID = ".1.3.6.1.4.1.476.1.42.3.8.50.20.1.95"
+CONTROL_OID = ".1.3.6.1.4.1.476.1.42.3.8.50.20.1.100"
+NAMES_OID = ".1.3.6.1.4.1.476.1.42.3.8.50.20.1.10"
+
+# Status constants returned as value from SNMP
+STATUS_DOWN = 1
+STATUS_UP = 2
+
+# Status constants to set as value to SNMP
+STATUS_SET_OFF = 0
+STATUS_SET_ON = 1
+
+def get_power_status(conn, options):
+ (_, status) = conn.get("%s.%s"% (STATUSES_OID, options["--plug"]))
+ return status == str(STATUS_UP) and "on" or "off"
+
+def set_power_status(conn, options):
+ conn.set("%s.%s" % (CONTROL_OID, options["--plug"]),
+ (options["--action"] == "on" and STATUS_SET_ON or STATUS_SET_OFF))
+
+def get_outlets_status(conn, _):
+ result = {}
+ res_outlet = conn.walk(STATUSES_OID, 30)
+
+ for outlet_info in res_outlet:
+ port_num = ".".join(outlet_info[0].split('.')[-3:])
+ port_alias = conn.get("%s.%s"% (NAMES_OID, port_num))[1]
+ port_status = (outlet_info[1] == str(STATUS_UP) and "on" or "off")
+ result[port_num] = (port_alias, port_status)
+ return result
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["power_wait"]["default"] = "5"
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Emerson over SNMP"
+ docs["longdesc"] = "fence_emerson is an I/O Fencing agent \
+ which can be used with MPX and MPH2 managed rack PDU."
+ docs["vendorurl"] = "http://www.emersonnetworkpower.com"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+if __name__ == "__main__":
+ main()
diff --git a/agents/eps/fence_eps.py b/agents/eps/fence_eps.py
new file mode 100644
index 0000000..f0df862
--- /dev/null
+++ b/agents/eps/fence_eps.py
@@ -0,0 +1,129 @@
+#!@PYTHON@ -tt
+
+# The Following Agent Has Been Tested On:
+# ePowerSwitch 8M+ version 1.0.0.4
+
+import sys, re
+import base64, string, socket
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, EC_LOGIN_DENIED, EC_TIMED_OUT, run_delay
+
+if sys.version_info[0] > 2:
+ import http.client as httplib
+else:
+ import httplib
+
+# Run command on EPS device.
+# @param options Device options
+# @param params HTTP GET parameters (without ?)
+def eps_run_command(options, params):
+ try:
+ # New http connection
+ conn = httplib.HTTPConnection(options["--ip"])
+
+ request_str = "/"+options["--page"]
+
+ if params != "":
+ request_str += "?"+params
+
+ logging.debug("GET %s\n", request_str)
+ conn.putrequest('GET', request_str)
+
+ if "--username" in options:
+ if "--password" not in options:
+ options["--password"] = "" # Default is empty password
+
+ # String for Authorization header
+ auth_str = 'Basic ' + string.strip(base64.encodestring(options["--username"]+':'+options["--password"]))
+ logging.debug("Authorization: %s\n", auth_str)
+ conn.putheader('Authorization', auth_str)
+
+ conn.endheaders()
+
+ response = conn.getresponse()
+
+ logging.debug("%d %s\n", response.status, response.reason)
+
+ #Response != OK -> couldn't login
+ if response.status != 200:
+ fail(EC_LOGIN_DENIED)
+
+ result = response.read()
+ logging.debug("%s \n", result)
+ conn.close()
+ except socket.timeout:
+ fail(EC_TIMED_OUT)
+ except socket.error as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_LOGIN_DENIED)
+
+ return result
+
+def get_power_status(conn, options):
+ del conn
+ ret_val = eps_run_command(options, "")
+
+ result = {}
+ status = re.findall(r"p(\d{2})=(0|1)\s*\<br\>", ret_val.lower())
+ for out_num, out_stat in status:
+ result[out_num] = ("", (out_stat == "1" and "on" or "off"))
+
+ if not options["--action"] in ['monitor', 'list']:
+ if not options["--plug"] in result:
+ fail_usage("Failed: You have to enter existing physical plug!")
+ else:
+ return result[options["--plug"]][1]
+ else:
+ return result
+
+def set_power_status(conn, options):
+ del conn
+ eps_run_command(options, "P%s=%s"%(options["--plug"], (options["--action"] == "on" and "1" or "0")))
+
+# Define new option
+def eps_define_new_opts():
+ all_opt["hidden_page"] = {
+ "getopt" : "c:",
+ "longopt" : "page",
+ "help":"-c, --page=[page] Name of hidden page (default: hidden.htm)",
+ "required" : "0",
+ "shortdesc" : "Name of hidden page",
+ "default" : "hidden.htm",
+ "order": 1
+ }
+
+# Starting point of fence agent
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "hidden_page", "web"]
+
+ atexit.register(atexit_handler)
+
+ eps_define_new_opts()
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for ePowerSwitch"
+ docs["longdesc"] = "fence_eps is an I/O Fencing agent \
+which can be used with the ePowerSwitch 8M+ power switch to fence \
+connected machines. Fence agent works ONLY on 8M+ device, because \
+this is only one, which has support for hidden page feature. \
+\n.TP\n\
+Agent basically works by connecting to hidden page and pass \
+appropriate arguments to GET request. This means, that hidden \
+page feature must be enabled and properly configured."
+ docs["vendorurl"] = "http://www.epowerswitch.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+ #Run fence action. Conn is None, beacause we always need open new http connection
+ result = fence_action(None, options, set_power_status, get_power_status, get_power_status)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/evacuate/fence_evacuate.py b/agents/evacuate/fence_evacuate.py
new file mode 100644
index 0000000..53d6fd1
--- /dev/null
+++ b/agents/evacuate/fence_evacuate.py
@@ -0,0 +1,428 @@
+#!@PYTHON@ -tt
+
+import sys
+import time
+import atexit
+import logging
+import inspect
+import requests.exceptions
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, is_executable, run_command, run_delay
+
+EVACUABLE_TAG = "evacuable"
+TRUE_TAGS = ['true']
+
+def get_power_status(connection, options):
+
+ status = "unknown"
+ logging.debug("get action: " + options["--action"])
+
+ if connection:
+ try:
+ services = connection.services.list(host=options["--plug"], binary="nova-compute")
+ for service in services:
+ logging.debug("Status of %s is %s, %s" % (service.binary, service.state, service.status))
+ if service.state == "up" and service.status == "enabled":
+ # Up and operational
+ status = "on"
+
+ elif service.state == "down" and service.status == "disabled":
+ # Down and fenced
+ status = "off"
+
+ elif service.state == "down":
+ # Down and requires fencing
+ status = "failed"
+
+ elif service.state == "up":
+ # Up and requires unfencing
+ status = "running"
+ else:
+ logging.warning("Unknown status detected from nova for %s: %s, %s" % (options["--plug"], service.state, service.status))
+ status = "%s %s" % (service.state, service.status)
+ break
+ except requests.exception.ConnectionError as err:
+ logging.warning("Nova connection failed: " + str(err))
+ return status
+
+# NOTE(sbauza); We mimic the host-evacuate module since it's only a contrib
+# module which is not stable
+def _server_evacuate(connection, server, on_shared_storage):
+ success = False
+ error_message = ""
+ try:
+ logging.debug("Resurrecting instance: %s" % server)
+ (response, dictionary) = connection.servers.evacuate(server=server, on_shared_storage=on_shared_storage)
+
+ if response == None:
+ error_message = "No response while evacuating instance"
+ elif response.status_code == 200:
+ success = True
+ error_message = response.reason
+ else:
+ error_message = response.reason
+
+ except Exception as e:
+ error_message = "Error while evacuating instance: %s" % e
+
+ return {
+ "uuid": server,
+ "accepted": success,
+ "reason": error_message,
+ }
+
+def _is_server_evacuable(server, evac_flavors, evac_images):
+ reason = "flavor "+server.flavor.get('id')
+ if server.flavor.get('id') in evac_flavors:
+ return True
+ if hasattr(server.image, 'get'):
+ if server.image.get('id') in evac_images:
+ return True
+ reason = reason +" and image "+server.image.get('id')
+
+ logging.debug("Instance is not evacuable: no match for %s" % reason)
+ return False
+
+def _get_evacuable_flavors(connection):
+ result = []
+ flavors = connection.flavors.list(is_public=None)
+ # Since the detailed view for all flavors doesn't provide the extra specs,
+ # we need to call each of the flavor to get them.
+ for flavor in flavors:
+ tag = flavor.get_keys().get(EVACUABLE_TAG)
+ if tag and tag.strip().lower() in TRUE_TAGS:
+ result.append(flavor.id)
+ return result
+
+def _get_evacuable_images(connection):
+ result = []
+ images = []
+ if hasattr(connection, "images"):
+ images = connection.images.list(detailed=True)
+ elif hasattr(connection, "glance"):
+ # OSP12+
+ images = connection.glance.list()
+
+ for image in images:
+ if hasattr(image, 'metadata'):
+ tag = image.metadata.get(EVACUABLE_TAG)
+ if tag and tag.strip().lower() in TRUE_TAGS:
+ result.append(image.id)
+ elif hasattr(image, 'tags'):
+ # OSP12+
+ if EVACUABLE_TAG in image.tags:
+ result.append(image.id)
+ return result
+
+def _host_evacuate(connection, options):
+ result = True
+ images = _get_evacuable_images(connection)
+ flavors = _get_evacuable_flavors(connection)
+ servers = connection.servers.list(search_opts={'host': options["--plug"], 'all_tenants': 1 })
+
+ if options["--instance-filtering"] == "False":
+ logging.debug("Not evacuating anything")
+ evacuables = []
+ elif len(flavors) or len(images):
+ logging.debug("Filtering images and flavors: %s %s" % (repr(flavors), repr(images)))
+ # Identify all evacuable servers
+ logging.debug("Checking %s" % repr(servers))
+ evacuables = [server for server in servers
+ if _is_server_evacuable(server, flavors, images)]
+ logging.debug("Evacuating %s" % repr(evacuables))
+ else:
+ logging.debug("Evacuating all images and flavors")
+ evacuables = servers
+
+ if options["--no-shared-storage"] != "False":
+ on_shared_storage = False
+ else:
+ on_shared_storage = True
+
+ for server in evacuables:
+ logging.debug("Processing %s" % server)
+ if hasattr(server, 'id'):
+ response = _server_evacuate(connection, server.id, on_shared_storage)
+ if response["accepted"]:
+ logging.debug("Evacuated %s from %s: %s" %
+ (response["uuid"], options["--plug"], response["reason"]))
+ else:
+ logging.error("Evacuation of %s on %s failed: %s" %
+ (response["uuid"], options["--plug"], response["reason"]))
+ result = False
+ else:
+ logging.error("Could not evacuate instance: %s" % server.to_dict())
+ # Should a malformed instance result in a failed evacuation?
+ # result = False
+ return result
+
+def set_attrd_status(host, status, options):
+ logging.debug("Setting fencing status for %s to %s" % (host, status))
+ run_command(options, "attrd_updater -p -n evacuate -Q -N %s -U %s" % (host, status))
+
+def set_power_status(connection, options):
+ logging.debug("set action: " + options["--action"])
+
+ if not connection:
+ return
+
+ if options["--action"] == "off" and not _host_evacuate(options):
+ sys.exit(1)
+
+ sys.exit(0)
+
+def get_plugs_list(connection, options):
+ result = {}
+
+ if connection:
+ services = connection.services.list(binary="nova-compute")
+ for service in services:
+ longhost = service.host
+ shorthost = longhost.split('.')[0]
+ result[longhost] = ("", None)
+ result[shorthost] = ("", None)
+ return result
+
+def create_nova_connection(options):
+ nova = None
+
+ try:
+ from novaclient import client
+ from novaclient.exceptions import NotAcceptable
+ except ImportError:
+ fail_usage("Nova not found or not accessible")
+
+ from keystoneauth1 import loading
+ from keystoneauth1 import session
+ from keystoneclient import discover
+
+ # Prefer the oldest and strip the leading 'v'
+ keystone_versions = discover.available_versions(options["--auth-url"])
+ keystone_version = keystone_versions[0]['id'][1:]
+ kwargs = dict(
+ auth_url=options["--auth-url"],
+ username=options["--username"],
+ password=options["--password"]
+ )
+
+ if discover.version_match("2", keystone_version):
+ kwargs["tenant_name"] = options["--tenant-name"]
+
+ elif discover.version_match("3", keystone_version):
+ kwargs["project_name"] = options["--tenant-name"]
+ kwargs["user_domain_name"] = options["--user-domain"]
+ kwargs["project_domain_name"] = options["--project-domain"]
+
+ loader = loading.get_plugin_loader('password')
+ keystone_auth = loader.load_from_options(**kwargs)
+ keystone_session = session.Session(auth=keystone_auth, verify=not "--insecure" in options)
+
+ versions = [ "2.11", "2" ]
+ for version in versions:
+ clientargs = inspect.getargspec(client.Client).varargs
+
+ # Some versions of Openstack prior to Ocata only
+ # supported positional arguments for username,
+ # password, and tenant.
+ #
+ # Versions since Ocata only support named arguments.
+ #
+ # So we need to use introspection to figure out how to
+ # create a Nova client.
+ #
+ # Happy days
+ #
+ if clientargs:
+ # OSP < 11
+ # ArgSpec(args=['version', 'username', 'password', 'project_id', 'auth_url'],
+ # varargs=None,
+ # keywords='kwargs', defaults=(None, None, None, None))
+ nova = client.Client(version,
+ None, # User
+ None, # Password
+ None, # Tenant
+ None, # Auth URL
+ insecure="--insecure" in options,
+ region_name=options["--region-name"],
+ endpoint_type=options["--endpoint-type"],
+ session=keystone_session, auth=keystone_auth,
+ http_log_debug="--verbose" in options)
+ else:
+ # OSP >= 11
+ # ArgSpec(args=['version'], varargs='args', keywords='kwargs', defaults=None)
+ nova = client.Client(version,
+ region_name=options["--region-name"],
+ endpoint_type=options["--endpoint-type"],
+ session=keystone_session, auth=keystone_auth,
+ http_log_debug="--verbose" in options)
+
+ try:
+ nova.hypervisors.list()
+ return nova
+
+ except NotAcceptable as e:
+ logging.warning(e)
+
+ except Exception as e:
+ logging.warning("Nova connection failed. %s: %s" % (e.__class__.__name__, e))
+
+ logging.warning("Couldn't obtain a supported connection to nova, tried: %s\n" % repr(versions))
+ return None
+
+def define_new_opts():
+ all_opt["endpoint_type"] = {
+ "getopt" : "e:",
+ "longopt" : "endpoint-type",
+ "help" : "-e, --endpoint-type=[endpoint] Nova Endpoint type (publicURL, internalURL, adminURL)",
+ "required" : "0",
+ "shortdesc" : "Nova Endpoint type",
+ "default" : "internalURL",
+ "order": 1,
+ }
+ all_opt["tenant_name"] = {
+ "getopt" : "t:",
+ "longopt" : "tenant-name",
+ "help" : "-t, --tenant-name=[name] Keystone v2 Tenant or v3 Project Name",
+ "required" : "0",
+ "shortdesc" : "Keystone Admin Tenant or v3 Project",
+ "default" : "",
+ "order": 1,
+ }
+ all_opt["user-domain"] = {
+ "getopt" : "u:",
+ "longopt" : "user-domain",
+ "help" : "-u, --user-domain=[name] Keystone v3 User Domain",
+ "required" : "0",
+ "shortdesc" : "Keystone v3 User Domain",
+ "default" : "Default",
+ "order": 2,
+ }
+ all_opt["project-domain"] = {
+ "getopt" : "P:",
+ "longopt" : "project-domain",
+ "help" : "-P, --project-domain=[name] Keystone v3 Project Domain",
+ "required" : "0",
+ "shortdesc" : "Keystone v3 Project Domain",
+ "default" : "Default",
+ "order": 2,
+ }
+ all_opt["auth_url"] = {
+ "getopt" : "k:",
+ "longopt" : "auth-url",
+ "help" : "-k, --auth-url=[url] Keystone Admin Auth URL",
+ "required" : "0",
+ "shortdesc" : "Keystone Admin Auth URL",
+ "default" : "",
+ "order": 1,
+ }
+ all_opt["region_name"] = {
+ "getopt" : ":",
+ "longopt" : "region-name",
+ "help" : "--region-name=[region] Region Name",
+ "required" : "0",
+ "shortdesc" : "Region Name",
+ "default" : "",
+ "order": 1,
+ }
+ all_opt["insecure"] = {
+ "getopt" : "",
+ "longopt" : "insecure",
+ "help" : "--insecure Explicitly allow agent to perform \"insecure\" TLS (https) requests",
+ "required" : "0",
+ "shortdesc" : "Allow Insecure TLS Requests",
+ "order": 2,
+ }
+ all_opt["domain"] = {
+ "getopt" : "d:",
+ "longopt" : "domain",
+ "help" : "-d, --domain=[string] DNS domain in which hosts live, useful when the cluster uses short names and nova uses FQDN",
+ "required" : "0",
+ "shortdesc" : "DNS domain in which hosts live",
+ "order": 5,
+ }
+ all_opt["instance_filtering"] = {
+ "getopt" : "",
+ "longopt" : "instance-filtering",
+ "help" : "--instance-filtering Allow instances created from images and flavors with evacuable=true to be evacuated (or all if no images/flavors have been tagged)",
+ "required" : "0",
+ "shortdesc" : "Allow instances to be evacuated",
+ "default" : "True",
+ "order": 5,
+ }
+ all_opt["no_shared_storage"] = {
+ "getopt" : "",
+ "longopt" : "no-shared-storage",
+ "help" : "--no-shared-storage Disable functionality for shared storage",
+ "required" : "0",
+ "shortdesc" : "Disable functionality for dealing with shared storage",
+ "default" : "False",
+ "order": 5,
+ }
+ all_opt["compute-domain"] = {
+ "getopt" : ":",
+ "longopt" : "compute-domain",
+ "help" : "--compute-domain=[string] Replaced by --domain",
+ "required" : "0",
+ "shortdesc" : "Replaced by domain",
+ "order": 6,
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["login", "passwd", "tenant_name", "auth_url",
+ "no_login", "no_password", "port", "domain", "compute-domain",
+ "project-domain", "user-domain", "no_shared_storage",
+ "endpoint_type", "instance_filtering", "insecure", "region_name"]
+ define_new_opts()
+ all_opt["shell_timeout"]["default"] = "180"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for the automatic resurrection of OpenStack compute instances"
+ docs["longdesc"] = "Used to reschedule flagged instances"
+ docs["vendorurl"] = ""
+
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # workaround to avoid regressions
+ if "--compute-domain" in options and options["--compute-domain"]:
+ options["--domain"] = options["--compute-domain"]
+ del options["--domain"]
+
+
+ # Disable insecure-certificate-warning message
+ if "--insecure" in options:
+ import urllib3
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+ connection = create_nova_connection(options)
+
+ # Un-evacuating a server doesn't make sense
+ if options["--action"] in ["on"]:
+ logging.error("Action %s is not supported by this agent" % (options["--action"]))
+ sys.exit(1)
+
+ if options["--action"] in ["off", "reboot"]:
+ status = get_power_status(connection, options)
+ if status != "off":
+ logging.error("Cannot resurrect instances from %s in state '%s'" % (options["--plug"], status))
+ sys.exit(1)
+
+ elif not _host_evacuate(connection, options):
+ logging.error("Resurrection of instances from %s failed" % (options["--plug"]))
+ sys.exit(1)
+
+ logging.info("Resurrection of instances from %s complete" % (options["--plug"]))
+ sys.exit(0)
+
+ result = fence_action(connection, options, set_power_status, get_power_status, get_plugs_list, None)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/gce/fence_gce.py b/agents/gce/fence_gce.py
new file mode 100644
index 0000000..2c815b8
--- /dev/null
+++ b/agents/gce/fence_gce.py
@@ -0,0 +1,632 @@
+#!@PYTHON@ -tt
+
+#
+# Requires the googleapiclient and oauth2client
+# RHEL 7.x: google-api-python-client==1.6.7 python-gflags==2.0 pyasn1==0.4.8 rsa==3.4.2 pysocks==1.7.1 httplib2==0.19.0
+# RHEL 8.x: pysocks==1.7.1 httplib2==0.19.0
+# SLES 12.x: python-google-api-python-client python-oauth2client python-oauth2client-gce pysocks==1.7.1 httplib2==0.19.0
+# SLES 15.x: python3-google-api-python-client python3-oauth2client pysocks==1.7.1 httplib2==0.19.0
+#
+
+import atexit
+import logging
+import json
+import re
+import os
+import socket
+import sys
+import time
+
+from ssl import SSLError
+
+if sys.version_info >= (3, 0):
+ # Python 3 imports.
+ import urllib.parse as urlparse
+ import urllib.request as urlrequest
+else:
+ # Python 2 imports.
+ import urllib as urlparse
+ import urllib2 as urlrequest
+sys.path.append("@FENCEAGENTSLIBDIR@")
+
+from fencing import fail_usage, run_delay, all_opt, atexit_handler, check_input, process_input, show_docs, fence_action, run_command
+try:
+ import httplib2
+ import googleapiclient.discovery
+ import socks
+ try:
+ from google.oauth2.credentials import Credentials as GoogleCredentials
+ except:
+ from oauth2client.client import GoogleCredentials
+except:
+ pass
+
+VERSION = '1.0.5'
+ACTION_IDS = {
+ 'on': 1, 'off': 2, 'reboot': 3, 'status': 4, 'list': 5, 'list-status': 6,
+ 'monitor': 7, 'metadata': 8, 'manpage': 9, 'validate-all': 10
+}
+USER_AGENT = 'sap-core-eng/fencegce/%s/%s/ACTION/%s'
+METADATA_SERVER = 'http://metadata.google.internal/computeMetadata/v1/'
+METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
+INSTANCE_LINK = 'https://www.googleapis.com/compute/v1/projects/{}/zones/{}/instances/{}'
+
+def run_on_fail(options):
+ if "--runonfail" in options:
+ run_command(options, options["--runonfail"])
+
+def fail_fence_agent(options, message):
+ run_on_fail(options)
+ fail_usage(message)
+
+def raise_fence_agent(options, message):
+ run_on_fail(options)
+ raise Exception(message)
+
+#
+# Will use baremetalsolution setting or the environment variable
+# FENCE_GCE_URI_REPLACEMENTS to replace the uri for calls to *.googleapis.com.
+#
+def replace_api_uri(options, http_request):
+ uri_replacements = []
+ # put any env var replacements first, then baremetalsolution if in options
+ if "FENCE_GCE_URI_REPLACEMENTS" in os.environ:
+ logging.debug("FENCE_GCE_URI_REPLACEMENTS environment variable exists")
+ env_uri_replacements = os.environ["FENCE_GCE_URI_REPLACEMENTS"]
+ try:
+ uri_replacements_json = json.loads(env_uri_replacements)
+ if isinstance(uri_replacements_json, list):
+ uri_replacements = uri_replacements_json
+ else:
+ logging.warning("FENCE_GCE_URI_REPLACEMENTS exists, but is not a JSON List")
+ except ValueError as e:
+ logging.warning("FENCE_GCE_URI_REPLACEMENTS exists but is not valid JSON")
+ if "--baremetalsolution" in options:
+ uri_replacements.append(
+ {
+ "matchlength": 4,
+ "match": "https://compute.googleapis.com/compute/v1/projects/(.*)/zones/(.*)/instances/(.*)/reset(.*)",
+ "replace": "https://baremetalsolution.googleapis.com/v1/projects/\\1/locations/\\2/instances/\\3:resetInstance\\4"
+ })
+ for uri_replacement in uri_replacements:
+ # each uri_replacement should have matchlength, match, and replace
+ if "matchlength" not in uri_replacement or "match" not in uri_replacement or "replace" not in uri_replacement:
+ logging.warning("FENCE_GCE_URI_REPLACEMENTS missing matchlength, match, or replace in %s" % uri_replacement)
+ continue
+ match = re.match(uri_replacement["match"], http_request.uri)
+ if match is None or len(match.groups()) != uri_replacement["matchlength"]:
+ continue
+ replaced_uri = re.sub(uri_replacement["match"], uri_replacement["replace"], http_request.uri)
+ match = re.match("https:\/\/.*.googleapis.com", replaced_uri)
+ if match is None or match.start() != 0:
+ logging.warning("FENCE_GCE_URI_REPLACEMENTS replace is not "
+ "targeting googleapis.com, ignoring it: %s" % replaced_uri)
+ continue
+ logging.debug("Replacing googleapis uri %s with %s" % (http_request.uri, replaced_uri))
+ http_request.uri = replaced_uri
+ break
+ return http_request
+
+def retry_api_execute(options, http_request):
+ replaced_http_request = replace_api_uri(options, http_request)
+ action = ACTION_IDS[options["--action"]] if options["--action"] in ACTION_IDS else 0
+ try:
+ user_agent_header = USER_AGENT % (VERSION, options["image"], action)
+ except ValueError:
+ user_agent_header = USER_AGENT % (VERSION, options["image"], 0)
+ replaced_http_request.headers["User-Agent"] = user_agent_header
+ logging.debug("User agent set as %s" % (user_agent_header))
+ retries = 3
+ if options.get("--retries"):
+ retries = int(options.get("--retries"))
+ retry_sleep = 5
+ if options.get("--retrysleep"):
+ retry_sleep = int(options.get("--retrysleep"))
+ retry = 0
+ current_err = None
+ while retry <= retries:
+ if retry > 0:
+ time.sleep(retry_sleep)
+ try:
+ return replaced_http_request.execute()
+ except Exception as err:
+ current_err = err
+ logging.warning("Could not execute api call to: %s, retry: %s, "
+ "err: %s" % (replaced_http_request.uri, retry, str(err)))
+ retry += 1
+ raise current_err
+
+
+def translate_status(instance_status):
+ "Returns on | off | unknown."
+ if instance_status == "RUNNING":
+ return "on"
+ elif instance_status == "TERMINATED":
+ return "off"
+ return "unknown"
+
+
+def get_nodes_list(conn, options):
+ result = {}
+ plug = options["--plug"] if "--plug" in options else ""
+ zones = options["--zone"] if "--zone" in options else ""
+ if not zones:
+ zones = get_zone(conn, options, plug) if "--plugzonemap" not in options else options["--plugzonemap"][plug]
+ try:
+ for zone in zones.split(","):
+ instanceList = retry_api_execute(options, conn.instances().list(
+ project=options["--project"],
+ zone=zone))
+ for instance in instanceList["items"]:
+ result[instance["id"]] = (instance["name"], translate_status(instance["status"]))
+ except Exception as err:
+ fail_fence_agent(options, "Failed: get_nodes_list: {}".format(str(err)))
+
+ return result
+
+
+def get_power_status(conn, options):
+ logging.debug("get_power_status")
+ # if this is bare metal we need to just send back the opposite of the
+ # requested action: if on send off, if off send on
+ if "--baremetalsolution" in options:
+ if options.get("--action") == "on":
+ return "off"
+ else:
+ return "on"
+ # If zone is not listed for an entry we attempt to get it automatically
+ instance = options["--plug"]
+ zone = get_zone(conn, options, instance) if "--plugzonemap" not in options else options["--plugzonemap"][instance]
+ instance_status = get_instance_power_status(conn, options, instance, zone)
+ # If any of the instances do not match the intended status we return the
+ # the opposite status so that the fence agent can change it.
+ if instance_status != options.get("--action"):
+ return instance_status
+
+ return options.get("--action")
+
+
+def get_instance_power_status(conn, options, instance, zone):
+ try:
+ instance = retry_api_execute(
+ options,
+ conn.instances().get(project=options["--project"], zone=zone, instance=instance))
+ return translate_status(instance["status"])
+ except Exception as err:
+ fail_fence_agent(options, "Failed: get_instance_power_status: {}".format(str(err)))
+
+
+def check_for_existing_operation(conn, options, instance, zone, operation_type):
+ logging.debug("check_for_existing_operation")
+ if "--baremetalsolution" in options:
+ # There is no API for checking in progress operations
+ return False
+
+ project = options["--project"]
+ target_link = INSTANCE_LINK.format(project, zone, instance)
+ query_filter = '(targetLink = "{}") AND (operationType = "{}") AND (status = "RUNNING")'.format(target_link, operation_type)
+ result = retry_api_execute(
+ options,
+ conn.zoneOperations().list(project=project, zone=zone, filter=query_filter, maxResults=1))
+
+ if "items" in result and result["items"]:
+ logging.info("Existing %s operation found", operation_type)
+ return result["items"][0]
+
+
+def wait_for_operation(conn, options, zone, operation):
+ if 'name' not in operation:
+ logging.warning('Cannot wait for operation to complete, the'
+ ' requested operation will continue asynchronously')
+ return False
+
+ wait_time = 0
+ project = options["--project"]
+ while True:
+ result = retry_api_execute(options, conn.zoneOperations().get(
+ project=project,
+ zone=zone,
+ operation=operation['name']))
+ if result['status'] == 'DONE':
+ if 'error' in result:
+ raise_fence_agent(options, result['error'])
+ return True
+
+ if "--errortimeout" in options and wait_time > int(options["--errortimeout"]):
+ raise_fence_agent(options, "Operation did not complete before the timeout.")
+
+ if "--warntimeout" in options and wait_time > int(options["--warntimeout"]):
+ logging.warning("Operation did not complete before the timeout.")
+ if "--runonwarn" in options:
+ run_command(options, options["--runonwarn"])
+ return False
+
+ wait_time = wait_time + 1
+ time.sleep(1)
+
+
+def set_power_status(conn, options):
+ logging.debug("set_power_status")
+ instance = options["--plug"]
+ # If zone is not listed for an entry we attempt to get it automatically
+ zone = get_zone(conn, options, instance) if "--plugzonemap" not in options else options["--plugzonemap"][instance]
+ set_instance_power_status(conn, options, instance, zone, options["--action"])
+
+
+def set_instance_power_status(conn, options, instance, zone, action):
+ logging.info("Setting power status of %s in zone %s", instance, zone)
+ project = options["--project"]
+
+ try:
+ if action == "off":
+ logging.info("Issuing poweroff of %s in zone %s", instance, zone)
+ operation = check_for_existing_operation(conn, options, instance, zone, "stop")
+ if operation and "--earlyexit" in options:
+ return
+ if not operation:
+ operation = retry_api_execute(
+ options,
+ conn.instances().stop(project=project, zone=zone, instance=instance))
+ logging.info("Poweroff command completed, waiting for the operation to complete")
+ if wait_for_operation(conn, options, zone, operation):
+ logging.info("Poweroff of %s in zone %s complete", instance, zone)
+ elif action == "on":
+ logging.info("Issuing poweron of %s in zone %s", instance, zone)
+ operation = check_for_existing_operation(conn, options, instance, zone, "start")
+ if operation and "--earlyexit" in options:
+ return
+ if not operation:
+ operation = retry_api_execute(
+ options,
+ conn.instances().start(project=project, zone=zone, instance=instance))
+ if wait_for_operation(conn, options, zone, operation):
+ logging.info("Poweron of %s in zone %s complete", instance, zone)
+ except Exception as err:
+ fail_fence_agent(options, "Failed: set_instance_power_status: {}".format(str(err)))
+
+def power_cycle(conn, options):
+ logging.debug("power_cycle")
+ instance = options["--plug"]
+ # If zone is not listed for an entry we attempt to get it automatically
+ zone = get_zone(conn, options, instance) if "--plugzonemap" not in options else options["--plugzonemap"][instance]
+ return power_cycle_instance(conn, options, instance, zone)
+
+
+def power_cycle_instance(conn, options, instance, zone):
+ logging.info("Issuing reset of %s in zone %s", instance, zone)
+ project = options["--project"]
+
+ try:
+ operation = check_for_existing_operation(conn, options, instance, zone, "reset")
+ if operation and "--earlyexit" in options:
+ return True
+ if not operation:
+ operation = retry_api_execute(
+ options,
+ conn.instances().reset(project=project, zone=zone, instance=instance))
+ logging.info("Reset command sent, waiting for the operation to complete")
+ if wait_for_operation(conn, options, zone, operation):
+ logging.info("Reset of %s in zone %s complete", instance, zone)
+ return True
+ except Exception as err:
+ logging.exception("Failed: power_cycle")
+ raise err
+
+
+def get_zone(conn, options, instance):
+ logging.debug("get_zone");
+ project = options['--project']
+ fl = 'name="%s"' % instance
+ request = replace_api_uri(options, conn.instances().aggregatedList(project=project, filter=fl))
+ while request is not None:
+ response = request.execute()
+ zones = response.get('items', {})
+ for zone in zones.values():
+ for inst in zone.get('instances', []):
+ if inst['name'] == instance:
+ return inst['zone'].split("/")[-1]
+ request = replace_api_uri(options, conn.instances().aggregatedList_next(
+ previous_request=request, previous_response=response))
+ raise_fence_agent(options, "Unable to find instance %s" % (instance))
+
+
+def get_metadata(metadata_key, params=None, timeout=None):
+ """Performs a GET request with the metadata headers.
+
+ Args:
+ metadata_key: string, the metadata to perform a GET request on.
+ params: dictionary, the query parameters in the GET request.
+ timeout: int, timeout in seconds for metadata requests.
+
+ Returns:
+ HTTP response from the GET request.
+
+ Raises:
+ urlerror.HTTPError: raises when the GET request fails.
+ """
+ logging.debug("get_metadata");
+ timeout = timeout or 60
+ metadata_url = os.path.join(METADATA_SERVER, metadata_key)
+ params = urlparse.urlencode(params or {})
+ url = '%s?%s' % (metadata_url, params)
+ request = urlrequest.Request(url, headers=METADATA_HEADERS)
+ request_opener = urlrequest.build_opener(urlrequest.ProxyHandler({}))
+ return request_opener.open(request, timeout=timeout * 1.1).read().decode("utf-8")
+
+
+def define_new_opts():
+ all_opt["zone"] = {
+ "getopt" : ":",
+ "longopt" : "zone",
+ "help" : "--zone=[name] Zone, e.g. us-central1-b",
+ "shortdesc" : "Zone.",
+ "required" : "0",
+ "order" : 2
+ }
+ all_opt["project"] = {
+ "getopt" : ":",
+ "longopt" : "project",
+ "help" : "--project=[name] Project ID",
+ "shortdesc" : "Project ID.",
+ "required" : "0",
+ "order" : 3
+ }
+ all_opt["stackdriver-logging"] = {
+ "getopt" : "",
+ "longopt" : "stackdriver-logging",
+ "help" : "--stackdriver-logging Enable Logging to Stackdriver",
+ "shortdesc" : "Stackdriver-logging support.",
+ "longdesc" : "If enabled IP failover logs will be posted to stackdriver logging.",
+ "required" : "0",
+ "order" : 4
+ }
+ all_opt["baremetalsolution"] = {
+ "getopt" : "",
+ "longopt" : "baremetalsolution",
+ "help" : "--baremetalsolution Enable on bare metal",
+ "shortdesc" : "If enabled this is a bare metal offering from google.",
+ "required" : "0",
+ "order" : 5
+ }
+ all_opt["apitimeout"] = {
+ "getopt" : ":",
+ "type" : "second",
+ "longopt" : "apitimeout",
+ "help" : "--apitimeout=[seconds] Timeout to use for API calls",
+ "shortdesc" : "Timeout in seconds to use for API calls, default is 60.",
+ "required" : "0",
+ "default" : 60,
+ "order" : 6
+ }
+ all_opt["retries"] = {
+ "getopt" : ":",
+ "type" : "integer",
+ "longopt" : "retries",
+ "help" : "--retries=[retries] Number of retries on failure for API calls",
+ "shortdesc" : "Number of retries on failure for API calls, default is 3.",
+ "required" : "0",
+ "default" : 3,
+ "order" : 7
+ }
+ all_opt["retrysleep"] = {
+ "getopt" : ":",
+ "type" : "second",
+ "longopt" : "retrysleep",
+ "help" : "--retrysleep=[seconds] Time to sleep between API retries",
+ "shortdesc" : "Time to sleep in seconds between API retries, default is 5.",
+ "required" : "0",
+ "default" : 5,
+ "order" : 8
+ }
+ all_opt["serviceaccount"] = {
+ "getopt" : ":",
+ "longopt" : "serviceaccount",
+ "help" : "--serviceaccount=[filename] Service account json file location e.g. serviceaccount=/somedir/service_account.json",
+ "shortdesc" : "Service Account to use for authentication to the google cloud APIs.",
+ "required" : "0",
+ "order" : 9
+ }
+ all_opt["plugzonemap"] = {
+ "getopt" : ":",
+ "longopt" : "plugzonemap",
+ "help" : "--plugzonemap=[plugzonemap] Comma separated zone map when fencing multiple plugs",
+ "shortdesc" : "Comma separated zone map when fencing multiple plugs.",
+ "required" : "0",
+ "order" : 10
+ }
+ all_opt["proxyhost"] = {
+ "getopt" : ":",
+ "longopt" : "proxyhost",
+ "help" : "--proxyhost=[proxy_host] The proxy host to use, if one is needed to access the internet (Example: 10.122.0.33)",
+ "shortdesc" : "If a proxy is used for internet access, the proxy host should be specified.",
+ "required" : "0",
+ "order" : 11
+ }
+ all_opt["proxyport"] = {
+ "getopt" : ":",
+ "type" : "integer",
+ "longopt" : "proxyport",
+ "help" : "--proxyport=[proxy_port] The proxy port to use, if one is needed to access the internet (Example: 3127)",
+ "shortdesc" : "If a proxy is used for internet access, the proxy port should be specified.",
+ "required" : "0",
+ "order" : 12
+ }
+ all_opt["earlyexit"] = {
+ "getopt" : "",
+ "longopt" : "earlyexit",
+ "help" : "--earlyexit Return early if reset is already in progress",
+ "shortdesc" : "If an existing reset operation is detected, the fence agent will return before the operation completes with a 0 return code.",
+ "required" : "0",
+ "order" : 13
+ }
+ all_opt["warntimeout"] = {
+ "getopt" : ":",
+ "type" : "second",
+ "longopt" : "warntimeout",
+ "help" : "--warntimeout=[warn_timeout] Timeout seconds before logging a warning and returning a 0 status code",
+ "shortdesc" : "If the operation is not completed within the timeout, the cluster operations are allowed to continue.",
+ "required" : "0",
+ "order" : 14
+ }
+ all_opt["errortimeout"] = {
+ "getopt" : ":",
+ "type" : "second",
+ "longopt" : "errortimeout",
+ "help" : "--errortimeout=[error_timeout] Timeout seconds before failing and returning a non-zero status code",
+ "shortdesc" : "If the operation is not completed within the timeout, cluster is notified of the operation failure.",
+ "required" : "0",
+ "order" : 15
+ }
+ all_opt["runonwarn"] = {
+ "getopt" : ":",
+ "longopt" : "runonwarn",
+ "help" : "--runonwarn=[run_on_warn] If a timeout occurs and warning is generated, run the supplied command",
+ "shortdesc" : "If a timeout would occur while running the agent, then the supplied command is run.",
+ "required" : "0",
+ "order" : 16
+ }
+ all_opt["runonfail"] = {
+ "getopt" : ":",
+ "longopt" : "runonfail",
+ "help" : "--runonfail=[run_on_fail] If a failure occurs, run the supplied command",
+ "shortdesc" : "If a failure would occur while running the agent, then the supplied command is run.",
+ "required" : "0",
+ "order" : 17
+ }
+
+
+def main():
+ conn = None
+
+ device_opt = ["port", "no_password", "zone", "project", "stackdriver-logging",
+ "method", "baremetalsolution", "apitimeout", "retries", "retrysleep",
+ "serviceaccount", "plugzonemap", "proxyhost", "proxyport", "earlyexit",
+ "warntimeout", "errortimeout", "runonwarn", "runonfail"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["power_timeout"]["default"] = "60"
+ all_opt["method"]["default"] = "cycle"
+ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for GCE (Google Cloud Engine)"
+ docs["longdesc"] = "fence_gce is an I/O Fencing agent for GCE (Google Cloud " \
+ "Engine). It uses the googleapiclient library to connect to GCE.\n" \
+ "googleapiclient can be configured with Google SDK CLI or by " \
+ "executing 'gcloud auth application-default login'.\n" \
+ "For instructions see: https://cloud.google.com/compute/docs/tutorials/python-guide"
+ docs["vendorurl"] = "http://cloud.google.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # Prepare logging
+ if options.get('--verbose') is None:
+ logging.getLogger('googleapiclient').setLevel(logging.ERROR)
+ logging.getLogger('oauth2client').setLevel(logging.ERROR)
+ if options.get('--stackdriver-logging') is not None and options.get('--plug'):
+ try:
+ import google.cloud.logging.handlers
+ client = google.cloud.logging.Client()
+ handler = google.cloud.logging.handlers.CloudLoggingHandler(client, name=options['--plug'])
+ handler.setLevel(logging.INFO)
+ formatter = logging.Formatter('gcp:stonith "%(message)s"')
+ handler.setFormatter(formatter)
+ root_logger = logging.getLogger()
+ if options.get('--verbose') is None:
+ root_logger.setLevel(logging.INFO)
+ root_logger.addHandler(handler)
+ except ImportError:
+ logging.error('Couldn\'t import google.cloud.logging, '
+ 'disabling Stackdriver-logging support')
+
+ # if apitimeout is defined we set the socket timeout, if not we keep the
+ # socket default which is 60s
+ if options.get("--apitimeout"):
+ socket.setdefaulttimeout(options["--apitimeout"])
+
+ # Prepare cli
+ try:
+ serviceaccount = options.get("--serviceaccount")
+ if serviceaccount:
+ scope = ['https://www.googleapis.com/auth/cloud-platform']
+ logging.debug("using credentials from service account")
+ try:
+ from google.oauth2.service_account import Credentials as ServiceAccountCredentials
+ credentials = ServiceAccountCredentials.from_service_account_file(filename=serviceaccount, scopes=scope)
+ except ImportError:
+ from oauth2client.service_account import ServiceAccountCredentials
+ credentials = ServiceAccountCredentials.from_json_keyfile_name(serviceaccount, scope)
+ else:
+ try:
+ from googleapiclient import _auth
+ credentials = _auth.default_credentials();
+ except:
+ credentials = GoogleCredentials.get_application_default()
+ logging.debug("using application default credentials")
+
+ if options.get("--proxyhost") and options.get("--proxyport"):
+ proxy_info = httplib2.ProxyInfo(
+ proxy_type=socks.PROXY_TYPE_HTTP,
+ proxy_host=options.get("--proxyhost"),
+ proxy_port=int(options.get("--proxyport")))
+ http = credentials.authorize(httplib2.Http(proxy_info=proxy_info))
+ conn = googleapiclient.discovery.build(
+ 'compute', 'v1', http=http, cache_discovery=False)
+ else:
+ conn = googleapiclient.discovery.build(
+ 'compute', 'v1', credentials=credentials, cache_discovery=False)
+ except SSLError as err:
+ fail_fence_agent(options, "Failed: Create GCE compute v1 connection: {}\n\nThis might be caused by old versions of httplib2.".format(str(err)))
+ except Exception as err:
+ fail_fence_agent(options, "Failed: Create GCE compute v1 connection: {}".format(str(err)))
+
+ # Get project and zone
+ if not options.get("--project"):
+ try:
+ options["--project"] = get_metadata('project/project-id')
+ except Exception as err:
+ fail_fence_agent(options, "Failed retrieving GCE project. Please provide --project option: {}".format(str(err)))
+
+ try:
+ image = get_metadata('instance/image')
+ options["image"] = image[image.rindex('/')+1:]
+ except Exception as err:
+ options["image"] = "unknown"
+
+ if "--baremetalsolution" in options:
+ options["--zone"] = "none"
+
+ # Populates zone automatically if missing from the command
+ zones = [] if not "--zone" in options else options["--zone"].split(",")
+ options["--plugzonemap"] = {}
+ if "--plug" in options:
+ for i, instance in enumerate(options["--plug"].split(",")):
+ if len(zones) == 1:
+ # If only one zone is specified, use it across all plugs
+ options["--plugzonemap"][instance] = zones[0]
+ continue
+
+ if len(zones) - 1 >= i:
+ # If we have enough zones specified with the --zone flag use the zone at
+ # the same index as the plug
+ options["--plugzonemap"][instance] = zones[i]
+ continue
+
+ try:
+ # In this case we do not have a zone specified so we attempt to detect it
+ options["--plugzonemap"][instance] = get_zone(conn, options, instance)
+ except Exception as err:
+ fail_fence_agent(options, "Failed retrieving GCE zone. Please provide --zone option: {}".format(str(err)))
+
+ # Operate the fencing device
+ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list, power_cycle)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/hds_cb/fence_hds_cb.py b/agents/hds_cb/fence_hds_cb.py
new file mode 100755
index 0000000..375054c
--- /dev/null
+++ b/agents/hds_cb/fence_hds_cb.py
@@ -0,0 +1,132 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Model Modle/Firmware
+## +--------------------+---------------------------+
+## (1) Main application CB2000/A0300-E-6617
+##
+#####
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+RE_STATUS_LINE = r"^([0-9]+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"
+
+def get_power_status(conn, options):
+ #### Maybe should put a conn.log_expect here to make sure
+ #### we have properly entered into the main menu
+ conn.sendline("S") # Enter System Command Mode
+ conn.log_expect("SVP>", int(options["--shell-timeout"]))
+ conn.sendline("PC") # Enter partition control
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ result = {}
+ # Status can now be obtained from the output of the PC
+ # command. Line looks like the following:
+ # "P Power Condition LID lamp Mode Auto power on"
+ # "0 On Normal Off Basic Synchronized"
+ # "1 On Normal Off Basic Synchronized"
+ for line in conn.before.splitlines():
+ # populate the relevant fields based on regex
+ partition = re.search(RE_STATUS_LINE, line)
+ if partition != None:
+ # find the blade number defined in args
+ if partition.group(1) == options["--plug"]:
+ result = partition.group(2).lower()
+ # We must make sure we go back to the main menu as the
+ # status is checked before any fencing operations are
+ # executed. We could in theory save some time by staying in
+ # the partition control, but the logic is a little cleaner
+ # this way.
+ conn.sendline("Q") # Back to system command mode
+ conn.log_expect("SVP>", int(options["--shell-timeout"]))
+ conn.sendline("EX") # Back to system console main menu
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ return result
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "P",
+ 'off': "F",
+ 'reboot' : "H",
+ }[options["--action"]]
+
+ conn.sendline("S") # Enter System Command Mode
+ conn.log_expect("SVP>", int(options["--shell-timeout"]))
+ conn.sendline("PC") # Enter partition control
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.sendline("P") # Enter power control menu
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.sendline(action) # Execute action from array above
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.sendline(options["--plug"]) # Select blade number from args
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.sendline("Y") # Confirm action
+ conn.log_expect("Hit enter key.", int(options["--shell-timeout"]))
+ conn.sendline("") # Press the any key
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.sendline("Q") # Quit back to partition control
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.sendline("Q") # Quit back to system command mode
+ conn.log_expect("SVP>", int(options["--shell-timeout"]))
+ conn.sendline("EX") # Quit back to system console menu
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_blades_list(conn, options):
+ outlets = {}
+
+ conn.sendline("S") # Enter System Command Mode
+ conn.log_expect("SVP>", int(options["--shell-timeout"]))
+ conn.sendline("PC") # Enter partition control
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ # Status can now be obtained from the output of the PC
+ # command. Line looks like the following:
+ # "P Power Condition LID lamp Mode Auto power on"
+ # "0 On Normal Off Basic Synchronized"
+ # "1 On Normal Off Basic Synchronized"
+ for line in conn.before.splitlines():
+ partition = re.search(RE_STATUS_LINE, line)
+ if partition != None:
+ outlets[partition.group(1)] = (partition.group(2), "")
+ conn.sendline("Q") # Quit back to system command mode
+ conn.log_expect("SVP>", int(options["--shell-timeout"]))
+ conn.sendline("EX") # Quit back to system console menu
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ return outlets
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "missing_as_off", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["power_wait"]["default"] = "5"
+ all_opt["cmd_prompt"]["default"] = [r"\) :"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Hitachi Compute Blade systems"
+ docs["longdesc"] = "fence_hds_cb is an I/O Fencing agent \
+which can be used with Hitachi Compute Blades with recent enough firmware that \
+includes telnet support."
+ docs["vendorurl"] = "http://www.hds.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ######
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_blades_list)
+
+ fence_logout(conn, "X")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/heuristics_ping/fence_heuristics_ping.py b/agents/heuristics_ping/fence_heuristics_ping.py
new file mode 100644
index 0000000..5b2c61d
--- /dev/null
+++ b/agents/heuristics_ping/fence_heuristics_ping.py
@@ -0,0 +1,198 @@
+#!@PYTHON@ -tt
+
+# The Following Agent Has Been Tested On:
+#
+# RHEL 7.4
+#
+
+import io
+import re
+import subprocess
+import shlex
+import sys, stat
+import logging
+import os
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import fail_usage, run_command, fence_action, all_opt
+from fencing import atexit_handler, check_input, process_input, show_docs
+from fencing import run_delay
+
+def ping_test(con, options):
+ # Send pings to the targets
+
+ if options["--action"] == "on":
+ # we want unfencing to always succeed
+ return True
+
+ if not "--ping-targets" in options or options["--ping-targets"] == "":
+ # "off" was requested so fake "on" to provoke failure
+ logging.error("ping target required")
+ return False
+
+ timeout = int(options["--ping-timeout"])
+ count = int(options["--ping-count"])
+ interval = int(options["--ping-interval"])
+ good_required = int(options["--ping-good-count"])
+ maxfail = int(options["--ping-maxfail"])
+ targets = options["--ping-targets"].split(",")
+ exitcode = True
+ p = {}
+ failcount = 0
+ # search string for parsing the results of the ping-executable
+ packet_count = re.compile(r".*transmitted, ([0-9]*)( packets)? received.*")
+
+ # start a ping-process per target
+ for target in targets:
+ ping_path = '@PING_CMD@'
+ target_mangled = target
+ if target.startswith('inet6:'):
+ if '@PING6_CMD@' == '':
+ p[target] = None
+ continue
+ ping_path = '@PING6_CMD@'
+ target_mangled = target.split(':',2)[1]
+ elif target.startswith('inet:'):
+ ping_path = '@PING4_CMD@'
+ target_mangled = target.split(':',2)[1]
+
+ ping_cmd = "%s -n -q -W %d -c %d -i %d %s" % (
+ ping_path, timeout, count, interval, target_mangled)
+ logging.info("Running command: %s", ping_cmd)
+ try:
+ p[target] = subprocess.Popen(shlex.split(ping_cmd),
+ stdout=subprocess.PIPE);
+ except OSError:
+ p[target] = None
+
+ # collect the results of the ping-processes
+ for target in targets:
+ good = 0
+ if p[target] != None:
+ p[target].wait()
+ if p[target].returncode == 0:
+ for line in p[target].stdout:
+ searchres = packet_count.search(line.decode())
+ if searchres:
+ good = int(searchres.group(1))
+ break
+ if good >= good_required:
+ logging.info("ping target %s received %d of %d" \
+ % (target, good, count))
+ continue
+ failcount += 1
+ logging.info("ping target %s received %d of %d and thus failed"
+ % (target, good, count))
+ else:
+ failcount += 1
+ logging.error("ping target %s failed on OS level" % target)
+
+ if failcount > maxfail:
+ exitcode = False
+
+ return exitcode
+
+
+def define_new_opts():
+ all_opt["ping_count"] = {
+ "getopt" : ":",
+ "longopt" : "ping-count",
+ "required" : "0",
+ "help" : "--ping-count=[number] Number of ping-probes to send",
+ "shortdesc" : "The number of ping-probes that is being sent per target",
+ "default" : "10",
+ "order" : 1
+ }
+
+ all_opt["ping_good_count"] = {
+ "getopt" : ":",
+ "longopt" : "ping-good-count",
+ "required" : "0",
+ "help" : "--ping-good-count=[number] Number of positive ping-probes required",
+ "shortdesc" : "The number of positive ping-probes required to account a target as available",
+ "default" : "8",
+ "order" : 1
+ }
+
+ all_opt["ping_interval"] = {
+ "getopt" : ":",
+ "longopt" : "ping-interval",
+ "required" : "0",
+ "help" : "--ping-interval=[seconds] Seconds between ping-probes",
+ "shortdesc" : "The interval in seconds between ping-probes",
+ "default" : "1",
+ "order" : 1
+ }
+
+ all_opt["ping_timeout"] = {
+ "getopt" : ":",
+ "longopt" : "ping-timeout",
+ "required" : "0",
+ "help" : "--ping-timeout=[seconds] Timeout for individual ping-probes",
+ "shortdesc" : "The timeout in seconds till an individual ping-probe is accounted as lost",
+ "default" : "2",
+ "order" : 1
+ }
+
+ all_opt["ping_maxfail"] = {
+ "getopt" : ":",
+ "longopt" : "ping-maxfail",
+ "required" : "0",
+ "help" : "--ping-maxfail=[number] Number of failed ping-targets allowed",
+ "shortdesc" : "The number of failed ping-targets to still account as overall success",
+ "default" : "0",
+ "order" : 1
+ }
+
+ all_opt["ping_targets"] = {
+ "getopt" : ":",
+ "longopt" : "ping-targets",
+ "required" : "1",
+ "help" : "--ping-targets=tgt1,[inet6:]tgt2 Comma separated list of ping-targets",
+ "shortdesc" : "A comma separated list of ping-targets (optionally prepended by 'inet:' or 'inet6:') to be probed",
+ "default" : "",
+ "order" : 1
+ }
+
+
+def main():
+ device_opt = ["no_status", "no_password", "ping_count", "ping_good_count",
+ "ping_interval", "ping_timeout", "ping_maxfail", "ping_targets", "method"]
+ define_new_opts()
+ atexit.register(atexit_handler)
+
+ all_opt["method"]["default"] = "cycle"
+ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (cycle|onoff) (Default: cycle)"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for ping-heuristic based fencing"
+ docs["longdesc"] = "fence_heuristics_ping uses ping-heuristics to control execution of another fence agent on the same fencing level.\
+\n.P\n\
+This is not a fence agent by itself! \
+Its only purpose is to enable/disable another fence agent that lives on the same fencing level but after fence_heuristics_ping."
+ docs["vendorurl"] = ""
+ show_docs(options, docs)
+
+ # move ping-test to the end of the time-window set via --delay
+ # as to give the network time to settle after the incident that has
+ # caused fencing and have the results as current as possible
+ max_pingcheck = (int(options["--ping-count"]) - 1) * \
+ int(options["--ping-interval"]) + int(options["--ping-timeout"])
+ run_delay(options, reserve=max_pingcheck)
+
+ result = fence_action(\
+ None, \
+ options, \
+ None, \
+ None, \
+ reboot_cycle_fn = ping_test,
+ sync_set_power_fn = ping_test)
+
+ # execute the remaining delay
+ run_delay(options, result=result)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/hpblade/fence_hpblade.py b/agents/hpblade/fence_hpblade.py
new file mode 100644
index 0000000..fbc89f6
--- /dev/null
+++ b/agents/hpblade/fence_hpblade.py
@@ -0,0 +1,134 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+## * HP BladeSystem c7000 Enclosure
+## * HP Integrity Superdome X (BL920s)
+#####
+
+import sys, re
+import pexpect
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS
+
+def get_enclosure_type(conn, options):
+ conn.send_eol("show enclosure info")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ type_re=re.compile(r"^\s*Enclosure Type: (\w+)(.*?)\s*$")
+ enclosure="unknown"
+ for line in conn.before.splitlines():
+ res = type_re.search(line)
+ if res != None:
+ enclosure=res.group(1)
+
+ if enclosure == "unknown":
+ fail(EC_GENERIC_ERROR)
+
+ return enclosure.lower().strip()
+
+def get_power_status(conn, options):
+ if options["enc_type"] == "superdome":
+ cmd_send = "parstatus -M -p " + options["--plug"]
+ powrestr = "^partition:\\d\\s+:\\w+\\s+/(\\w+)\\s.*$"
+ else:
+ cmd_send = "show server status " + options["--plug"]
+ powrestr = "^\\s*Power: (.*?)\\s*$"
+
+ conn.send_eol(cmd_send)
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ power_re = re.compile(powrestr)
+ status = "unknown"
+ for line in conn.before.splitlines():
+ res = power_re.search(line)
+ if res != None:
+ if options["enc_type"] == "superdome":
+ if res.group(1) == "DOWN":
+ status = "off"
+ else:
+ status = "on"
+ else:
+ status = res.group(1)
+
+ if status == "unknown":
+ if "--missing-as-off" in options:
+ return "off"
+ else:
+ fail(EC_STATUS)
+
+ return status.lower().strip()
+
+def set_power_status(conn, options):
+ if options["enc_type"] == "superdome":
+ dev="partition "
+ else:
+ dev="server "
+
+ if options["--action"] == "on":
+ conn.send_eol("poweron " + dev + options["--plug"])
+ elif options["--action"] == "off":
+ conn.send_eol("poweroff " + dev + options["--plug"] + " force")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_instances_list(conn, options):
+ outlets = {}
+ if options["enc_type"] == "superdome":
+ cmd_send = "parstatus -P -M"
+ listrestr = "^partition:(\\d+)\\s+:\\w+\\s+/(\\w+)\\s+:OK.*?:(\\w+)\\s*$"
+ else:
+ cmd_send = "show server list"
+ listrestr = "^\\s*(\\d+)\\s+(.*?)\\s+(.*?)\\s+OK\\s+(.*?)\\s+(.*?)\\s*$"
+
+ conn.send_eol(cmd_send)
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ list_re = re.compile(listrestr)
+ for line in conn.before.splitlines():
+ res = list_re.search(line)
+ if res != None:
+ if options["enc_type"] == "superdome":
+ outlets[res.group(1)] = (res.group(3), res.group(2).lower())
+ else:
+ outlets[res.group(1)] = (res.group(2), res.group(4).lower())
+
+ return outlets
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", \
+ "port", "missing_as_off", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["c7000oa>"]
+ all_opt["login_timeout"]["default"] = "10"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP BladeSystem"
+ docs["longdesc"] = "fence_hpblade is an I/O Fencing agent \
+which can be used with HP BladeSystem and HP Integrity Superdome X. \
+It logs into the onboard administrator of an enclosure via telnet or \
+ssh and uses the command line interface to power blades or partitions \
+on or off."
+ docs["vendorurl"] = "http://www.hp.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ######
+ options["eol"] = "\n"
+ conn = fence_login(options)
+
+ options["enc_type"] = get_enclosure_type(conn, options)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_instances_list)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ibm_powervs/fence_ibm_powervs.py b/agents/ibm_powervs/fence_ibm_powervs.py
new file mode 100755
index 0000000..1838936
--- /dev/null
+++ b/agents/ibm_powervs/fence_ibm_powervs.py
@@ -0,0 +1,267 @@
+#!@PYTHON@ -tt
+
+import sys
+import pycurl, io, json
+import logging
+import atexit
+import time
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS
+
+state = {
+ "ACTIVE": "on",
+ "SHUTOFF": "off",
+ "ERROR": "unknown"
+}
+
+def get_token(conn, options):
+ try:
+ command = "identity/token"
+ action = "grant_type=urn%3Aibm%3Aparams%3Aoauth%3Agrant-type%3Aapikey&apikey={}".format(options["--token"])
+ res = send_command(conn, command, "POST", action, printResult=False)
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ return "TOKEN_IS_MISSING_OR_WRONG"
+
+ return res["access_token"]
+
+def get_list(conn, options):
+ outlets = {}
+
+ try:
+ command = "cloud-instances/{}/pvm-instances".format(options["--instance"])
+ res = send_command(conn, command)
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ return outlets
+
+ for r in res["pvmInstances"]:
+ if "--verbose" in options:
+ logging.debug(json.dumps(r, indent=2))
+ outlets[r["pvmInstanceID"]] = (r["serverName"], state[r["status"]])
+
+ return outlets
+
+def get_power_status(conn, options):
+ try:
+ command = "cloud-instances/{}/pvm-instances/{}".format(
+ options["--instance"], options["--plug"])
+ res = send_command(conn, command)
+ result = get_list(conn, options)[options["--plug"]][1]
+ except KeyError as e:
+ logging.debug("Failed: Unable to get status for {}".format(e))
+ fail(EC_STATUS)
+
+ return result
+
+def set_power_status(conn, options):
+ action = {
+ "on" : '{"action" : "start"}',
+ "off" : '{"action" : "immediate-shutdown"}',
+ }[options["--action"]]
+
+ try:
+ send_command(conn, "cloud-instances/{}/pvm-instances/{}/action".format(
+ options["--instance"], options["--plug"]), "POST", action)
+ except Exception as e:
+ logging.debug("Failed: Unable to set power to {} for {}".format(options["--action"], e))
+ fail(EC_STATUS)
+
+def connect(opt, token):
+ conn = pycurl.Curl()
+
+ ## setup correct URL
+ conn.base_url = "https://" + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/"
+ if opt["--api-type"] == "private":
+ conn.base_url = "https://private." + opt["--region"] + ".power-iaas.cloud.ibm.com/pcloud/v1/"
+
+ if opt["--verbose-level"] < 3:
+ conn.setopt(pycurl.VERBOSE, 0)
+
+ conn.setopt(pycurl.CONNECTTIMEOUT,int(opt["--shell-timeout"]))
+ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ conn.setopt(pycurl.PROXY, "{}".format(opt["--proxy"]))
+
+ # set auth token for later requests
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Content-Type: application/json",
+ "Authorization: Bearer {}".format(token),
+ "CRN: {}".format(opt["--crn"]),
+ "User-Agent: curl",
+ ])
+
+ return conn
+
+def auth_connect(opt):
+ conn = pycurl.Curl()
+
+ # setup correct URL
+ conn.base_url = "https://iam.cloud.ibm.com/"
+
+ if opt["--verbose-level"] > 1:
+ conn.setopt(pycurl.VERBOSE, 1)
+
+ conn.setopt(pycurl.CONNECTTIMEOUT,int(opt["--shell-timeout"]))
+ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ conn.setopt(pycurl.PROXY, "{}".format(opt["--proxy"]))
+
+ # set auth token for later requests
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Content-type: application/x-www-form-urlencoded",
+ "Accept: application/json",
+ "User-Agent: curl",
+ ])
+
+ return conn
+
+def disconnect(conn):
+ conn.close()
+
+def send_command(conn, command, method="GET", action=None, printResult=True):
+ url = conn.base_url + command
+
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+
+ web_buffer = io.BytesIO()
+
+ if method == "GET":
+ conn.setopt(pycurl.POST, 0)
+ if method == "POST":
+ conn.setopt(pycurl.POSTFIELDS, action)
+ if method == "DELETE":
+ conn.setopt(pycurl.CUSTOMREQUEST, "DELETE")
+
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+
+ try:
+ conn.perform()
+ except Exception as e:
+ logging.error("send_command(): {}".format(e))
+ raise(e)
+
+ rc = conn.getinfo(pycurl.HTTP_CODE)
+ result = web_buffer.getvalue().decode("UTF-8")
+
+ web_buffer.close()
+
+ if rc != 200:
+ if len(result) > 0:
+ raise Exception("{}: {}".format(rc,result))
+ else:
+ raise Exception("Remote returned {} for request to {}".format(rc, url))
+
+ if len(result) > 0:
+ result = json.loads(result)
+
+ logging.debug("url: {}".format(url))
+ logging.debug("method: {}".format(method))
+ logging.debug("response code: {}".format(rc))
+ if printResult:
+ logging.debug("result: {}\n".format(result))
+
+ return result
+
+def define_new_opts():
+ all_opt["token"] = {
+ "getopt" : ":",
+ "longopt" : "token",
+ "help" : "--token=[token] API Token",
+ "required" : "1",
+ "shortdesc" : "API Token",
+ "order" : 0
+ }
+ all_opt["crn"] = {
+ "getopt" : ":",
+ "longopt" : "crn",
+ "help" : "--crn=[crn] CRN",
+ "required" : "1",
+ "shortdesc" : "CRN",
+ "order" : 0
+ }
+ all_opt["instance"] = {
+ "getopt" : ":",
+ "longopt" : "instance",
+ "help" : "--instance=[instance] PowerVS Instance",
+ "required" : "1",
+ "shortdesc" : "PowerVS Instance",
+ "order" : 0
+ }
+ all_opt["region"] = {
+ "getopt" : ":",
+ "longopt" : "region",
+ "help" : "--region=[region] Region",
+ "required" : "1",
+ "shortdesc" : "Region",
+ "order" : 0
+ }
+ all_opt["api-type"] = {
+ "getopt" : ":",
+ "longopt" : "api-type",
+ "help" : "--api-type=[public|private] API-type: 'public' (default) or 'private'",
+ "required" : "0",
+ "shortdesc" : "API-type (public|private)",
+ "order" : 0
+ }
+ all_opt["proxy"] = {
+ "getopt" : ":",
+ "longopt" : "proxy",
+ "help" : "--proxy=[http://<URL>:<PORT>] Proxy: 'http://<URL>:<PORT>'",
+ "required" : "0",
+ "shortdesc" : "Network proxy",
+ "order" : 0
+ }
+
+
+def main():
+ device_opt = [
+ "token",
+ "crn",
+ "instance",
+ "region",
+ "api-type",
+ "proxy",
+ "port",
+ "no_password",
+ ]
+
+ atexit.register(atexit_handler)
+ define_new_opts()
+
+ all_opt["shell_timeout"]["default"] = "500"
+ all_opt["power_timeout"]["default"] = "30"
+ all_opt["power_wait"]["default"] = "1"
+ all_opt["stonith_status_sleep"]["default"] = "2"
+ all_opt["api-type"]["default"] = "private"
+ all_opt["proxy"]["default"] = ""
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM PowerVS"
+ docs["longdesc"] = """fence_ibm_powervs is an I/O Fencing agent which can be \
+used with IBM PowerVS to fence virtual machines."""
+ docs["vendorurl"] = "https://www.ibm.com"
+ show_docs(options, docs)
+
+ ####
+ ## Fence operations
+ ####
+ run_delay(options)
+
+ auth_conn = auth_connect(options)
+ token = get_token(auth_conn, options)
+ disconnect(auth_conn)
+ conn = connect(options, token)
+ atexit.register(disconnect, conn)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_list)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ibm_vpc/fence_ibm_vpc.py b/agents/ibm_vpc/fence_ibm_vpc.py
new file mode 100755
index 0000000..8470105
--- /dev/null
+++ b/agents/ibm_vpc/fence_ibm_vpc.py
@@ -0,0 +1,316 @@
+#!@PYTHON@ -tt
+
+import sys
+import pycurl, io, json
+import logging
+import atexit
+import hashlib
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS, EC_GENERIC_ERROR
+
+state = {
+ "running": "on",
+ "stopped": "off",
+ "starting": "unknown",
+ "stopping": "unknown",
+ "restarting": "unknown",
+ "pending": "unknown",
+}
+
+def get_list(conn, options):
+ outlets = {}
+
+ try:
+ command = "instances?version=2021-05-25&generation=2&limit={}".format(options["--limit"])
+ res = send_command(conn, options, command)
+ except Exception as e:
+ logging.debug("Failed: Unable to get list: {}".format(e))
+ return outlets
+
+ for r in res["instances"]:
+ if options["--verbose-level"] > 1:
+ logging.debug("Node:\n{}".format(json.dumps(r, indent=2)))
+ logging.debug("Status: " + state[r["status"]])
+ outlets[r["id"]] = (r["name"], state[r["status"]])
+
+ return outlets
+
+def get_power_status(conn, options):
+ try:
+ command = "instances/{}?version=2021-05-25&generation=2".format(options["--plug"])
+ res = send_command(conn, options, command)
+ result = state[res["status"]]
+ if options["--verbose-level"] > 1:
+ logging.debug("Result:\n{}".format(json.dumps(res, indent=2)))
+ logging.debug("Status: " + result)
+ except Exception as e:
+ logging.debug("Failed: Unable to get status for {}: {}".format(options["--plug"], e))
+ fail(EC_STATUS)
+
+ return result
+
+def set_power_status(conn, options):
+ action = {
+ "on" : '{"type" : "start"}',
+ "off" : '{"type" : "stop"}',
+ }[options["--action"]]
+
+ try:
+ command = "instances/{}/actions?version=2021-05-25&generation=2".format(options["--plug"])
+ send_command(conn, options, command, "POST", action, 201)
+ except Exception as e:
+ logging.debug("Failed: Unable to set power to {} for {}".format(options["--action"], e))
+ fail(EC_STATUS)
+
+def get_bearer_token(conn, options):
+ import os, errno
+
+ try:
+ # FIPS requires usedforsecurity=False and might not be
+ # available on all distros: https://bugs.python.org/issue9216
+ hash = hashlib.sha256(options["--apikey"].encode("utf-8"), usedforsecurity=False).hexdigest()
+ except (AttributeError, TypeError):
+ hash = hashlib.sha256(options["--apikey"].encode("utf-8")).hexdigest()
+ file_path = options["--token-file"].replace("[hash]", hash)
+ token = None
+
+ if not os.path.isdir(os.path.dirname(file_path)):
+ os.makedirs(os.path.dirname(file_path))
+
+ # For security, remove file with potentially elevated mode
+ try:
+ os.remove(file_path)
+ except OSError:
+ pass
+
+ try:
+ oldumask = os.umask(0)
+ file_handle = os.open(file_path, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o600)
+ except OSError as e:
+ if e.errno == errno.EEXIST: # Failed as the file already exists.
+ logging.error("Failed: File already exists: {}".format(e))
+ sys.exit(EC_GENERIC_ERROR)
+ else: # Something unexpected went wrong
+ logging.error("Failed: Unable to open file: {}".format(e))
+ sys.exit(EC_GENERIC_ERROR)
+ else: # No exception, so the file must have been created successfully.
+ with os.fdopen(file_handle, 'w') as file_obj:
+ try:
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Content-Type: application/x-www-form-urlencoded",
+ "User-Agent: curl",
+ ])
+ token = send_command(conn, options, "https://iam.cloud.ibm.com/identity/token", "POST", "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey={}".format(options["--apikey"]))["access_token"]
+ except Exception as e:
+ logging.error("Failed: Unable to authenticate: {}".format(e))
+ fail(EC_LOGIN_DENIED)
+ file_obj.write(token)
+ finally:
+ os.umask(oldumask)
+
+ return token
+
+def set_bearer_token(conn, bearer_token):
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Content-Type: application/json",
+ "Authorization: Bearer {}".format(bearer_token),
+ "User-Agent: curl",
+ ])
+
+ return conn
+
+def connect(opt):
+ conn = pycurl.Curl()
+ bearer_token = ""
+
+ ## setup correct URL
+ conn.base_url = "https://" + opt["--region"] + ".iaas.cloud.ibm.com/v1/"
+
+ if opt["--verbose-level"] > 1:
+ conn.setopt(pycurl.VERBOSE, 1)
+
+ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ conn.setopt(pycurl.PROXY, "{}".format(opt["--proxy"]))
+
+ # get bearer token
+ try:
+ try:
+ # FIPS requires usedforsecurity=False and might not be
+ # available on all distros: https://bugs.python.org/issue9216
+ hash = hashlib.sha256(opt["--apikey"].encode("utf-8"), usedforsecurity=False).hexdigest()
+ except (AttributeError, TypeError):
+ hash = hashlib.sha256(opt["--apikey"].encode("utf-8")).hexdigest()
+ f = open(opt["--token-file"].replace("[hash]", hash))
+ bearer_token = f.read()
+ f.close()
+ except IOError:
+ bearer_token = get_bearer_token(conn, opt)
+
+ # set auth token for later requests
+ conn = set_bearer_token(conn, bearer_token)
+
+ return conn
+
+def disconnect(conn):
+ conn.close()
+
+def send_command(conn, options, command, method="GET", action=None, expected_rc=200):
+ if not command.startswith("https"):
+ url = conn.base_url + command
+ else:
+ url = command
+
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+
+ web_buffer = io.BytesIO()
+
+ if method == "GET":
+ conn.setopt(pycurl.POST, 0)
+ if method == "POST":
+ conn.setopt(pycurl.POSTFIELDS, action)
+ if method == "DELETE":
+ conn.setopt(pycurl.CUSTOMREQUEST, "DELETE")
+
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+
+ try:
+ conn.perform()
+ except Exception as e:
+ raise(e)
+
+ rc = conn.getinfo(pycurl.HTTP_CODE)
+
+ # auth if token has expired
+ if rc in [400, 401, 415]:
+ tokenconn = pycurl.Curl()
+ token = get_bearer_token(tokenconn, options)
+ tokenconn.close()
+ conn = set_bearer_token(conn, token)
+
+ # flush web_buffer
+ web_buffer.close()
+ web_buffer = io.BytesIO()
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+
+ try:
+ conn.perform()
+ except Exception as e:
+ raise(e)
+
+ rc = conn.getinfo(pycurl.HTTP_CODE)
+
+ result = web_buffer.getvalue().decode("UTF-8")
+
+ web_buffer.close()
+
+ # actions (start/stop/reboot) report 201 when they've been created
+ if rc != expected_rc:
+ logging.debug("rc: {}, result: {}".format(rc, result))
+ if len(result) > 0:
+ raise Exception("{}: {}".format(rc,
+ result["value"]["messages"][0]["default_message"]))
+ else:
+ raise Exception("Remote returned {} for request to {}".format(rc, url))
+
+ if len(result) > 0:
+ result = json.loads(result)
+
+ logging.debug("url: {}".format(url))
+ logging.debug("method: {}".format(method))
+ logging.debug("response code: {}".format(rc))
+ logging.debug("result: {}\n".format(result))
+
+ return result
+
+def define_new_opts():
+ all_opt["apikey"] = {
+ "getopt" : ":",
+ "longopt" : "apikey",
+ "help" : "--apikey=[key] API Key",
+ "required" : "1",
+ "shortdesc" : "API Key",
+ "order" : 0
+ }
+ all_opt["region"] = {
+ "getopt" : ":",
+ "longopt" : "region",
+ "help" : "--region=[region] Region",
+ "required" : "1",
+ "shortdesc" : "Region",
+ "order" : 0
+ }
+ all_opt["proxy"] = {
+ "getopt" : ":",
+ "longopt" : "proxy",
+ "help" : "--proxy=[http://<URL>:<PORT>] Proxy: 'http://<URL>:<PORT>'",
+ "required" : "0",
+ "default": "",
+ "shortdesc" : "Network proxy",
+ "order" : 0
+ }
+ all_opt["limit"] = {
+ "getopt" : ":",
+ "longopt" : "limit",
+ "help" : "--limit=[number] Limit number of nodes returned by API",
+ "required" : "0",
+ "default": 50,
+ "shortdesc" : "Number of nodes returned by API",
+ "order" : 0
+ }
+ all_opt["token_file"] = {
+ "getopt" : ":",
+ "longopt" : "token-file",
+ "help" : "--token-file=[path] Path to the token cache file\n"
+ "\t\t\t\t (Default: @FENCETMPDIR@/fence_ibm_vpc/[hash].token)\n"
+ "\t\t\t\t [hash] will be replaced by a hashed value",
+ "required" : "0",
+ "default": "@FENCETMPDIR@/fence_ibm_vpc/[hash].token",
+ "shortdesc" : "Path to the token cache file",
+ "order" : 0
+ }
+
+
+def main():
+ device_opt = [
+ "apikey",
+ "region",
+ "proxy",
+ "limit",
+ "token_file",
+ "port",
+ "no_password",
+ ]
+
+ atexit.register(atexit_handler)
+ define_new_opts()
+
+ all_opt["shell_timeout"]["default"] = "15"
+ all_opt["power_timeout"]["default"] = "30"
+ all_opt["power_wait"]["default"] = "1"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM Cloud VPC"
+ docs["longdesc"] = """fence_ibm_vpc is an I/O Fencing agent which can be \
+used with IBM Cloud VPC to fence virtual machines."""
+ docs["vendorurl"] = "https://www.ibm.com"
+ show_docs(options, docs)
+
+ ####
+ ## Fence operations
+ ####
+ run_delay(options)
+
+ conn = connect(options)
+ atexit.register(disconnect, conn)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_list)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ibmblade/fence_ibmblade.py b/agents/ibmblade/fence_ibmblade.py
new file mode 100644
index 0000000..d623fff
--- /dev/null
+++ b/agents/ibmblade/fence_ibmblade.py
@@ -0,0 +1,72 @@
+#!@PYTHON@ -tt
+
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# From fence_ibmblade.pl
+STATUSES_OID = ".1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.4" # remoteControlBladePowerState
+CONTROL_OID = ".1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.7" # powerOnOffBlade
+
+# Status constants returned as value from SNMP
+STATUS_DOWN = 0
+STATUS_UP = 1
+
+# Status constants to set as value to SNMP
+STATUS_SET_OFF = 0
+STATUS_SET_ON = 1
+
+### FUNCTIONS ###
+
+def get_power_status(conn, options):
+ (_, status) = conn.get("%s.%s"% (STATUSES_OID, options["--plug"]))
+ return status == str(STATUS_UP) and "on" or "off"
+
+def set_power_status(conn, options):
+ conn.set("%s.%s" % (CONTROL_OID, options["--plug"]),
+ (options["--action"] == "on" and STATUS_SET_ON or STATUS_SET_OFF))
+
+def get_outlets_status(conn, _):
+ result = {}
+
+ res_blades = conn.walk(STATUSES_OID, 30)
+
+ for blade_info in res_blades:
+ port_num = blade_info[0].split('.')[-1]
+
+ port_alias = ""
+ port_status = (blade_info[1] == str(STATUS_UP) and "on" or "off")
+
+ result[port_num] = (port_alias, port_status)
+
+ return result
+
+# Main agent method
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["snmp_version"]["default"] = "1"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM BladeCenter over SNMP"
+ docs["longdesc"] = "fence_ibmblade is an I/O Fencing agent \
+which can be used with IBM BladeCenter chassis. It issues SNMP Set \
+request to BladeCenter chassis, rebooting, powering up or down \
+the specified Blade Server."
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+if __name__ == "__main__":
+ main()
diff --git a/agents/ibmz/fence_ibmz.py b/agents/ibmz/fence_ibmz.py
new file mode 100644
index 0000000..d477ade
--- /dev/null
+++ b/agents/ibmz/fence_ibmz.py
@@ -0,0 +1,566 @@
+#!@PYTHON@ -tt
+
+# Copyright (c) 2020 IBM Corp.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+import atexit
+import logging
+import time
+import sys
+
+import requests
+from requests.packages import urllib3
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, run_delay, EC_GENERIC_ERROR
+
+DEFAULT_POWER_TIMEOUT = '300'
+ERROR_NOT_FOUND = ("{obj_type} {obj_name} not found in this HMC. "
+ "Attention: names are case-sensitive.")
+
+class ApiClientError(Exception):
+ """
+ Base exception for all API Client related errors.
+ """
+
+class ApiClientRequestError(ApiClientError):
+ """
+ Raised when an API request ends in error
+ """
+
+ def __init__(self, req_method, req_uri, status, reason, message):
+ self.req_method = req_method
+ self.req_uri = req_uri
+ self.status = status
+ self.reason = reason
+ self.message = message
+ super(ApiClientRequestError, self).__init__()
+
+ def __str__(self):
+ return (
+ "API request failed, details:\n"
+ "HTTP Request : {req_method} {req_uri}\n"
+ "HTTP Response status: {status}\n"
+ "Error reason: {reason}\n"
+ "Error message: {message}\n".format(
+ req_method=self.req_method, req_uri=self.req_uri,
+ status=self.status, reason=self.reason, message=self.message)
+ )
+
+class APIClient(object):
+ DEFAULT_CONFIG = {
+ # how many connection-related errors to retry on
+ 'connect_retries': 3,
+ # how many times to retry on read errors (after request was sent to the
+ # server)
+ 'read_retries': 3,
+ # http methods that should be retried
+ 'method_whitelist': ['HEAD', 'GET', 'OPTIONS'],
+ # limit of redirects to perform to avoid loops
+ 'redirect': 5,
+ # how long to wait while establishing a connection
+ 'connect_timeout': 30,
+ # how long to wait for asynchronous operations (jobs) to complete
+ 'operation_timeout': 900,
+ # how long to wait between bytes sent by the remote side
+ 'read_timeout': 300,
+ # default API port
+ 'port': 6794,
+ # validate ssl certificates
+ 'ssl_verify': False,
+ # load on activate is set in the HMC activation profile and therefore
+ # no additional load is executed by the fence agent
+ 'load_on_activate': False
+ }
+ LABEL_BY_OP_MODE = {
+ 'classic': {
+ 'nodes': 'logical-partitions',
+ 'state-on': 'operating',
+ 'start': 'load',
+ 'stop': 'deactivate'
+ },
+ 'dpm': {
+ 'nodes': 'partitions',
+ 'state-on': 'active',
+ 'start': 'start',
+ 'stop': 'stop'
+ }
+ }
+ def __init__(self, host, user, passwd, config=None):
+ self.host = host
+ if not passwd:
+ raise ValueError('Password cannot be empty')
+ self.passwd = passwd
+ if not user:
+ raise ValueError('Username cannot be empty')
+ self.user = user
+ self._cpc_cache = {}
+ self._session = None
+ self._config = self.DEFAULT_CONFIG.copy()
+ # apply user defined values
+ if config:
+ self._config.update(config)
+
+ def _create_session(self):
+ """
+ Create a new requests session and apply config values
+ """
+ session = requests.Session()
+ retry_obj = urllib3.Retry(
+ # setting a total is necessary to cover SSL related errors
+ total=max(self._config['connect_retries'],
+ self._config['read_retries']),
+ connect=self._config['connect_retries'],
+ read=self._config['read_retries'],
+ method_whitelist=self._config['method_whitelist'],
+ redirect=self._config['redirect']
+ )
+ session.mount('http://', requests.adapters.HTTPAdapter(
+ max_retries=retry_obj))
+ session.mount('https://', requests.adapters.HTTPAdapter(
+ max_retries=retry_obj))
+ return session
+
+ def _get_mode_labels(self, cpc):
+ """
+ Return the map of labels that corresponds to the cpc operation mode
+ """
+ if self.is_dpm_enabled(cpc):
+ return self.LABEL_BY_OP_MODE['dpm']
+ return self.LABEL_BY_OP_MODE['classic']
+
+ def _get_partition(self, cpc, partition):
+ """
+ Return the properties of the specified partition. Raises ValueError if
+ it cannot be found.
+ """
+ # HMC API's documentation says it'll return an empty array when no
+ # matches are found but for a CPC in classic mode it returns in fact
+ # 404, so we handle this accordingly. Remove the extra handling below
+ # once this behavior has been fixed on the API's side.
+ label_map = self._get_mode_labels(cpc)
+ resp = self._request('get', '{}/{}?name={}'.format(
+ self._cpc_cache[cpc]['object-uri'], label_map['nodes'], partition),
+ valid_codes=[200, 404])
+
+ if label_map['nodes'] not in resp or not resp[label_map['nodes']]:
+ raise ValueError(ERROR_NOT_FOUND.format(
+ obj_type='LPAR/Partition', obj_name=partition))
+ return resp[label_map['nodes']][0]
+
+ def _partition_switch_power(self, cpc, partition, action):
+ """
+ Perform the API request to start (power on) or stop (power off) the
+ target partition and wait for the job to finish.
+ """
+ # retrieve partition's uri
+ part_uri = self._get_partition(cpc, partition)['object-uri']
+ label_map = self._get_mode_labels(cpc)
+
+ # in dpm mode the request must have empty body
+ if self.is_dpm_enabled(cpc):
+ body = None
+ # in classic mode we make sure the operation is executed
+ # even if the partition is already on
+ else:
+ body = {'force': True}
+ # when powering on the partition must be activated first
+ if action == 'start':
+ op_uri = '{}/operations/activate'.format(part_uri)
+ job_resp = self._request(
+ 'post', op_uri, body=body, valid_codes=[202])
+ # always wait for activate otherwise the load (start)
+ # operation will fail
+ if self._config['operation_timeout'] == 0:
+ timeout = self.DEFAULT_CONFIG['operation_timeout']
+ else:
+ timeout = self._config['operation_timeout']
+ logging.debug(
+ 'waiting for activate (timeout %s secs)', timeout)
+ self._wait_for_job('post', op_uri, job_resp['job-uri'],
+ timeout=timeout)
+ if self._config['load_on_activate']:
+ return
+
+ # trigger the start job
+ op_uri = '{}/operations/{}'.format(part_uri, label_map[action])
+ job_resp = self._request('post', op_uri, body=body, valid_codes=[202])
+ if self._config['operation_timeout'] == 0:
+ return
+ logging.debug('waiting for %s (timeout %s secs)',
+ label_map[action], self._config['operation_timeout'])
+ self._wait_for_job('post', op_uri, job_resp['job-uri'],
+ timeout=self._config['operation_timeout'])
+
+ def _request(self, method, uri, body=None, headers=None, valid_codes=None):
+ """
+ Perform a request to the HMC API
+ """
+ assert method in ('delete', 'head', 'get', 'post', 'put')
+
+ url = 'https://{host}:{port}{uri}'.format(
+ host=self.host, port=self._config['port'], uri=uri)
+ if not headers:
+ headers = {}
+
+ if self._session is None:
+ raise ValueError('You need to log on first')
+ method = getattr(self._session, method)
+ timeout = (
+ self._config['connect_timeout'], self._config['read_timeout'])
+ response = method(url, json=body, headers=headers,
+ verify=self._config['ssl_verify'], timeout=timeout)
+
+ if valid_codes and response.status_code not in valid_codes:
+ reason = '(no reason)'
+ message = '(no message)'
+ if response.headers.get('content-type') == 'application/json':
+ try:
+ json_resp = response.json()
+ except ValueError:
+ pass
+ else:
+ reason = json_resp.get('reason', reason)
+ message = json_resp.get('message', message)
+ else:
+ message = '{}...'.format(response.text[:500])
+ raise ApiClientRequestError(
+ response.request.method, response.request.url,
+ response.status_code, reason, message)
+
+ if response.status_code == 204:
+ return dict()
+ try:
+ json_resp = response.json()
+ except ValueError:
+ raise ApiClientRequestError(
+ response.request.method, response.request.url,
+ response.status_code, '(no reason)',
+ 'Invalid JSON content in response')
+
+ return json_resp
+
+ def _update_cpc_cache(self, cpc_props):
+ self._cpc_cache[cpc_props['name']] = {
+ 'object-uri': cpc_props['object-uri'],
+ 'dpm-enabled': cpc_props.get('dpm-enabled', False)
+ }
+
+ def _wait_for_job(self, req_method, req_uri, job_uri, timeout):
+ """
+ Perform API requests to check for job status until it has completed
+ or the specified timeout is reached
+ """
+ op_timeout = time.time() + timeout
+ while time.time() < op_timeout:
+ job_resp = self._request("get", job_uri)
+ if job_resp['status'] == 'complete':
+ if job_resp['job-status-code'] in (200, 201, 204):
+ return
+ raise ApiClientRequestError(
+ req_method, req_uri,
+ job_resp.get('job-status-code', '(no status)'),
+ job_resp.get('job-reason-code', '(no reason)'),
+ job_resp.get('job-results', {}).get(
+ 'message', '(no message)')
+ )
+ time.sleep(1)
+ raise ApiClientError('Timed out while waiting for job completion')
+
+ def cpc_list(self):
+ """
+ Return a list of CPCs in the format {'name': 'cpc-name', 'status':
+ 'operating'}
+ """
+ list_resp = self._request("get", "/api/cpcs", valid_codes=[200])
+ ret = []
+ for cpc_props in list_resp['cpcs']:
+ self._update_cpc_cache(cpc_props)
+ ret.append({
+ 'name': cpc_props['name'], 'status': cpc_props['status']})
+ return ret
+
+ def is_dpm_enabled(self, cpc):
+ """
+ Return True if CPC is in DPM mode, False for classic mode
+ """
+ if cpc in self._cpc_cache:
+ return self._cpc_cache[cpc]['dpm-enabled']
+ list_resp = self._request("get", "/api/cpcs?name={}".format(cpc),
+ valid_codes=[200])
+ if not list_resp['cpcs']:
+ raise ValueError(ERROR_NOT_FOUND.format(
+ obj_type='CPC', obj_name=cpc))
+ self._update_cpc_cache(list_resp['cpcs'][0])
+ return self._cpc_cache[cpc]['dpm-enabled']
+
+ def logon(self):
+ """
+ Open a session with the HMC API and store its ID
+ """
+ self._session = self._create_session()
+ logon_body = {"userid": self.user, "password": self.passwd}
+ logon_resp = self._request("post", "/api/sessions", body=logon_body,
+ valid_codes=[200, 201])
+ self._session.headers["X-API-Session"] = logon_resp['api-session']
+
+ def logoff(self):
+ """
+ Close/delete the HMC API session
+ """
+ if self._session is None:
+ return
+ self._request("delete", "/api/sessions/this-session",
+ valid_codes=[204])
+ self._cpc_cache = {}
+ self._session = None
+
+ def partition_list(self, cpc):
+ """
+ Return a list of partitions in the format {'name': 'part-name',
+ 'status': 'on'}
+ """
+ label_map = self._get_mode_labels(cpc)
+ list_resp = self._request(
+ 'get', '{}/{}'.format(
+ self._cpc_cache[cpc]['object-uri'], label_map['nodes']),
+ valid_codes=[200])
+ status_map = {label_map['state-on']: 'on'}
+ return [{'name': part['name'],
+ 'status': status_map.get(part['status'].lower(), 'off')}
+ for part in list_resp[label_map['nodes']]]
+
+ def partition_start(self, cpc, partition):
+ """
+ Power on a partition
+ """
+ self._partition_switch_power(cpc, partition, 'start')
+
+ def partition_status(self, cpc, partition):
+ """
+ Return the current status of a partition (on or off)
+ """
+ label_map = self._get_mode_labels(cpc)
+
+ part_props = self._get_partition(cpc, partition)
+ if part_props['status'].lower() == label_map['state-on']:
+ return 'on'
+ return 'off'
+
+ def partition_stop(self, cpc, partition):
+ """
+ Power off a partition
+ """
+ self._partition_switch_power(cpc, partition, 'stop')
+
+def parse_plug(options):
+ """
+ Extract cpc and partition from specified plug value
+ """
+ try:
+ cpc, partition = options['--plug'].strip().split('/', 1)
+ except ValueError:
+ fail_usage('Please specify nodename in format cpc/partition')
+ cpc = cpc.strip()
+ if not cpc or not partition:
+ fail_usage('Please specify nodename in format cpc/partition')
+ return cpc, partition
+
+def get_power_status(conn, options):
+ logging.debug('executing get_power_status')
+ status = conn.partition_status(*parse_plug(options))
+ return status
+
+def set_power_status(conn, options):
+ logging.debug('executing set_power_status')
+ if options['--action'] == 'on':
+ conn.partition_start(*parse_plug(options))
+ elif options['--action'] == 'off':
+ conn.partition_stop(*parse_plug(options))
+ else:
+ fail_usage('Invalid action {}'.format(options['--action']))
+
+def get_outlet_list(conn, options):
+ logging.debug('executing get_outlet_list')
+ result = {}
+ for cpc in conn.cpc_list():
+ for part in conn.partition_list(cpc['name']):
+ result['{}/{}'.format(cpc['name'], part['name'])] = (
+ part['name'], part['status'])
+ return result
+
+def disconnect(conn):
+ """
+ Close the API session
+ """
+ try:
+ conn.logoff()
+ except Exception as exc:
+ logging.exception('Logoff failed: ')
+ sys.exit(str(exc))
+
+def set_opts():
+ """
+ Define the options supported by this agent
+ """
+ device_opt = [
+ "ipaddr",
+ "ipport",
+ "login",
+ "passwd",
+ "port",
+ "connect_retries",
+ "connect_timeout",
+ "operation_timeout",
+ "read_retries",
+ "read_timeout",
+ "ssl_secure",
+ "load_on_activate",
+ ]
+
+ all_opt["ipport"]["default"] = APIClient.DEFAULT_CONFIG['port']
+ all_opt["power_timeout"]["default"] = DEFAULT_POWER_TIMEOUT
+ port_desc = ("Physical plug id in the format cpc-name/partition-name "
+ "(case-sensitive)")
+ all_opt["port"]["shortdesc"] = port_desc
+ all_opt["port"]["help"] = (
+ "-n, --plug=[id] {}".format(port_desc))
+ all_opt["connect_retries"] = {
+ "getopt" : ":",
+ "longopt" : "connect-retries",
+ "help" : "--connect-retries=[number] How many times to "
+ "retry on connection errors",
+ "default" : APIClient.DEFAULT_CONFIG['connect_retries'],
+ "type" : "integer",
+ "required" : "0",
+ "shortdesc" : "How many times to retry on connection errors",
+ "order" : 2
+ }
+ all_opt["read_retries"] = {
+ "getopt" : ":",
+ "longopt" : "read-retries",
+ "help" : "--read-retries=[number] How many times to "
+ "retry on errors related to reading from server",
+ "default" : APIClient.DEFAULT_CONFIG['read_retries'],
+ "type" : "integer",
+ "required" : "0",
+ "shortdesc" : "How many times to retry on read errors",
+ "order" : 2
+ }
+ all_opt["connect_timeout"] = {
+ "getopt" : ":",
+ "longopt" : "connect-timeout",
+ "help" : "--connect-timeout=[seconds] How long to wait to "
+ "establish a connection",
+ "default" : APIClient.DEFAULT_CONFIG['connect_timeout'],
+ "type" : "second",
+ "required" : "0",
+ "shortdesc" : "How long to wait to establish a connection",
+ "order" : 2
+ }
+ all_opt["operation_timeout"] = {
+ "getopt" : ":",
+ "longopt" : "operation-timeout",
+ "help" : "--operation-timeout=[seconds] How long to wait for "
+ "power operation to complete (0 = do not wait)",
+ "default" : APIClient.DEFAULT_CONFIG['operation_timeout'],
+ "type" : "second",
+ "required" : "0",
+ "shortdesc" : "How long to wait for power operation to complete",
+ "order" : 2
+ }
+ all_opt["read_timeout"] = {
+ "getopt" : ":",
+ "longopt" : "read-timeout",
+ "help" : "--read-timeout=[seconds] How long to wait "
+ "to read data from server",
+ "default" : APIClient.DEFAULT_CONFIG['read_timeout'],
+ "type" : "second",
+ "required" : "0",
+ "shortdesc" : "How long to wait for server data",
+ "order" : 2
+ }
+ all_opt["load_on_activate"] = {
+ "getopt" : "",
+ "longopt" : "load-on-activate",
+ "help" : "--load-on-activate Rely on the HMC to perform "
+ "a load operation on activation",
+ "required" : "0",
+ "order" : 3
+ }
+ return device_opt
+
+def main():
+ """
+ Agent entry point
+ """
+ # register exit handler used by pacemaker
+ atexit.register(atexit_handler)
+
+ # prepare accepted options
+ device_opt = set_opts()
+
+ # parse options provided on input
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {
+ "shortdesc": "Fence agent for IBM z LPARs",
+ "longdesc": (
+ "fence_ibmz is a power fencing agent which uses the HMC Web "
+ "Services API to fence IBM z LPARs."),
+ "vendorurl": "http://www.ibm.com"
+ }
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # set underlying library's logging and ssl config according to specified
+ # options
+ requests_log = logging.getLogger("urllib3")
+ requests_log.propagate = True
+ if "--verbose" in options:
+ requests_log.setLevel(logging.DEBUG)
+ if "--ssl-insecure" in options:
+ urllib3.disable_warnings(
+ category=urllib3.exceptions.InsecureRequestWarning)
+
+ hmc_address = options["--ip"]
+ hmc_userid = options["--username"]
+ hmc_password = options["--password"]
+ config = {
+ 'connect_retries': int(options['--connect-retries']),
+ 'read_retries': int(options['--read-retries']),
+ 'operation_timeout': int(options['--operation-timeout']),
+ 'connect_timeout': int(options['--connect-timeout']),
+ 'read_timeout': int(options['--read-timeout']),
+ 'port': int(options['--ipport']),
+ 'ssl_verify': bool('--ssl-insecure' not in options),
+ 'load_on_activate': bool('--load-on-activate' in options),
+ }
+ try:
+ conn = APIClient(hmc_address, hmc_userid, hmc_password, config)
+ conn.logon()
+ atexit.register(disconnect, conn)
+ result = fence_action(conn, options, set_power_status,
+ get_power_status, get_outlet_list)
+ except Exception:
+ logging.exception('Exception occurred: ')
+ result = EC_GENERIC_ERROR
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ifmib/README b/agents/ifmib/README
new file mode 100644
index 0000000..6fe8a2b
--- /dev/null
+++ b/agents/ifmib/README
@@ -0,0 +1,45 @@
+Intro:
+------
+This is an SNMP-based fencing agent for RHCS. It was designed with the use-case
+of disabling ethernet ports on an iSCSI SAN, but could be used to disable any
+port on any SNMP v1/2c/3 device that implementes the IF-MIB.
+
+The script requires NetSNMP to be installed and working on all nodes
+in the cluster. There are no requirements for any MIBs to be setup --- all of
+the required OIDs are hard-coded into the script. Since the IF-MIB is an IETF
+standard, these identifiers are very widely supported and will not change.
+
+
+Typical usage:
+--------------
+To use this agent with the switch used on the iSCSI network, you'll need:
+ 1) A managed switch running SNMP.
+ 2) An SNMP community with write privileges.
+ 3) Permission to send SNMP through any ACLs or firewalls from the nodes.
+ 4) The ifIndex or ifPort associated with the ports being used by the cluster nodes.
+
+Consider a three-node cluster composed of A, B, and C. Each node has two
+network interfaces - one used for network and cluster communication, the second
+used for iSCSI traffic. If A needs to be fenced, B and C will run this script
+to administratively disable the switchport for A's connection to the iSCSI
+storage.
+
+If you are using a single interface for cluster and iSCSI traffic, this will
+still work, but you will lose network connectivity to the fenced host.
+
+
+cluster.conf:
+-------------
+There is no GUI support for this fence agent at this time. To use it, you will
+need something like this cluster.conf
+
+<fencedevice agent="fence_ifmib" name="myswitch" comm="fencing" ipaddr="sw1"/>
+
+In a node's fencing methods, you'll include a line like this:
+
+<device name="myswitch" port="43" option="off"/>
+
+This node will be fenced by disabling the port with ifIndex 43 on the host sw1.
+In SNMP speak, we set IF-MIB::ifAdminStatus.43 = down(2).
+
+If you will use port name (like fc1/1), script will try to find ifIndex.
diff --git a/agents/ifmib/fence_ifmib.py b/agents/ifmib/fence_ifmib.py
new file mode 100644
index 0000000..d119134
--- /dev/null
+++ b/agents/ifmib/fence_ifmib.py
@@ -0,0 +1,116 @@
+#!@PYTHON@ -tt
+
+# The Following agent has been tested on:
+# - Cisco MDS UROS 9134 FC (1 Slot) Chassis ("1/2/4 10 Gbps FC/Supervisor-2") Motorola, e500v2
+# with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c)
+# - Cisco MDS 9124 (1 Slot) Chassis ("1/2/4 Gbps FC/Supervisor-2") Motorola, e500
+# with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c)
+# - Partially with APC PDU (Network Management Card AOS v2.7.0, Rack PDU APP v2.7.3)
+# Only lance if is visible
+
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, array_to_dict
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# IF-MIB trees for alias, status and port
+ALIASES_OID = ".1.3.6.1.2.1.31.1.1.1.18"
+PORTS_OID = ".1.3.6.1.2.1.2.2.1.2"
+STATUSES_OID = ".1.3.6.1.2.1.2.2.1.7"
+
+# Status constants returned as value from SNMP
+STATUS_UP = 1
+STATUS_DOWN = 2
+STATUS_TESTING = 3
+
+### GLOBAL VARIABLES ###
+# Port number converted from port name or index
+port_num = None
+
+### FUNCTIONS ###
+
+# Convert port index or name to port index
+def port2index(conn, port):
+ res = None
+
+ if port.isdigit():
+ res = int(port)
+ else:
+ ports = conn.walk(PORTS_OID, 30)
+
+ for x in ports:
+ if x[1].strip('"') == port:
+ res = int(x[0].split('.')[-1])
+ break
+
+ if res == None:
+ fail_usage("Can't find port with name %s!"%(port))
+
+ return res
+
+def get_power_status(conn, options):
+ global port_num
+
+ if port_num == None:
+ port_num = port2index(conn, options["--plug"])
+
+ (_, status) = conn.get("%s.%d"%(STATUSES_OID, port_num))
+ return status == str(STATUS_UP) and "on" or "off"
+
+def set_power_status(conn, options):
+ global port_num
+
+ if port_num == None:
+ port_num = port2index(conn, options["--plug"])
+
+ conn.set("%s.%d" % (STATUSES_OID, port_num), (options["--action"] == "on" and STATUS_UP or STATUS_DOWN))
+
+def get_outlets_status(conn, options):
+ result = {}
+
+ res_fc = conn.walk(PORTS_OID, 30)
+ res_aliases = array_to_dict(conn.walk(ALIASES_OID, 30))
+
+ for x in res_fc:
+ port_number = x[0].split('.')[-1]
+
+ port_name = x[1].strip('"')
+ port_alias = (port_number in res_aliases and res_aliases[port_number].strip('"') or "")
+ port_status = ""
+ result[port_name] = (port_alias, port_status)
+
+ return result
+
+# Main agent method
+def main():
+ device_opt = ["fabric_fencing", "ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["snmp_version"]["default"] = "2c"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IF MIB"
+ docs["longdesc"] = "fence_ifmib is an I/O Fencing agent \
+which can be used with any SNMP IF-MIB capable device. \
+\n.P\n\
+It was written with managed ethernet switches in mind, in order to \
+fence iSCSI SAN connections. However, there are many devices that \
+support the IF-MIB interface. The agent uses IF-MIB::ifAdminStatus \
+to control the state of an interface."
+ docs["vendorurl"] = "http://www.ietf.org/wg/concluded/ifmib.html"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ilo/fence_ilo.py b/agents/ilo/fence_ilo.py
new file mode 100644
index 0000000..6124505
--- /dev/null
+++ b/agents/ilo/fence_ilo.py
@@ -0,0 +1,143 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## iLO Version
+## +---------------------------------------------+
+## iLO / firmware 1.91 / RIBCL 2.22
+## iLO2 / firmware 1.22 / RIBCL 2.22
+## iLO2 / firmware 1.50 / RIBCL 2.22
+#####
+
+import sys, re, pexpect
+import atexit
+from xml.sax.saxutils import quoteattr
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_LOGIN_DENIED
+
+def get_power_status(conn, options):
+ conn.send("<LOGIN USER_LOGIN = " + quoteattr(options["--username"]) + \
+ " PASSWORD = " + quoteattr(options["--password"]) + ">\r\n")
+ conn.send("<SERVER_INFO MODE = \"read\"><GET_HOST_POWER_STATUS/>\r\n")
+ conn.send("</SERVER_INFO></LOGIN>\r\n")
+ conn.log_expect("HOST_POWER=\"(.*?)\"", int(options["--power-timeout"]))
+
+ status = conn.match.group(1)
+ return status.lower().strip()
+
+def set_power_status(conn, options):
+ conn.send("<LOGIN USER_LOGIN = " + quoteattr(options["--username"]) + \
+ " PASSWORD = " + quoteattr(options["--password"]) + ">\r\n")
+ conn.send("<SERVER_INFO MODE = \"write\">")
+
+ if options.get("fw_processor", None) == "iLO2":
+ if options["fw_version"] > 1.29:
+ conn.send("<HOLD_PWR_BTN TOGGLE=\"yes\" />\r\n")
+ else:
+ conn.send("<HOLD_PWR_BTN />\r\n")
+ elif options["--ribcl-version"] < 2.21:
+ conn.send("<SET_HOST_POWER HOST_POWER = \"" + options["--action"] + "\" />\r\n")
+ else:
+ if options["--action"] == "off":
+ conn.send("<HOLD_PWR_BTN/>\r\n")
+ else:
+ conn.send("<PRESS_PWR_BTN/>\r\n")
+ conn.send("</SERVER_INFO></LOGIN>\r\n")
+
+ return
+
+def define_new_opts():
+ all_opt["ribcl"] = {
+ "getopt" : "r:",
+ "longopt" : "ribcl-version",
+ "help" : "-r, --ribcl-version=[version] Force ribcl version to use",
+ "required" : "0",
+ "shortdesc" : "Force ribcl version to use",
+ "order" : 1}
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "ssl", "notls", "tls1.0", "ribcl"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["login_timeout"]["default"] = "10"
+ all_opt["retry_on"]["default"] = "3"
+ all_opt["ssl"]["default"] = "1"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP iLO"
+ docs["longdesc"] = "fence_ilo is an I/O Fencing agent \
+used for HP servers with the Integrated Light Out (iLO) PCI card.\
+The agent opens an SSL connection to the iLO card. Once the SSL \
+connection is established, the agent is able to communicate with \
+the iLO card through an XML stream."
+ docs["vendorurl"] = "http://www.hp.com"
+ docs["symlink"] = [("fence_ilo2", "Fence agent for HP iLO2")]
+ show_docs(options, docs)
+
+ ##
+ ## Login and get version number
+ ####
+ conn = fence_login(options)
+ try:
+ conn.send("<?xml version=\"1.0\"?>\r\n")
+ conn.log_expect(["</RIBCL>", "<END_RIBCL/>"], int(options["--login-timeout"]))
+ except pexpect.TIMEOUT:
+ fail(EC_LOGIN_DENIED)
+ except pexpect.EOF:
+ if "--tls1.0" in options:
+ fail(EC_LOGIN_DENIED)
+ options["--tls1.0"] = "1"
+ conn.close()
+ conn = fence_login(options)
+ try:
+ conn.send("<?xml version=\"1.0\"?>\r\n")
+ conn.log_expect(["</RIBCL>", "<END_RIBCL/>"], int(options["--login-timeout"]))
+ except pexpect.TIMEOUT:
+ fail(EC_LOGIN_DENIED)
+ except pexpect.EOF:
+ fail(EC_LOGIN_DENIED)
+
+ try:
+ version = re.compile("<RIBCL VERSION=\"(.*?)\"", re.IGNORECASE).search(conn.before).group(1)
+ if "--ribcl-version" not in options:
+ options["--ribcl-version"] = float(version)
+
+ if options["--ribcl-version"] >= 2:
+ conn.send("<RIBCL VERSION=\"2.0\">\r\n")
+ else:
+ conn.send("<RIBCL VERSION=\"1.2\">\r\n")
+
+ conn.send("<LOGIN USER_LOGIN = " + quoteattr(options["--username"]) + \
+ " PASSWORD = " + quoteattr(options["--password"]) + ">\r\n")
+ if options["--ribcl-version"] >= 2:
+ conn.send("<RIB_INFO MODE=\"read\"><GET_FW_VERSION />\r\n")
+ conn.send("</RIB_INFO>\r\n")
+ conn.log_expect(r"<GET_FW_VERSION\s*\n", int(options["--shell-timeout"]))
+ conn.log_expect("/>", int(options["--shell-timeout"]))
+ options["fw_version"] = float(re.compile(r"FIRMWARE_VERSION\s*=\s*\"(.*?)\"",
+ re.IGNORECASE).search(conn.before).group(1))
+ options["fw_processor"] = re.compile(r"MANAGEMENT_PROCESSOR\s*=\s*\"(.*?)\"",
+ re.IGNORECASE).search(conn.before).group(1)
+ conn.send("</LOGIN>\r\n")
+ except pexpect.TIMEOUT:
+ fail(EC_LOGIN_DENIED)
+ except pexpect.EOF:
+ fail(EC_LOGIN_DENIED)
+
+ ##
+ ## Fence operations
+ ####
+ result = fence_action(conn, options, set_power_status, get_power_status, None)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ilo_moonshot/fence_ilo_moonshot.py b/agents/ilo_moonshot/fence_ilo_moonshot.py
new file mode 100644
index 0000000..1923eeb
--- /dev/null
+++ b/agents/ilo_moonshot/fence_ilo_moonshot.py
@@ -0,0 +1,65 @@
+#!@PYTHON@ -tt
+
+import sys
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS
+
+def get_power_status(conn, options):
+ conn.send_eol("show node list")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ nodes = {}
+ for line in conn.before.splitlines():
+ if len(line.split()) == 10:
+ nodes[line.split()[1]] = ("", line.split()[8].lower().strip())
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return nodes
+ else:
+ try:
+ (_, status) = nodes[options["--plug"]]
+ return status.lower()
+ except KeyError as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_STATUS)
+
+def set_power_status(conn, options):
+ if options["--action"] == "on":
+ conn.send_eol("set node power on %s" % (options["--plug"]))
+ else:
+ conn.send_eol("set node power off force %s" % (options["--plug"]))
+
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ return
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", "port"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["secure"]["default"] = "1"
+ all_opt["cmd_prompt"]["default"] = ["MP>", "hpiLO->"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP Moonshot iLO"
+ docs["longdesc"] = ""
+ docs["vendorurl"] = "http://www.hp.com"
+ show_docs(options, docs)
+
+ conn = fence_login(options)
+
+ ##
+ ## Fence operations
+ ####
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ilo_mp/fence_ilo_mp.py b/agents/ilo_mp/fence_ilo_mp.py
new file mode 100644
index 0000000..1ae4d3e
--- /dev/null
+++ b/agents/ilo_mp/fence_ilo_mp.py
@@ -0,0 +1,58 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+def get_power_status(conn, options):
+ conn.send_eol("show /system1")
+
+ re_state = re.compile('EnabledState=(.*)', re.IGNORECASE)
+ conn.log_expect(re_state, int(options["--shell-timeout"]))
+
+ status = conn.match.group(1).lower()
+
+ if status.startswith("enabled"):
+ return "on"
+ else:
+ return "off"
+
+def set_power_status(conn, options):
+ if options["--action"] == "on":
+ conn.send_eol("start /system1")
+ else:
+ conn.send_eol("stop -f /system1")
+
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ return
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["MP>", "hpiLO->"]
+ all_opt["power_wait"]["default"] = 5
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP iLO MP"
+ docs["longdesc"] = ""
+ docs["vendorurl"] = "http://www.hp.com"
+ show_docs(options, docs)
+
+ conn = fence_login(options)
+ conn.send_eol("SMCLP")
+
+ ##
+ ## Fence operations
+ ####
+ result = fence_action(conn, options, set_power_status, get_power_status)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ilo_ssh/fence_ilo_ssh.py b/agents/ilo_ssh/fence_ilo_ssh.py
new file mode 100644
index 0000000..a27e341
--- /dev/null
+++ b/agents/ilo_ssh/fence_ilo_ssh.py
@@ -0,0 +1,77 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+def get_power_status(conn, options):
+ conn.send_eol("show /system1")
+
+ re_state = re.compile('EnabledState=(.*)', re.IGNORECASE)
+ conn.log_expect(re_state, int(options["--shell-timeout"]))
+
+ status = conn.match.group(1).lower()
+
+ if status.startswith("enabled"):
+ return "on"
+ else:
+ return "off"
+
+def set_power_status(conn, options):
+ if options["--action"] == "on":
+ conn.send_eol("start /system1")
+ else:
+ conn.send_eol("power off hard")
+
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ return
+
+def reboot_cycle(conn, options):
+ conn.send_eol("reset /system1 hard")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ if get_power_status(conn, options) == "off":
+ logging.error("Timed out waiting to power ON\n")
+
+ return True
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", "method", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["MP>", "hpiLO->"]
+ all_opt["power_wait"]["default"] = 5
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for HP iLO over SSH"
+ docs["longdesc"] = "fence_ilo_ssh is a fence agent that connects to iLO device. It logs into \
+device via ssh and reboot a specified outlet.\
+\n.P\n\
+WARNING: The monitor-action is prone to timeouts. Use the fence_ilo-equivalent \
+to avoid this issue."
+ docs["vendorurl"] = "http://www.hp.com"
+ docs["symlink"] = [("fence_ilo3_ssh", "Fence agent for HP iLO3 over SSH"),
+ ("fence_ilo4_ssh", "Fence agent for HP iLO4 over SSH"),
+ ("fence_ilo5_ssh", "Fence agent for HP iLO5 over SSH")]
+ show_docs(options, docs)
+
+ options["eol"] = "\r"
+
+ conn = fence_login(options)
+ conn.send_eol("SMCLP")
+
+ ##
+ ## Fence operations
+ ####
+ result = fence_action(conn, options, set_power_status, get_power_status, None, reboot_cycle)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/intelmodular/fence_intelmodular.py b/agents/intelmodular/fence_intelmodular.py
new file mode 100644
index 0000000..294ea4d
--- /dev/null
+++ b/agents/intelmodular/fence_intelmodular.py
@@ -0,0 +1,86 @@
+#!@PYTHON@ -tt
+
+# Tested with an Intel MFSYS25 using firmware package 2.6 Should work with an
+# MFSYS35 as well.
+#
+# Notes:
+#
+# The manual and firmware release notes says SNMP is read only. This is not
+# true, as per the MIBs that ship with the firmware you can write to
+# the bladePowerLed oid to control the servers.
+#
+# Thanks Matthew Kent for original agent and testing.
+
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# From INTELCORPORATION-MULTI-FLEX-SERVER-BLADES-MIB.my that ships with
+# firmware updates
+STATUSES_OID = ".1.3.6.1.4.1.343.2.19.1.2.10.202.1.1.6"
+
+# Status constants returned as value from SNMP
+STATUS_UP = 2
+STATUS_DOWN = 0
+
+# Status constants to set as value to SNMP
+STATUS_SET_ON = 2
+STATUS_SET_OFF = 3
+
+### FUNCTIONS ###
+
+def get_power_status(conn, options):
+ (_, status) = conn.get("%s.%s"% (STATUSES_OID, options["--plug"]))
+ return status == str(STATUS_UP) and "on" or "off"
+
+def set_power_status(conn, options):
+ conn.set("%s.%s" % (STATUSES_OID, options["--plug"]),
+ (options["--action"] == "on" and STATUS_SET_ON or STATUS_SET_OFF))
+
+def get_outlets_status(conn, options):
+ result = {}
+
+ res_blades = conn.walk(STATUSES_OID, 30)
+
+ for x in res_blades:
+ port_num = x[0].split('.')[-1]
+
+ port_alias = ""
+ port_status = (x[1] == str(STATUS_UP) and "on" or "off")
+
+ result[port_num] = (port_alias, port_status)
+
+ return result
+
+# Main agent method
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password",
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Intel Modular"
+ docs["longdesc"] = "fence_intelmodular is an I/O Fencing agent \
+which can be used with Intel Modular device (tested on Intel MFSYS25, should \
+work with MFSYS35 as well). \
+\n.P\n\
+Note: Since firmware update version 2.7, SNMP v2 write support is \
+removed, and replaced by SNMP v3 support. So agent now has default \
+SNMP version 3. If you are using older firmware, please supply -d \
+for command line and snmp_version option for your cluster.conf."
+ docs["vendorurl"] = "http://www.intel.com"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ipdu/fence_ipdu.py b/agents/ipdu/fence_ipdu.py
new file mode 100644
index 0000000..da34d2b
--- /dev/null
+++ b/agents/ipdu/fence_ipdu.py
@@ -0,0 +1,153 @@
+#!@PYTHON@ -tt
+
+# The Following agent has been tested on:
+# IBM iPDU model 46M4002
+# Firmware release OPDP_sIBM_v01.2_1
+#
+
+import sys
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# oid defining fence device
+OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0'
+
+### GLOBAL VARIABLES ###
+# Device - see IBM iPDU
+device = None
+
+# Port ID
+port_id = None
+# Switch ID
+switch_id = None
+
+# Classes describing Device params
+class IBMiPDU(object):
+ # iPDU
+ status_oid = '.1.3.6.1.4.1.2.6.223.8.2.2.1.11.%d'
+ control_oid = '.1.3.6.1.4.1.2.6.223.8.2.2.1.11.%d'
+ outlet_table_oid = '.1.3.6.1.4.1.2.6.223.8.2.2.1.2'
+ ident_str = "IBM iPDU"
+ state_on = 1
+ state_off = 0
+ turn_on = 1
+ turn_off = 0
+ has_switches = False
+
+### FUNCTIONS ###
+def ipdu_set_device(conn, options):
+ global device
+
+ agents_dir = {'.1.3.6.1.4.1.2.6.223':IBMiPDU,
+ None:IBMiPDU}
+
+ # First resolve type of PDU device
+ pdu_type = conn.walk(OID_SYS_OBJECT_ID)
+
+ if not ((len(pdu_type) == 1) and (pdu_type[0][1] in agents_dir)):
+ pdu_type = [[None, None]]
+
+ device = agents_dir[pdu_type[0][1]]
+
+ logging.debug("Trying %s"%(device.ident_str))
+
+def ipdu_resolv_port_id(conn, options):
+ global port_id, switch_id
+
+ if device == None:
+ ipdu_set_device(conn, options)
+
+ # Now we resolv port_id/switch_id
+ if options["--plug"].isdigit() and ((not device.has_switches) or (options["--switch"].isdigit())):
+ port_id = int(options["--plug"])
+
+ if device.has_switches:
+ switch_id = int(options["--switch"])
+ else:
+ table = conn.walk(device.outlet_table_oid, 30)
+
+ for x in table:
+ if x[1].strip('"') == options["--plug"]:
+ t = x[0].split('.')
+ if device.has_switches:
+ port_id = int(t[len(t)-1])
+ switch_id = int(t[len(t)-3])
+ else:
+ port_id = int(t[len(t)-1])
+
+ if port_id == None:
+ fail_usage("Can't find port with name %s!"%(options["--plug"]))
+
+def get_power_status(conn, options):
+ if port_id == None:
+ ipdu_resolv_port_id(conn, options)
+
+ oid = ((device.has_switches) and device.status_oid%(switch_id, port_id) or device.status_oid%(port_id))
+
+ (oid, status) = conn.get(oid)
+ return status == str(device.state_on) and "on" or "off"
+
+def set_power_status(conn, options):
+ if port_id == None:
+ ipdu_resolv_port_id(conn, options)
+
+ oid = ((device.has_switches) and device.control_oid%(switch_id, port_id) or device.control_oid%(port_id))
+
+ conn.set(oid, (options["--action"] == "on" and device.turn_on or device.turn_off))
+
+
+def get_outlets_status(conn, options):
+ result = {}
+
+ if device == None:
+ ipdu_set_device(conn, options)
+
+ res_ports = conn.walk(device.outlet_table_oid, 30)
+
+ for x in res_ports:
+ t = x[0].split('.')
+
+ port_num = ((device.has_switches) and "%s:%s"%(t[len(t)-3], t[len(t)-1]) or "%s"%(t[len(t)-1]))
+
+ port_name = x[1].strip('"')
+ port_status = ""
+ result[port_num] = (port_name, port_status)
+
+ return result
+
+# Main agent method
+def main():
+ global device
+
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["snmp_version"]["default"] = "3"
+ all_opt["community"]["default"] = "private"
+ all_opt["switch"]["default"] = "1"
+ device = IBMiPDU
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for iPDU over SNMP"
+ docs["longdesc"] = "fence_ipdu is an I/O Fencing agent \
+which can be used with the IBM iPDU network power switch. It logs \
+into a device via SNMP and reboots a specified outlet. It supports \
+SNMP v3 with all combinations of authenticity/privacy settings."
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+if __name__ == "__main__":
+ main()
diff --git a/agents/ipmilan/fence_ipmilan.py b/agents/ipmilan/fence_ipmilan.py
new file mode 100644
index 0000000..f751de6
--- /dev/null
+++ b/agents/ipmilan/fence_ipmilan.py
@@ -0,0 +1,233 @@
+#!@PYTHON@ -tt
+
+import sys, re, os
+import atexit
+from pipes import quote
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, is_executable, run_command, run_delay
+
+def get_power_status(_, options):
+ output = _run_command(options, "status")
+ match = re.search('[Cc]hassis [Pp]ower is [\\s]*([a-zA-Z]{2,3})', str(output))
+ status = match.group(1) if match else None
+ return status
+
+def set_power_status(_, options):
+ _run_command(options, options["--action"])
+ return
+
+def reboot_cycle(_, options):
+ output = _run_command(options, "cycle")
+ return bool(re.search('chassis power control: cycle', str(output).lower()))
+
+def reboot_diag(_, options):
+ output = _run_command(options, "diag")
+ return bool(re.search('chassis power control: diag', str(output).lower()))
+
+def _run_command(options, action):
+ cmd, log_cmd = create_command(options, action)
+ return run_command(options, cmd, log_command=log_cmd)
+
+def create_command(options, action):
+ class Cmd:
+ cmd = ""
+ log = ""
+
+ @classmethod
+ def append(cls, cmd, log=None):
+ cls.cmd += cmd
+ cls.log += (cmd if log is None else log)
+
+ # --use-sudo / -d
+ if "--use-sudo" in options:
+ Cmd.append(options["--sudo-path"] + " ")
+
+ Cmd.append(options["--ipmitool-path"])
+
+ # --lanplus / -L
+ if "--lanplus" in options and options["--lanplus"] in ["", "1"]:
+ Cmd.append(" -I lanplus")
+ else:
+ Cmd.append(" -I lan")
+
+ # --ip / -a
+ Cmd.append(" -H " + options["--ip"])
+
+ # --port / -n
+ if "--ipport" in options:
+ Cmd.append(" -p " + options["--ipport"])
+
+ # --target
+ if "--target" in options:
+ Cmd.append(" -t " + options["--target"])
+
+ # --username / -l
+ if "--username" in options and len(options["--username"]) != 0:
+ Cmd.append(" -U " + quote(options["--username"]))
+
+ # --auth / -A
+ if "--auth" in options:
+ Cmd.append(" -A " + options["--auth"])
+
+ # --password / -p
+ if "--password" in options:
+ Cmd.append(" -P " + quote(options["--password"]), " -P [set]")
+ else:
+ Cmd.append(" -P ''", " -P [set]")
+
+ # --cipher / -C
+ if "--cipher" in options:
+ Cmd.append(" -C " + options["--cipher"])
+
+ if "--privlvl" in options:
+ Cmd.append(" -L " + options["--privlvl"])
+
+ if "--hexadecimal-kg" in options:
+ Cmd.append(" -y " + options["--hexadecimal-kg"])
+
+ if "--ipmitool-timeout" in options:
+ Cmd.append(" -N " + options["--ipmitool-timeout"])
+
+ # --action / -o
+ Cmd.append(" chassis power " + action)
+
+ # --verbose-level
+ if options["--verbose-level"] > 1:
+ Cmd.append(" -" + "v" * (options["--verbose-level"] - 1))
+
+ return (Cmd.cmd, Cmd.log)
+
+def define_new_opts():
+ all_opt["lanplus"] = {
+ "getopt" : "P",
+ "longopt" : "lanplus",
+ "help" : "-P, --lanplus Use Lanplus to improve security of connection",
+ "required" : "0",
+ "default" : "0",
+ "shortdesc" : "Use Lanplus to improve security of connection",
+ "order": 1
+ }
+ all_opt["auth"] = {
+ "getopt" : "A:",
+ "longopt" : "auth",
+ "help" : "-A, --auth=[auth] IPMI Lan Auth type (md5|password|none)",
+ "required" : "0",
+ "shortdesc" : "IPMI Lan Auth type.",
+ "choices" : ["md5", "password", "none"],
+ "order": 1
+ }
+ all_opt["cipher"] = {
+ "getopt" : "C:",
+ "longopt" : "cipher",
+ "help" : "-C, --cipher=[cipher] Ciphersuite to use (same as ipmitool -C parameter)",
+ "required" : "0",
+ "shortdesc" : "Ciphersuite to use (same as ipmitool -C parameter)",
+ "order": 1
+ }
+ all_opt["privlvl"] = {
+ "getopt" : "L:",
+ "longopt" : "privlvl",
+ "help" : "-L, --privlvl=[level] "
+ "Privilege level on IPMI device (callback|user|operator|administrator)",
+ "required" : "0",
+ "shortdesc" : "Privilege level on IPMI device",
+ "default" : "administrator",
+ "choices" : ["callback", "user", "operator", "administrator"],
+ "order": 1
+ }
+ all_opt["ipmitool_path"] = {
+ "getopt" : ":",
+ "longopt" : "ipmitool-path",
+ "help" : "--ipmitool-path=[path] Path to ipmitool binary",
+ "required" : "0",
+ "shortdesc" : "Path to ipmitool binary",
+ "default" : "@IPMITOOL_PATH@",
+ "order": 200
+ }
+ all_opt["ipmitool_timeout"] = {
+ "getopt" : ":",
+ "longopt" : "ipmitool-timeout",
+ "help" : "--ipmitool-timeout=[timeout] Timeout (sec) for IPMI operation",
+ "required" : "0",
+ "shortdesc" : "Timeout (sec) for IPMI operation",
+ "default" : "2",
+ "order": 201
+ }
+ all_opt["target"] = {
+ "getopt" : ":",
+ "longopt" : "target",
+ "help" : "--target=[targetaddress] Bridge IPMI requests to the remote target address",
+ "required" : "0",
+ "shortdesc" : "Bridge IPMI requests to the remote target address",
+ "order": 1
+ }
+ all_opt["hexadecimal_kg"] = {
+ "getopt" : ":",
+ "longopt" : "hexadecimal-kg",
+ "help" : "--hexadecimal-kg=[key] Hexadecimal-encoded Kg key for IPMIv2 authentication",
+ "required" : "0",
+ "shortdesc" : "Hexadecimal-encoded Kg key for IPMIv2 authentication",
+ "order": 1
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["ipaddr", "login", "no_login", "no_password", "passwd",
+ "diag", "lanplus", "auth", "cipher", "privlvl", "sudo",
+ "ipmitool_path", "ipmitool_timeout", "method", "target", "hexadecimal_kg"]
+ define_new_opts()
+
+ all_opt["power_wait"]["default"] = 2
+ if os.path.basename(sys.argv[0]) == "fence_ilo3":
+ all_opt["power_wait"]["default"] = "4"
+ all_opt["lanplus"]["default"] = "1"
+ elif os.path.basename(sys.argv[0]) == "fence_ilo4":
+ all_opt["lanplus"]["default"] = "1"
+ elif os.path.basename(sys.argv[0]) == "fence_ilo5":
+ all_opt["lanplus"]["default"] = "1"
+ elif os.path.basename(sys.argv[0]) == "fence_ipmilanplus":
+ all_opt["lanplus"]["default"] = "1"
+
+ all_opt["ipport"]["default"] = "623"
+ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: onoff)\n" \
+ "WARNING! This fence agent might report success before the node is powered off. " \
+ "You should use -m/method onoff if your fence device works correctly with that option."
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IPMI"
+ docs["longdesc"] = "fence_ipmilan is an I/O Fencing agent\
+which can be used with machines controlled by IPMI.\
+This agent calls support software ipmitool (http://ipmitool.sf.net/). \
+WARNING! This fence agent might report success before the node is powered off. \
+You should use -m/method onoff if your fence device works correctly with that option."
+ docs["vendorurl"] = ""
+ docs["symlink"] = [("fence_ilo3", "Fence agent for HP iLO3"),
+ ("fence_ilo4", "Fence agent for HP iLO4"),
+ ("fence_ilo5", "Fence agent for HP iLO5"),
+ ("fence_ipmilanplus", "Fence agent for IPMIv2 lanplus"),
+ ("fence_imm", "Fence agent for IBM Integrated Management Module"),
+ ("fence_idrac", "Fence agent for Dell iDRAC")]
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if not is_executable(options["--ipmitool-path"]):
+ fail_usage("Ipmitool not found or not accessible")
+
+ reboot_fn = reboot_cycle
+ if options["--action"] == "diag":
+ # Diag is a special action that can't be verified so we will reuse reboot functionality
+ # to minimize impact on generic library
+ options["--action"] = "reboot"
+ options["--method"] = "cycle"
+ reboot_fn = reboot_diag
+
+ result = fence_action(None, options, set_power_status, get_power_status, None, reboot_fn)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ironic/fence_ironic.py b/agents/ironic/fence_ironic.py
new file mode 100644
index 0000000..66d84fc
--- /dev/null
+++ b/agents/ironic/fence_ironic.py
@@ -0,0 +1,130 @@
+#!@PYTHON@ -tt
+
+import atexit
+import logging
+import os
+import re
+import sys
+from pipes import quote
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, is_executable, run_command, run_delay
+
+def get_name_or_uuid(options):
+ return options["--uuid"] if "--uuid" in options else options["--plug"]
+
+def get_power_status(_, options):
+ output = ironic_run_command(options, "status")
+ stdout = output[1]
+ match = re.search('power[\\s]*([a-zA-Z]{2,3})', str(stdout))
+ status = match.group(1) if match else None
+ return status
+
+def set_power_status(_, options):
+ ironic_run_command(options, options["--action"])
+ return
+
+def get_devices_list(_, options):
+ nodes = {}
+ output = ironic_run_command(options, "list")
+ stdout = output[1]
+ for line in stdout.splitlines():
+ uuid = "UUID"
+ try:
+ (uuid, name, state) = line.split(',')
+ except ValueError:
+ pass
+ if "UUID" in uuid:
+ continue # skip line header
+ match = re.search('power[\\s]*([a-zA-Z]{2,3})', state)
+ status = match.group(1) if match else None
+ nodes[uuid] = (name, status)
+
+ return nodes
+
+def ironic_run_command(options, action, timeout=None):
+ cmd = options["--openstack-path"] + " baremetal"
+ env = os.environ.copy()
+ # --username / -l
+ if "--username" in options and len(options["--username"]) != 0:
+ env["OS_USERNAME"] = options["--username"]
+
+ # --password / -p
+ if "--password" in options:
+ env["OS_PASSWORD"] = options["--password"]
+
+ # --tenant-name -t
+ if "--tenant-name" in options:
+ env["OS_TENANT_NAME"] = options["--tenant-name"]
+
+ # --auth-url
+ if "--auth-url" in options:
+ env["OS_AUTH_URL"] = options["--auth-url"]
+
+ # --action / -o
+ if action == "status":
+ cmd += " show %s -c power_state --format value" % (get_name_or_uuid(options))
+ elif action in ["on", "off"]:
+ cmd += " power %s %s" % (action, get_name_or_uuid(options))
+ elif action == "list":
+ cmd += " list -c 'Instance UUID' -c Name -c 'Power State' --format csv --quote minimal"
+
+
+ logging.debug("cmd -> %s" % cmd)
+ return run_command(options, cmd, timeout, env)
+
+def define_new_opts():
+ all_opt["auth-url"] = {
+ "getopt" : ":",
+ "longopt" : "auth-url",
+ "help" : "--auth-url=[authurl] Auth URL",
+ "required" : "1",
+ "shortdesc" : "Keystone Admin Auth URL",
+ "order": 1
+ }
+ all_opt["tenant-name"] = {
+ "getopt" : "t:",
+ "longopt" : "tenant-name",
+ "help" : "-t, --tenant-name=[tenant] Tenantname",
+ "required" : "0",
+ "shortdesc" : "Keystone Admin Tenant",
+ "default": "admin",
+ "order": 1
+ }
+ all_opt["openstack-path"] = {
+ "getopt" : ":",
+ "longopt" : "openstack-path",
+ "help" : "--openstack-path=[path] Path to openstack binary",
+ "required" : "0",
+ "shortdesc" : "Path to the OpenStack binary",
+ "default" : "@OPENSTACK_PATH@",
+ "order": 200
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["login", "passwd", "port", "auth-url", "tenant-name", "openstack-path"]
+ define_new_opts()
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for OpenStack's Ironic (Bare Metal as a service) service"
+ docs["longdesc"] = "fence_ironic is a Fencing agent \
+which can be used with machines controlled by the Ironic service. \
+This agent calls the openstack CLI. \
+WARNING! This fence agent is not intended for production use. Relying on a functional ironic service for fencing is not a good design choice."
+ docs["vendorurl"] = "https://wiki.openstack.org/wiki/Ironic"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if not is_executable(options["--openstack-path"]):
+ fail_usage("openstack tool not found or not accessible")
+
+ result = fence_action(None, options, set_power_status, get_power_status, get_devices_list)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/kdump/fence_kdump.c b/agents/kdump/fence_kdump.c
new file mode 100644
index 0000000..eda1559
--- /dev/null
+++ b/agents/kdump/fence_kdump.c
@@ -0,0 +1,592 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) Ryan O'Hara (rohara@redhat.com)
+ * Copyright (c) Red Hat, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "options.h"
+#include "message.h"
+#include "version.h"
+
+static int verbose = 0;
+
+#define log_debug(lvl, fmt, args...) \
+do { \
+ if (lvl <= verbose) { \
+ fprintf (stdout, "[debug]: " fmt, ##args); \
+ syslog (LOG_INFO, fmt, ##args); \
+ } \
+} while (0);
+
+#define log_error(lvl, fmt, args...) \
+do { \
+ if (lvl <= verbose) { \
+ fprintf (stderr, "[error]: " fmt, ##args); \
+ syslog (LOG_ERR, fmt, ##args); \
+ } \
+} while (0);
+
+static int
+trim (char *str)
+{
+ char *p;
+ int len;
+
+ if (!str) return (0);
+
+ len = strlen (str);
+
+ while (len--) {
+ if (isspace (str[len])) {
+ str[len] = 0;
+ } else {
+ break;
+ }
+ }
+
+ for (p = str; *p && isspace (*p); p++);
+
+ memmove (str, p, strlen (p) + 1);
+
+ return (strlen (str));
+}
+
+static int
+do_action_monitor (void)
+{
+ const char cmdline_path[] = "/proc/cmdline";
+ FILE *procFile;
+ size_t sz = 0;
+ char *lines = NULL;
+ int result = 1;
+
+ procFile = fopen(cmdline_path, "r");
+
+ if (procFile == NULL) {
+ log_error (0, "Unable to open file %s (%s)\n", cmdline_path, strerror (errno));
+ return 1;
+ }
+
+ while (!feof (procFile)) {
+ ssize_t rv = getline (&lines, &sz, procFile);
+ if ((rv != -1) && (strstr(lines, "crashkernel=") != NULL)) {
+ result = 0;
+ }
+ }
+
+ free (lines);
+ fclose (procFile);
+
+ return result;
+}
+
+static int
+do_action_off (const fence_kdump_opts_t *opts)
+{
+ int error;
+ fd_set rfds;
+ fence_kdump_msg_t msg;
+ fence_kdump_node_t *node;
+ struct timeval timeout;
+ struct addrinfo hints;
+ fence_kdump_node_t *check_node;
+ char addr[NI_MAXHOST];
+ char port[NI_MAXSERV];
+ struct sockaddr_storage ss;
+ socklen_t size = sizeof (ss);
+
+ if (list_empty (&opts->nodes)) {
+ return (1);
+ } else {
+ node = list_first_entry (&opts->nodes, fence_kdump_node_t, list);
+ }
+
+ timeout.tv_sec = opts->timeout;
+ timeout.tv_usec = 0;
+
+ FD_ZERO (&rfds);
+ FD_SET (node->socket, &rfds);
+
+ // create listening socket
+ memset (&hints, 0, sizeof (hints));
+
+ hints.ai_family = opts->family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ hints.ai_family = node->info->ai_family;
+ hints.ai_flags |= AI_PASSIVE;
+
+ freeaddrinfo (node->info);
+
+ node->info = NULL;
+ error = getaddrinfo (NULL, node->port, &hints, &node->info);
+ if (error != 0) {
+ log_error (2, "getaddrinfo (%s)\n", gai_strerror (error));
+ free_node (node);
+ return (1);
+ }
+
+ error = bind (node->socket, node->info->ai_addr, node->info->ai_addrlen);
+ if (error != 0) {
+ log_error (2, "bind (%s)\n", strerror (errno));
+ free_node (node);
+ return (1);
+ }
+
+ list_for_each_entry (check_node, &opts->nodes, list) {
+ log_debug (0, "waiting for message from '%s'\n", check_node->addr);
+ if (node->info->ai_family != check_node->info->ai_family) {
+ log_error (0, "mixing IPv4 and IPv6 nodes is not supported\n");
+ return (1);
+ }
+ }
+
+ for (;;) {
+ error = select (node->socket + 1, &rfds, NULL, NULL, &timeout);
+ if (error < 0) {
+ log_error (2, "select (%s)\n", strerror (errno));
+ break;
+ }
+ if (error == 0) {
+ log_debug (0, "timeout after %d seconds\n", opts->timeout);
+ break;
+ }
+
+ error = recvfrom (node->socket, &msg, sizeof (msg), 0, (struct sockaddr *) &ss, &size);
+ if (error < 0) {
+ log_error (2, "recvfrom (%s)\n", strerror (errno));
+ continue;
+ }
+
+ error = getnameinfo ((struct sockaddr *) &ss, size,
+ addr, sizeof (addr),
+ port, sizeof (port),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ log_error (2, "getnameinfo (%s)\n", gai_strerror (error));
+ continue;
+ }
+
+ if (msg.magic != FENCE_KDUMP_MAGIC) {
+ log_debug (1, "invalid magic number '0x%X'\n", msg.magic);
+ continue;
+ }
+
+ // check if we have matched messages from any known node
+ list_for_each_entry (check_node, &opts->nodes, list) {
+ error = strcasecmp (check_node->addr, addr);
+ if (error == 0 ) {
+ switch (msg.version) {
+ case FENCE_KDUMP_MSGV1:
+ log_debug (0, "received valid message from '%s'\n", addr);
+ return (0);
+ default:
+ log_debug (1, "invalid message version '0x%X'\n", msg.version);
+ continue;
+ }
+ }
+ }
+ log_debug (1, "discard message from '%s'\n", addr);
+
+ }
+
+ return (1);
+}
+
+static int
+do_action_metadata (const char *self)
+{
+ fprintf (stdout, "<?xml version=\"1.0\" ?>\n");
+ fprintf (stdout, "<resource-agent name=\"%s\"", basename (self));
+ fprintf (stdout, " shortdesc=\"fencing agent for use with kdump crash recovery service\">\n");
+ fprintf (stdout, "<longdesc>");
+ fprintf (stdout, "fence_kdump is an I/O fencing agent to be used with the kdump\n"
+ "crash recovery service. When the fence_kdump agent is invoked,\n"
+ "it will listen for a message from the failed node that acknowledges\n"
+ "that the failed node is executing the kdump crash kernel.\n"
+ "Note that fence_kdump is not a replacement for traditional\n"
+ "fencing methods. The fence_kdump agent can only detect that a\n"
+ "node has entered the kdump crash recovery service. This allows the\n"
+ "kdump crash recovery service complete without being preempted by\n"
+ "traditional power fencing methods.\n\n"
+ "Note: the \"off\" action listen for message from failed node that\n"
+ "acknowledges node has entered kdump crash recovery service. If a valid\n"
+ "message is received from the failed node, the node is considered to be\n"
+ "fenced and the agent returns success. Failure to receive a valid\n"
+ "message from the failed node in the given timeout period results in\n"
+ "fencing failure. When multiple node names/IP addresses are specified\n"
+ "a single valid message is sufficient for success. This is useful when\n"
+ "single node can send message via several different IP addresses.\n");
+ fprintf (stdout, "</longdesc>\n");
+ fprintf (stdout, "<vendor-url>http://www.kernel.org/pub/linux/utils/kernel/kexec/</vendor-url>\n");
+
+ fprintf (stdout, "<parameters>\n");
+
+ fprintf (stdout, "\t<parameter name=\"nodename\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-n, --nodename=NODE[,NODE...]\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "List of names or IP addresses of node to be fenced. This option is\n"
+ "required for the \"off\" action. Multiple values separated by commas\n"
+ "can be specified. All values must be of same IP network family." );
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"ipport\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-p, --ipport=PORT\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"7410\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "IP port number that the fence_kdump agent will use to listen for\n"
+ "messages.");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"family\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-f, --family=FAMILY\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"auto\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "IP network family. Force the fence_kdump agent to use a specific\n"
+ "family. The value for FAMILY can be \"auto\", \"ipv4\", or\n"
+ "\"ipv6\".");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"action\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-o, --action=ACTION\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"off\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Fencing action to perform. The value for ACTION can be either\n"
+ "\"off\" or \"metadata\".");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"timeout\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-t, --timeout=TIMEOUT\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"60\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Number of seconds to wait for message from failed node. If no message\n"
+ "is received within TIMEOUT seconds, the fence_kdump agent\n"
+ "returns failure.");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"verbose\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-v, --verbose\" />\n");
+ fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Print verbose output");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"version\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-V, --version\" />\n");
+ fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Print version");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"usage\" unique=\"0\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-h, --help\" />\n");
+ fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Print usage");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "</parameters>\n");
+
+ fprintf (stdout, "<actions>\n");
+ fprintf (stdout, "\t<action name=\"off\" />\n");
+ fprintf (stdout, "\t<action name=\"monitor\" />\n");
+ fprintf (stdout, "\t<action name=\"metadata\" />\n");
+ fprintf (stdout, "\t<action name=\"validate-all\" />\n");
+ fprintf (stdout, "</actions>\n");
+
+ fprintf (stdout, "</resource-agent>\n");
+
+ return (0);
+}
+
+static void
+print_usage (const char *self)
+{
+ fprintf (stdout, "Usage: %s [options]\n", basename (self));
+ fprintf (stdout, "\n");
+ fprintf (stdout, "Options:\n");
+ fprintf (stdout, "\n");
+ fprintf (stdout, "%s\n",
+ " -n, --nodename=NODE[,NODE...]List of names or IP addresses of node to be fenced");
+ fprintf (stdout, "%s\n",
+ " -p, --ipport=PORT IP port number (default: 7410)");
+ fprintf (stdout, "%s\n",
+ " -f, --family=FAMILY Network family: ([auto], ipv4, ipv6)");
+ fprintf (stdout, "%s\n",
+ " -o, --action=ACTION Fencing action: ([off], monitor, metadata, validate-all)");
+ fprintf (stdout, "%s\n",
+ " -t, --timeout=TIMEOUT Timeout in seconds (default: 60)");
+ fprintf (stdout, "%s\n",
+ " -v, --verbose Print verbose output");
+ fprintf (stdout, "%s\n",
+ " -V, --version Print version");
+ fprintf (stdout, "%s\n",
+ " -h, --help Print usage");
+ fprintf (stdout, "\n");
+
+ return;
+}
+
+static int
+get_options_node (fence_kdump_opts_t *opts)
+{
+ int error;
+ struct addrinfo hints;
+ fence_kdump_node_t *node;
+
+ node = malloc (sizeof (fence_kdump_node_t));
+ if (!node) {
+ log_error (2, "malloc (%s)\n", strerror (errno));
+ return (1);
+ }
+
+ memset (node, 0, sizeof (fence_kdump_node_t));
+ memset (&hints, 0, sizeof (hints));
+
+ hints.ai_family = opts->family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ strncpy (node->name, opts->nodename, sizeof (node->name) - 1);
+ snprintf (node->port, sizeof (node->port), "%d", opts->ipport);
+
+ node->info = NULL;
+ error = getaddrinfo (node->name, node->port, &hints, &node->info);
+ if (error != 0) {
+ log_error (2, "getaddrinfo (%s)\n", gai_strerror (error));
+ free_node (node);
+ return (1);
+ }
+
+ error = getnameinfo (node->info->ai_addr, node->info->ai_addrlen,
+ node->addr, sizeof (node->addr),
+ node->port, sizeof (node->port),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ log_error (2, "getnameinfo (%s)\n", gai_strerror (error));
+ free_node (node);
+ return (1);
+ }
+
+ node->socket = socket (node->info->ai_family,
+ node->info->ai_socktype,
+ node->info->ai_protocol);
+ if (node->socket < 0) {
+ log_error (2, "socket (%s)\n", strerror (errno));
+ free_node (node);
+ return (1);
+ }
+
+ list_add_tail (&node->list, &opts->nodes);
+
+ return (0);
+}
+
+static void
+get_options (int argc, char **argv, fence_kdump_opts_t *opts)
+{
+ int opt;
+
+ struct option options[] = {
+ { "nodename", required_argument, NULL, 'n' },
+ { "ipport", required_argument, NULL, 'p' },
+ { "family", required_argument, NULL, 'f' },
+ { "action", required_argument, NULL, 'o' },
+ { "timeout", required_argument, NULL, 't' },
+ { "verbose", optional_argument, NULL, 'v' },
+ { "version", no_argument, NULL, 'V' },
+ { "help", no_argument, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ while ((opt = getopt_long (argc, argv, "n:p:f:o:t:v::Vh", options, NULL)) != EOF) {
+ switch (opt) {
+ case 'n':
+ set_option_nodename (opts, optarg);
+ break;
+ case 'p':
+ set_option_ipport (opts, optarg);
+ break;
+ case 'f':
+ set_option_family (opts, optarg);
+ break;
+ case 'o':
+ set_option_action (opts, optarg);
+ break;
+ case 't':
+ set_option_timeout (opts, optarg);
+ break;
+ case 'v':
+ set_option_verbose (opts, optarg);
+ break;
+ case 'V':
+ print_version (argv[0]);
+ exit (0);
+ case 'h':
+ print_usage (argv[0]);
+ exit (0);
+ default:
+ print_usage (argv[0]);
+ exit (1);
+ }
+ }
+
+ verbose = opts->verbose;
+
+ return;
+}
+
+static void
+get_options_stdin (fence_kdump_opts_t *opts)
+{
+ char buf[1024];
+ char *opt;
+ char *arg;
+
+ while (fgets (buf, sizeof (buf), stdin) != 0) {
+ if (trim (buf) == 0) {
+ continue;
+ }
+ if (buf[0] == '#') {
+ continue;
+ }
+
+ opt = buf;
+
+ if ((arg = strchr (opt, '=')) != 0) {
+ *arg = 0;
+ arg += 1;
+ } else {
+ continue;
+ }
+
+ if (!strcasecmp (opt, "nodename")) {
+ set_option_nodename (opts, arg);
+ continue;
+ }
+ if (!strcasecmp (opt, "ipport")) {
+ set_option_ipport (opts, arg);
+ continue;
+ }
+ if (!strcasecmp (opt, "family")) {
+ set_option_family (opts, arg);
+ continue;
+ }
+ if (!strcasecmp (opt, "action")) {
+ set_option_action (opts, arg);
+ continue;
+ }
+ if (!strcasecmp (opt, "timeout")) {
+ set_option_timeout (opts, arg);
+ continue;
+ }
+ if (!strcasecmp (opt, "verbose")) {
+ set_option_verbose (opts, arg);
+ continue;
+ }
+ }
+
+ verbose = opts->verbose;
+
+ return;
+}
+
+int
+main (int argc, char **argv)
+{
+ int error = 1;
+ fence_kdump_opts_t opts;
+ char *ptr;
+ char *node_list;
+
+ init_options (&opts);
+
+ if (argc > 1) {
+ get_options (argc, argv, &opts);
+ } else {
+ get_options_stdin (&opts);
+ }
+
+ openlog ("fence_kdump", LOG_CONS|LOG_PID, LOG_DAEMON);
+
+ if (opts.action == FENCE_KDUMP_ACTION_OFF) {
+ if (opts.nodename == NULL) {
+ log_error (0, "action 'off' requires nodename\n");
+ exit (1);
+ }
+ node_list = (char *)malloc(strlen(opts.nodename)+1);
+
+ strcpy(node_list, opts.nodename); //make local copy of nodename on which we can safely iterate
+ // iterate through node_list
+ for (ptr = strtok(node_list, ","); ptr != NULL; ptr = strtok(NULL, ",")) {
+ set_option_nodename (&opts, ptr); //overwrite nodename for next function
+ if (get_options_node (&opts) != 0) {
+ log_error (0, "failed to get node '%s'\n", opts.nodename);
+ exit (1);
+ }
+ }
+ free(node_list);
+ }
+
+ if (verbose != 0) {
+ //clear nodename to avoid showing just last nodename here
+ free(opts.nodename);
+ opts.nodename = NULL;
+ print_options (&opts);
+ }
+
+ switch (opts.action) {
+ case FENCE_KDUMP_ACTION_OFF:
+ error = do_action_off (&opts);
+ break;
+ case FENCE_KDUMP_ACTION_METADATA:
+ error = do_action_metadata (argv[0]);
+ break;
+ case FENCE_KDUMP_ACTION_MONITOR:
+ error = do_action_monitor ();
+ break;
+ case FENCE_KDUMP_ACTION_VALIDATE:
+ error = 0;
+ break;
+ default:
+ break;
+ }
+
+ free_options (&opts);
+
+ return (error);
+}
diff --git a/agents/kdump/fence_kdump_send.8 b/agents/kdump/fence_kdump_send.8
new file mode 100644
index 0000000..ab95836
--- /dev/null
+++ b/agents/kdump/fence_kdump_send.8
@@ -0,0 +1,50 @@
+.TH fence_kdump_send 8
+.SH NAME
+fence_kdump_send - send kdump acknowlegement message to cluster nodes
+.SH SYNOPSIS
+.B
+fence_kdump_send
+[\fIOPTIONS]\fR... [NODE]...
+.SH DESCRIPTION
+\fIfence_kdump_send\fP is a utility used to send messages that
+acknowledge that the node has entered the kdump crash recovery
+service. This utility is intended to be used the the \fIfence_kdump\fP
+agent as a means detect that a failed node has entered the kdump crash
+recovery service.
+The \fIfence_kdump_send\fP utility is typically run from within the
+kdump kernel after a cluster node has encountered a kernel panic. Once
+the cluster node has entered the kdump crash recovery service,
+\fIfence_kdump_send\fP will periodically send messages to all cluster
+nodes. When the \fIfence_kdump\fP agent receives a valid message from
+the failed node, fencing is complete.
+.SH OPTIONS
+.TP
+.B -p, --ipport=\fIPORT\fP
+IP port number that the \fIfence_kdump\fP agent is using to listen for
+messages. (default: 7410)
+.TP
+.B -f, --family=\fIFAMILY\fP
+IP network family. Force the \fIfence_kdump_send\fP utility to use a
+particular network family. Value for \fIFAMILY\fP can be "auto",
+"ipv4", or "ipv6". (default: auto)
+.TP
+.B -c, --count=\fICOUNT\fP
+Number of messages to send. If \fICOUNT\fP is zero,
+\fIfence_kdump_send\fP will send messages indefinitely. (default: 0)
+.TP
+.B -i, --interval=\fIINTERVAL\fP
+Time to wait between sending a message. The value for \fIINTERVAL\fP
+must be greater than zero. (default: 10)
+.TP
+.B -v, --verbose
+Print verbose output.
+.TP
+.B -V, --version
+Print version and exit.
+.TP
+.B -h, --help
+Print usage and exit.
+.SH AUTHOR
+Ryan O'Hara <rohara@redhat.com>
+.SH SEE ALSO
+fence_kdump(8), mkdumprd(8), kdump.conf(5)
diff --git a/agents/kdump/fence_kdump_send.c b/agents/kdump/fence_kdump_send.c
new file mode 100644
index 0000000..638f8c9
--- /dev/null
+++ b/agents/kdump/fence_kdump_send.c
@@ -0,0 +1,255 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) Ryan O'Hara (rohara@redhat.com)
+ * Copyright (c) Red Hat, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "options.h"
+#include "message.h"
+#include "version.h"
+
+static int verbose = 0;
+
+#define log_debug(lvl, fmt, args...) \
+do { \
+ if (lvl <= verbose) \
+ fprintf (stdout, "[debug]: " fmt, ##args); \
+} while (0);
+
+#define log_error(lvl, fmt, args...) \
+do { \
+ if (lvl <= verbose) \
+ fprintf (stderr, "[error]: " fmt, ##args); \
+} while (0);
+
+static int
+send_message (const fence_kdump_node_t *node, void *msg, int len)
+{
+ int error;
+
+ error = sendto (node->socket, msg, len, 0, node->info->ai_addr, node->info->ai_addrlen);
+ if (error < 0) {
+ log_error (2, "sendto (%s)\n", strerror (errno));
+ goto out;
+ }
+
+ log_debug (1, "message sent to node '%s'\n", node->addr);
+
+out:
+ return (error);
+}
+
+static void
+print_usage (const char *self)
+{
+ fprintf (stdout, "Usage: %s [options] [nodes]\n", basename (self));
+ fprintf (stdout, "\n");
+ fprintf (stdout, "Options:\n");
+ fprintf (stdout, "\n");
+ fprintf (stdout, "%s\n",
+ " -p, --ipport=PORT Port number (default: 7410)");
+ fprintf (stdout, "%s\n",
+ " -f, --family=FAMILY Network family ([auto], ipv4, ipv6)");
+ fprintf (stdout, "%s\n",
+ " -c, --count=COUNT Number of messages to send (default: 0)");
+ fprintf (stdout, "%s\n",
+ " -i, --interval=INTERVAL Interval in seconds (default: 10)");
+ fprintf (stdout, "%s\n",
+ " -v, --verbose Print verbose output");
+ fprintf (stdout, "%s\n",
+ " -V, --version Print version");
+ fprintf (stdout, "%s\n",
+ " -h, --help Print usage");
+ fprintf (stdout, "\n");
+
+ return;
+}
+
+static int
+get_options_node (fence_kdump_opts_t *opts)
+{
+ int error;
+ struct addrinfo hints;
+ fence_kdump_node_t *node;
+
+ node = malloc (sizeof (fence_kdump_node_t));
+ if (!node) {
+ log_error (2, "malloc (%s)\n", strerror (errno));
+ return (1);
+ }
+
+ memset (node, 0, sizeof (fence_kdump_node_t));
+ memset (&hints, 0, sizeof (hints));
+
+ hints.ai_family = opts->family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_flags = AI_NUMERICSERV;
+
+ strncpy (node->name, opts->nodename, sizeof (node->name) - 1);
+ snprintf (node->port, sizeof (node->port), "%d", opts->ipport);
+
+ node->info = NULL;
+ error = getaddrinfo (node->name, node->port, &hints, &node->info);
+ if (error != 0) {
+ log_error (2, "getaddrinfo (%s)\n", gai_strerror (error));
+ free_node (node);
+ return (1);
+ }
+
+ error = getnameinfo (node->info->ai_addr, node->info->ai_addrlen,
+ node->addr, sizeof (node->addr),
+ node->port, sizeof (node->port),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ log_error (2, "getnameinfo (%s)\n", gai_strerror (error));
+ free_node (node);
+ return (1);
+ }
+
+ node->socket = socket (node->info->ai_family,
+ node->info->ai_socktype,
+ node->info->ai_protocol);
+ if (node->socket < 0) {
+ log_error (2, "socket (%s)\n", strerror (errno));
+ free_node (node);
+ return (1);
+ }
+
+ list_add_tail (&node->list, &opts->nodes);
+
+ return (0);
+}
+
+static void
+get_options (int argc, char **argv, fence_kdump_opts_t *opts)
+{
+ int opt;
+
+ struct option options[] = {
+ { "ipport", required_argument, NULL, 'p' },
+ { "family", required_argument, NULL, 'f' },
+ { "count", required_argument, NULL, 'c' },
+ { "interval", required_argument, NULL, 'i' },
+ { "verbose", optional_argument, NULL, 'v' },
+ { "version", no_argument, NULL, 'V' },
+ { "help", no_argument, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ while ((opt = getopt_long (argc, argv, "p:f:c:i:v::Vh", options, NULL)) != EOF) {
+ switch (opt) {
+ case 'p':
+ set_option_ipport (opts, optarg);
+ break;
+ case 'f':
+ set_option_family (opts, optarg);
+ break;
+ case 'c':
+ set_option_count (opts, optarg);
+ break;
+ case 'i':
+ set_option_interval (opts, optarg);
+ break;
+ case 'v':
+ set_option_verbose (opts, optarg);
+ break;
+ case 'V':
+ print_version (argv[0]);
+ exit (0);
+ case 'h':
+ print_usage (argv[0]);
+ exit (0);
+ default:
+ print_usage (argv[0]);
+ exit (1);
+ }
+ }
+
+ verbose = opts->verbose;
+
+ return;
+}
+
+int
+main (int argc, char **argv)
+{
+ int count = 1;
+ fence_kdump_msg_t msg;
+ fence_kdump_opts_t opts;
+ fence_kdump_node_t *node;
+
+ init_options (&opts);
+
+ if (argc > 1) {
+ get_options (argc, argv, &opts);
+ } else {
+ print_usage (argv[0]);
+ exit (1);
+ }
+
+ for (; optind < argc; optind++) {
+ opts.nodename = argv[optind];
+ if (get_options_node (&opts) != 0) {
+ log_error (1, "failed to get node '%s'\n", opts.nodename);
+ }
+ opts.nodename = NULL;
+ }
+
+ if (list_empty (&opts.nodes)) {
+ print_usage (argv[0]);
+ exit (1);
+ }
+
+ if (verbose != 0) {
+ print_options (&opts);
+ }
+
+ init_message (&msg);
+
+ for (;;) {
+ list_for_each_entry (node, &opts.nodes, list) {
+ send_message (node, &msg, sizeof (msg));
+ }
+
+ if ((opts.count != 0) && (++count > opts.count)) {
+ break;
+ }
+
+ sleep (opts.interval);
+ }
+
+ free_options (&opts);
+
+ return (0);
+}
diff --git a/agents/kdump/list.h b/agents/kdump/list.h
new file mode 100644
index 0000000..8945a62
--- /dev/null
+++ b/agents/kdump/list.h
@@ -0,0 +1,573 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#include <stddef.h>
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x00100100)
+#define LIST_POISON2 ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new,
+ struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new,
+ struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev,
+ struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void __list_del_entry(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del_entry(entry);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del_entry(list);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del_entry(list);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+
+ return (next == head) && (next == head->prev);
+}
+
+/**
+ * list_rotate_left - rotate the list to the left
+ * @head: the head of the list
+ */
+static inline void list_rotate_left(struct list_head *head)
+{
+ struct list_head *first;
+
+ if (!list_empty(head)) {
+ first = head->next;
+ list_move_tail(first, head);
+ }
+}
+
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+ return !list_empty(head) && (head->next == head->prev);
+}
+
+static inline void __list_cut_position(struct list_head *list,
+ struct list_head *head,
+ struct list_head *entry)
+{
+ struct list_head *new_first = entry->next;
+
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry;
+ entry->next = list;
+ head->next = new_first;
+ new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ * and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ */
+static inline void list_cut_position(struct list_head *list,
+ struct list_head *head,
+ struct list_head *entry)
+{
+ if (list_empty(head))
+ return;
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
+ return;
+ if (entry == head)
+ INIT_LIST_HEAD(list);
+ else
+ __list_cut_position(list, head, entry);
+}
+
+static inline void __list_splice(const struct list_head *list,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+
+ first->prev = prev;
+ prev->next = first;
+ last->next = next;
+ next->prev = last;
+}
+
+/**
+ * list_splice - join two lists, this is designed for stacks
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(const struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head->prev, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head, head->next);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head->prev, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue - continue list iteration safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from - iterate over list from current point safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+/**
+ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos: the loop cursor used in the list_for_each_entry_safe loop
+ * @n: temporary storage used in list_for_each_entry_safe
+ * @member: the name of the list_struct within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_safe_reset_next(pos, n, member) \
+ n = list_entry(pos->member.next, typeof(*pos), member)
+
+#endif /* _LINUX_LIST_H */
diff --git a/agents/kdump/message.h b/agents/kdump/message.h
new file mode 100644
index 0000000..2c82229
--- /dev/null
+++ b/agents/kdump/message.h
@@ -0,0 +1,41 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) Ryan O'Hara (rohara@redhat.com)
+ * Copyright (c) Red Hat, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _FENCE_KDUMP_MESSAGE_H
+#define _FENCE_KDUMP_MESSAGE_H
+
+#define FENCE_KDUMP_MAGIC 0x1B302A40
+
+#define FENCE_KDUMP_MSGV1 0x1
+
+typedef struct __attribute__ ((packed)) fence_kdump_msg {
+ uint32_t magic;
+ uint32_t version;
+} fence_kdump_msg_t;
+
+static inline void
+init_message (fence_kdump_msg_t *msg)
+{
+ msg->magic = FENCE_KDUMP_MAGIC;
+ msg->version = FENCE_KDUMP_MSGV1;
+}
+
+#endif /* _FENCE_KDUMP_MESSAGE_H */
diff --git a/agents/kdump/options.h b/agents/kdump/options.h
new file mode 100644
index 0000000..3cf7b43
--- /dev/null
+++ b/agents/kdump/options.h
@@ -0,0 +1,260 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) Ryan O'Hara (rohara@redhat.com)
+ * Copyright (c) Red Hat, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _FENCE_KDUMP_OPTIONS_H
+#define _FENCE_KDUMP_OPTIONS_H
+
+#include "list.h"
+
+#define FENCE_KDUMP_NAME_LEN 256
+#define FENCE_KDUMP_ADDR_LEN 46
+#define FENCE_KDUMP_PORT_LEN 6
+
+enum {
+ FENCE_KDUMP_ACTION_OFF = 0,
+ FENCE_KDUMP_ACTION_ON = 1,
+ FENCE_KDUMP_ACTION_REBOOT = 2,
+ FENCE_KDUMP_ACTION_STATUS = 3,
+ FENCE_KDUMP_ACTION_LIST = 4,
+ FENCE_KDUMP_ACTION_MONITOR = 5,
+ FENCE_KDUMP_ACTION_METADATA = 6,
+ FENCE_KDUMP_ACTION_VALIDATE = 7,
+};
+
+enum {
+ FENCE_KDUMP_FAMILY_AUTO = AF_UNSPEC,
+ FENCE_KDUMP_FAMILY_IPV6 = AF_INET6,
+ FENCE_KDUMP_FAMILY_IPV4 = AF_INET,
+};
+
+#define FENCE_KDUMP_DEFAULT_IPPORT 7410
+#define FENCE_KDUMP_DEFAULT_FAMILY 0
+#define FENCE_KDUMP_DEFAULT_ACTION 0
+#define FENCE_KDUMP_DEFAULT_COUNT 0
+#define FENCE_KDUMP_DEFAULT_INTERVAL 10
+#define FENCE_KDUMP_DEFAULT_TIMEOUT 60
+#define FENCE_KDUMP_DEFAULT_VERBOSE 0
+
+typedef struct fence_kdump_opts {
+ char *nodename;
+ int ipport;
+ int family;
+ int action;
+ int count;
+ int interval;
+ int timeout;
+ int verbose;
+ struct list_head nodes;
+} fence_kdump_opts_t;
+
+typedef struct fence_kdump_node {
+ char name[FENCE_KDUMP_NAME_LEN];
+ char addr[FENCE_KDUMP_ADDR_LEN];
+ char port[FENCE_KDUMP_PORT_LEN];
+ int socket;
+ struct addrinfo *info;
+ struct list_head list;
+} fence_kdump_node_t;
+
+static inline void
+init_node (fence_kdump_node_t *node)
+{
+ node->info = NULL;
+}
+
+static inline void
+free_node (fence_kdump_node_t *node)
+{
+ freeaddrinfo (node->info);
+ free (node);
+}
+
+static inline void
+print_node (const fence_kdump_node_t *node)
+{
+ fprintf (stdout, "[debug]: node { \n");
+ fprintf (stdout, "[debug]: name = %s\n", node->name);
+ fprintf (stdout, "[debug]: addr = %s\n", node->addr);
+ fprintf (stdout, "[debug]: port = %s\n", node->port);
+ fprintf (stdout, "[debug]: info = %p\n", node->info);
+ fprintf (stdout, "[debug]: } \n");
+}
+
+static inline void
+init_options (fence_kdump_opts_t *opts)
+{
+ opts->nodename = NULL;
+ opts->ipport = FENCE_KDUMP_DEFAULT_IPPORT;
+ opts->family = FENCE_KDUMP_DEFAULT_FAMILY;
+ opts->action = FENCE_KDUMP_DEFAULT_ACTION;
+ opts->count = FENCE_KDUMP_DEFAULT_COUNT;
+ opts->interval = FENCE_KDUMP_DEFAULT_INTERVAL;
+ opts->timeout = FENCE_KDUMP_DEFAULT_TIMEOUT;
+ opts->verbose = FENCE_KDUMP_DEFAULT_VERBOSE;
+
+ INIT_LIST_HEAD (&opts->nodes);
+}
+
+static inline void
+free_options (fence_kdump_opts_t *opts)
+{
+ fence_kdump_node_t *node;
+ fence_kdump_node_t *safe;
+
+ list_for_each_entry_safe (node, safe, &opts->nodes, list) {
+ list_del (&node->list);
+ free_node (node);
+ }
+
+ free (opts->nodename);
+}
+
+static inline void
+print_options (fence_kdump_opts_t *opts)
+{
+ fence_kdump_node_t *node;
+
+ fprintf (stdout, "[debug]: options { \n");
+ fprintf (stdout, "[debug]: nodename = %s\n", opts->nodename);
+ fprintf (stdout, "[debug]: ipport = %d\n", opts->ipport);
+ fprintf (stdout, "[debug]: family = %d\n", opts->family);
+ fprintf (stdout, "[debug]: count = %d\n", opts->count);
+ fprintf (stdout, "[debug]: interval = %d\n", opts->interval);
+ fprintf (stdout, "[debug]: timeout = %d\n", opts->timeout);
+ fprintf (stdout, "[debug]: verbose = %d\n", opts->verbose);
+ fprintf (stdout, "[debug]: } \n");
+
+ list_for_each_entry (node, &opts->nodes, list) {
+ print_node (node);
+ }
+}
+
+static inline void
+set_option_nodename (fence_kdump_opts_t *opts, const char *arg)
+{
+ if (opts->nodename != NULL) {
+ free (opts->nodename);
+ }
+
+ opts->nodename = strdup (arg);
+}
+
+static inline void
+set_option_ipport (fence_kdump_opts_t *opts, const char *arg)
+{
+ opts->ipport = atoi (arg);
+
+ if ((opts->ipport < 1) || (opts->ipport > 65535)) {
+ fprintf (stderr, "[error]: invalid ipport '%s'\n", arg);
+ exit (1);
+ }
+}
+
+static inline void
+set_option_family (fence_kdump_opts_t *opts, const char *arg)
+{
+ if (!strcasecmp (arg, "auto")) {
+ opts->family = FENCE_KDUMP_FAMILY_AUTO;
+ } else if (!strcasecmp (arg, "ipv6")) {
+ opts->family = FENCE_KDUMP_FAMILY_IPV6;
+ } else if (!strcasecmp (arg, "ipv4")) {
+ opts->family = FENCE_KDUMP_FAMILY_IPV4;
+ } else {
+ fprintf (stderr, "[error]: unsupported family '%s'\n", arg);
+ exit (1);
+ }
+}
+
+static inline void
+set_option_action (fence_kdump_opts_t *opts, const char *arg)
+{
+ if (!strcasecmp (arg, "off")) {
+ opts->action = FENCE_KDUMP_ACTION_OFF;
+ } else if (!strcasecmp (arg, "metadata")) {
+ opts->action = FENCE_KDUMP_ACTION_METADATA;
+ } else if (!strcasecmp (arg, "monitor")) {
+ opts->action = FENCE_KDUMP_ACTION_MONITOR;
+ } else if (!strcasecmp (arg, "validate-all")) {
+ opts->action = FENCE_KDUMP_ACTION_VALIDATE;
+ } else {
+ fprintf (stderr, "[error]: unsupported action '%s'\n", arg);
+ exit (1);
+ }
+}
+
+static inline void
+set_option_count (fence_kdump_opts_t *opts, const char *arg)
+{
+ opts->count = atoi (arg);
+
+ if (opts->count < 0) {
+ fprintf (stderr, "[error]: invalid count '%s'\n", arg);
+ exit (1);
+ }
+}
+
+static inline void
+set_option_interval (fence_kdump_opts_t *opts, const char *arg)
+{
+ opts->interval = atoi (arg);
+
+ if (opts->interval < 1) {
+ fprintf (stderr, "[error]: invalid interval '%s'\n", arg);
+ exit (1);
+ }
+}
+
+static inline void
+set_option_timeout (fence_kdump_opts_t *opts, const char *arg)
+{
+ opts->timeout = atoi (arg);
+
+ if (opts->timeout < 1) {
+ fprintf (stderr, "[error]: invalid timeout '%s'\n", arg);
+ exit (1);
+ }
+}
+
+static inline void
+set_option_verbose (fence_kdump_opts_t *opts, const char *arg)
+{
+ int i;
+
+ if (arg != NULL) {
+ if (isdigit(arg[0])) {
+ opts->verbose += atoi (arg);
+ } else {
+ opts->verbose += 1; /* initial -v */
+ for (i = 0; i < strlen(arg); i++) {
+ if (arg[i] == 'v') {
+ opts->verbose += 1;
+ } else {
+ fprintf (stderr, "[error]: invalid value '%c' for verbose\n", arg[i]);
+ return;
+ }
+ }
+ }
+ } else {
+ opts->verbose += 1;
+ }
+}
+
+#endif /* _FENCE_KDUMP_OPTIONS_H */
diff --git a/agents/kdump/version.h b/agents/kdump/version.h
new file mode 100644
index 0000000..ed178b1
--- /dev/null
+++ b/agents/kdump/version.h
@@ -0,0 +1,33 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright (c) Ryan O'Hara (rohara@redhat.com)
+ * Copyright (c) Red Hat, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _FENCE_KDUMP_VERSION_H
+#define _FENCE_KDUMP_VERSION_H
+
+#define FENCE_KDUMP_VERSION "0.1"
+
+static inline void
+print_version (const char *self)
+{
+ fprintf (stdout, "%s %s\n", basename (self), FENCE_KDUMP_VERSION);
+}
+
+#endif /* _FENCE_KDUMP_VERSION_H */
diff --git a/agents/kubevirt/fence_kubevirt.py b/agents/kubevirt/fence_kubevirt.py
new file mode 100755
index 0000000..8c27a03
--- /dev/null
+++ b/agents/kubevirt/fence_kubevirt.py
@@ -0,0 +1,154 @@
+#!@PYTHON@ -tt
+
+import sys
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, run_delay, EC_STATUS, EC_FETCH_VM_UUID
+
+try:
+ from kubernetes.client.exceptions import ApiException
+except ImportError:
+ logging.error("Couldn\'t import kubernetes.client.exceptions.ApiException - not found or not accessible")
+
+def _get_namespace(options):
+ from kubernetes import config
+
+ ns = options.get("--namespace")
+ if ns is None:
+ ns = config.kube_config.list_kube_config_contexts()[1]['context']['namespace']
+
+ return ns
+
+def get_nodes_list(conn, options):
+ logging.debug("Starting list/monitor operation")
+ result = {}
+ try:
+ apiversion = options.get("--apiversion")
+ namespace = _get_namespace(options)
+ include_uninitialized = True
+ vm_api = conn.resources.get(api_version=apiversion, kind='VirtualMachine')
+ vm_list = vm_api.get(namespace=namespace)
+ for vm in vm_list.items:
+ result[vm.metadata.name] = ("", None)
+ except Exception as e:
+ logging.error("Exception when calling VirtualMachine list: %s", e)
+ return result
+
+def get_power_status(conn, options):
+ logging.debug("Starting get status operation")
+ try:
+ apiversion = options.get("--apiversion")
+ namespace = _get_namespace(options)
+ name = options.get("--plug")
+ vmi_api = conn.resources.get(api_version=apiversion,
+ kind='VirtualMachineInstance')
+ vmi = vmi_api.get(name=name, namespace=namespace)
+ return translate_status(vmi.status.phase)
+ except ApiException as e:
+ if e.status == 404:
+ try:
+ vm_api = conn.resources.get(api_version=apiversion, kind='VirtualMachine')
+ vm = vm_api.get(name=name, namespace=namespace)
+ except ApiException as e:
+ logging.error("VM %s doesn't exist", name)
+ fail(EC_FETCH_VM_UUID)
+ return "off"
+ logging.error("Failed to get power status, with API Exception: %s", e)
+ fail(EC_STATUS)
+ except Exception as e:
+ logging.error("Failed to get power status, with Exception: %s", e)
+ fail(EC_STATUS)
+
+def translate_status(instance_status):
+ if instance_status == "Running":
+ return "on"
+ return "unknown"
+
+def set_power_status(conn, options):
+ logging.debug("Starting set status operation")
+ try:
+ apiversion= options.get("--apiversion")
+ namespace = _get_namespace(options)
+ name = options.get("--plug")
+ action = 'start' if options["--action"] == "on" else 'stop'
+ virtctl_vm_action(conn, action, namespace, name, apiversion)
+ except Exception as e:
+ logging.error("Failed to set power status, with Exception: %s", e)
+ fail(EC_STATUS)
+
+def define_new_opts():
+ all_opt["namespace"] = {
+ "getopt" : ":",
+ "longopt" : "namespace",
+ "help" : "--namespace=[namespace] Namespace of the KubeVirt machine",
+ "shortdesc" : "Namespace of the KubeVirt machine.",
+ "required" : "0",
+ "order" : 2
+ }
+ all_opt["kubeconfig"] = {
+ "getopt" : ":",
+ "longopt" : "kubeconfig",
+ "help" : "--kubeconfig=[kubeconfig] Kubeconfig file path",
+ "shortdesc": "Kubeconfig file path",
+ "required": "0",
+ "order": 4
+ }
+ all_opt["apiversion"] = {
+ "getopt" : ":",
+ "longopt" : "apiversion",
+ "help" : "--apiversion=[apiversion] Version of the KubeVirt API",
+ "shortdesc" : "Version of the KubeVirt API.",
+ "required" : "0",
+ "default" : "kubevirt.io/v1",
+ "order" : 5
+ }
+
+def virtctl_vm_action(conn, action, namespace, name, apiversion):
+ path = '/apis/subresources.{api_version}/namespaces/{namespace}/virtualmachines/{name}/{action}'
+ path = path.format(api_version=apiversion, namespace=namespace, name=name, action=action)
+ return conn.request('put', path, header_params={'accept': '*/*'})
+
+# Main agent method
+def main():
+ conn = None
+
+ device_opt = ["port", "namespace", "kubeconfig", "ssl_insecure", "no_password", "apiversion"]
+
+ atexit.register(atexit_handler)
+ define_new_opts()
+
+ all_opt["power_timeout"]["default"] = "40"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for KubeVirt"
+ docs["longdesc"] = "fence_kubevirt is an I/O Fencing agent for KubeVirt."
+ docs["vendorurl"] = "https://kubevirt.io/"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # Disable insecure-certificate-warning message
+ if "--ssl-insecure" in options:
+ import urllib3
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+ try:
+ from kubernetes import config
+ from openshift.dynamic import DynamicClient
+ kubeconfig = options.get('--kubeconfig')
+ k8s_client = config.new_client_from_config(config_file=kubeconfig)
+ conn = DynamicClient(k8s_client)
+ except ImportError:
+ logging.error("Couldn\'t import kubernetes.config or "
+ "openshift.dynamic.DynamicClient - not found or not accessible")
+
+ # Operate the fencing device
+ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ldom/fence_ldom.py b/agents/ldom/fence_ldom.py
new file mode 100644
index 0000000..0cb3320
--- /dev/null
+++ b/agents/ldom/fence_ldom.py
@@ -0,0 +1,102 @@
+#!@PYTHON@ -tt
+
+##
+## The Following Agent Has Been Tested On - LDOM 1.0.3
+## The interface is backward compatible so it will work
+## with 1.0, 1.0.1 and .2 too.
+##
+#####
+
+import sys, re, pexpect
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage
+
+COMMAND_PROMPT_REG = r"\[PEXPECT\]$"
+COMMAND_PROMPT_NEW = "[PEXPECT]"
+
+# Start comunicating after login. Prepare good environment.
+def start_communication(conn, options):
+ conn.send_eol("PS1='" + COMMAND_PROMPT_NEW + "'")
+ res = conn.expect([pexpect.TIMEOUT, COMMAND_PROMPT_REG], int(options["--shell-timeout"]))
+ if res == 0:
+ #CSH stuff
+ conn.send_eol("set prompt='" + COMMAND_PROMPT_NEW + "'")
+ conn.log_expect(COMMAND_PROMPT_REG, int(options["--shell-timeout"]))
+
+def get_power_status(conn, options):
+ start_communication(conn, options)
+
+ conn.send_eol("ldm ls")
+
+ conn.log_expect(COMMAND_PROMPT_REG, int(options["--shell-timeout"]))
+
+ result = {}
+
+ #This is status of mini finite automata. 0 = we didn't found NAME and STATE, 1 = we did
+ fa_status = 0
+
+ for line in conn.before.splitlines():
+ domain = re.search(r"^(\S+)\s+(\S+)\s+.*$", line)
+
+ if domain != None:
+ if fa_status == 0 and domain.group(1) == "NAME" and domain.group(2) == "STATE":
+ fa_status = 1
+ elif fa_status == 1:
+ result[domain.group(1)] = ("", (domain.group(2).lower() == "bound" and "off" or "on"))
+
+ if not options["--action"] in ['monitor', 'list']:
+ if not options["--plug"] in result:
+ fail_usage("Failed: You have to enter existing logical domain!")
+ else:
+ return result[options["--plug"]][1]
+ else:
+ return result
+
+def set_power_status(conn, options):
+ start_communication(conn, options)
+
+ cmd_line = "ldm "+ (options["--action"] == "on" and "start" or "stop -f") + " \"" + options["--plug"] + "\""
+
+ conn.send_eol(cmd_line)
+
+ conn.log_expect(COMMAND_PROMPT_REG, int(options["--power-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", "port"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["secure"]["default"] = "1"
+ all_opt["cmd_prompt"]["default"] = [r"\ $"]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Sun LDOM"
+ docs["longdesc"] = "fence_ldom is an I/O Fencing agent \
+which can be used with LDoms virtual machines. This agent works \
+so, that run ldm command on host machine. So ldm must be directly \
+runnable.\
+\n.P\n\
+Very useful parameter is -c (or cmd_prompt in stdin mode). This \
+must be set to something, what is displayed after successful login \
+to host machine. Default string is space on end of string (default \
+for root in bash). But (for example) csh use ], so in that case you \
+must use parameter -c with argument ]. Very similar situation is, \
+if you use bash and login to host machine with other user than \
+root. Than prompt is $, so again, you must use parameter -c."
+ docs["vendorurl"] = "http://www.sun.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ fence_logout(conn, "logout")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/lindy_pdu/fence_lindypdu.py b/agents/lindy_pdu/fence_lindypdu.py
new file mode 100644
index 0000000..432b741
--- /dev/null
+++ b/agents/lindy_pdu/fence_lindypdu.py
@@ -0,0 +1,206 @@
+#!@PYTHON@ -tt
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# The Following agent has been tested on:
+# Lindy PDU model 32657
+# Firmware release s4.82-091012-1cb08s
+# Probably works on different models with same MIB .. but is better test on them
+#
+# (C) 2021 Daimonlab -- Damiano Scaramuzza (cesello) cesello@daimonlab.it
+
+import sys
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage
+from fencing_snmp import FencingSnmp
+
+### CONSTANTS ###
+# oid defining fence device
+OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0'
+
+### GLOBAL VARIABLES ###
+# Device - see Lindy PDU
+device = None
+
+# Port ID
+port_id = None
+# Switch ID
+switch_id = None
+
+# Classes describing Device params
+# Here I follow the MIBS specs that use "switch" and "plug" concepts but
+# the pdu really have one switch only and 8-16 plugs.
+# Probably the "switch" term is used for future uses or more advanced pdus
+class LindyPDU(object):
+ # PDU
+ status_oid = '.1.3.6.1.4.1.17420.1.2.9.%d.13.0'
+ control_oid = '.1.3.6.1.4.1.17420.1.2.9.%d.13.0'
+ outlet_table_oid = '.1.3.6.1.4.1.17420.1.2.9.%d.14'
+ pdu_table_oid = '.1.3.6.1.4.1.17420.1.2.9'
+ attached_pdus = '.1.3.6.1.4.1.17420.1.2.5.0'
+ ident_str = "Lindy 32657 PDU"
+ state_on = 1
+ state_off = 0
+ turn_on = 1
+ turn_off = 0
+ has_switches = True
+
+### FUNCTIONS ###
+def lpdu_set_device(conn, options):
+ global device
+
+ agents_dir = {'.1.3.6.1.4.1.17420':LindyPDU}
+
+ # First resolve type of PDU device
+ pdu_type = conn.walk(OID_SYS_OBJECT_ID)
+
+ if not ((len(pdu_type) == 1) and (pdu_type[0][1] in agents_dir)):
+ pdu_type = [[None, None]]
+
+ device = agents_dir[pdu_type[0][1]]
+
+ logging.debug("Trying %s"%(device.ident_str))
+
+def lpdu_resolv_port_id(conn, options):
+
+ if device == None:
+ lpdu_set_device(conn, options)
+
+ port_id=switch_id=None
+ # Now we resolv port_id/switch_id
+ if options["--plug"].isdigit() and ((not device.has_switches) or (options["--switch"].isdigit())):
+ port_id = int(options["--plug"])
+
+ if device.has_switches:
+ switch_id = int(options["--switch"])
+ else:
+ table = conn.walk(device.pdu_table_oid, 30)
+
+ for x in table:
+ if x[1].strip('"').split(',')[0] == options["--plug"]:
+ t = x[0].split('.')
+ if device.has_switches:
+ port_id = int(t[len(t)-1])
+ switch_id = int(t[len(t)-3])
+ else:
+ port_id = int(t[len(t)-1])
+
+ if port_id == None:
+ fail_usage("Can't find port with name %s!"%(options["--plug"]))
+
+ return (switch_id,port_id)
+
+def get_power_status(conn, options):
+
+ (switch_id,port_id)=lpdu_resolv_port_id(conn, options)
+
+ oid = ((device.has_switches) and device.status_oid%(switch_id) or device.status_oid%(port_id))
+
+
+ try:
+ (oid, status) = conn.get(oid)
+ # status is a comma separated string
+ # one line only as "1,1,1,0,1,1,1,1".
+ state=status.strip('"').split(',')[port_id-1]
+ if state == str(device.state_on):
+ return "on"
+ elif state == str(device.state_off):
+ return "off"
+ else:
+ return None
+ except Exception:
+ return None
+
+def set_power_status(conn, options):
+
+ (switch_id,port_id)=lpdu_resolv_port_id(conn, options)
+
+ oid = ((device.has_switches) and device.control_oid%(switch_id) or device.control_oid%(port_id))
+
+ (oid, status) = conn.get(oid)
+ # status is a comma separated string
+ state=status.strip('"').split(',')
+ state[port_id-1]=str((options["--action"] == "on" and device.turn_on or device.turn_off))
+ conn.set(oid, ",".join(state))
+
+
+def get_outlets_status(conn, options):
+ result = {}
+ pdu_id=[]
+
+ if device == None:
+ lpdu_set_device(conn, options)
+
+ if (device.has_switches and options["--switch"].isdigit()):
+ pdu_id.append(options["--switch"])
+
+ elif (device.has_switches):
+ #search for all pdu
+ pdus=conn.walk(device.attached_pdus, 30)
+ pdus_info=pdus[0][1].strip('"').split(',')
+ pdu_id=pdus_info[1:]
+ else:
+ #I really don't know what to do with this case. I haven't a different lindy pdu to test
+ table_oid=device.pdu_table_oid
+
+
+ for switch in pdu_id:
+ table_oid = device.outlet_table_oid % int(switch)
+ res_ports = conn.walk(table_oid, 30)
+ status_oid=device.status_oid % int(switch)
+ port_status=conn.walk(status_oid, 30)
+ state=port_status[0][1].strip('"').split(',')
+ for x in res_ports:
+ t = x[0].split('.')
+ port_num = ((device.has_switches) and "%s:%s"%(t[len(t)-4], t[len(t)-2]) or "%s"%(t[len(t)-2]))
+ port_name = x[1].strip('"').split(',')[0]
+ result[port_num] = (port_name, "on" if state[int(t[len(t)-2])-1]=='1' else "off")
+
+ return result
+
+# Main agent method
+def main():
+ global device
+
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "port", "snmp_version", "snmp","switch"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["snmp_version"]["default"] = "1"
+ all_opt["community"]["default"] = "public"
+ all_opt["switch"]["default"] = "1"
+ device = LindyPDU
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Lindy over SNMP"
+ docs["longdesc"] = "fence_lindypdu is an I/O Fencing agent \
+which can be used with the Lindy PDU network power switch. It logs \
+into a device via SNMP and reboots a specified outlet. It supports \
+SNMP v1 with all combinations of authenticity/privacy settings."
+ docs["vendorurl"] = "http://www.lindy.co.uk"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+if __name__ == "__main__":
+ main()
diff --git a/agents/lpar/fence_lpar.py b/agents/lpar/fence_lpar.py
new file mode 100644
index 0000000..975971a
--- /dev/null
+++ b/agents/lpar/fence_lpar.py
@@ -0,0 +1,197 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Version
+## +---------------------------------------------+
+## Tested on HMC
+##
+#####
+
+import sys, re
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, EC_STATUS_HMC
+
+##
+## Transformation to standard ON/OFF status if possible
+def _normalize_status(status):
+ if status in ["Running", "Open Firmware", "Shutting Down", "Starting"]:
+ status = "on"
+ else:
+ status = "off"
+
+ return status
+
+def get_power_status(conn, options):
+ if options["--hmc-version"] == "3":
+ command = "lssyscfg -r lpar -m " + options["--managed"] + " -n " + options["--plug"] + " -F name,state\n"
+ elif options["--hmc-version"] in ["4", "IVM"]:
+ command = "lssyscfg -r lpar -m "+ options["--managed"] + \
+ " --filter 'lpar_names=" + options["--plug"] + "'\n"
+ else:
+ # Bad HMC Version cannot be reached
+ fail(EC_STATUS_HMC)
+
+ conn.send(command)
+ # First line (command) may cause parsing issues if long
+ conn.readline()
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ try:
+ if options["--hmc-version"] == "3":
+ status = re.compile("^" + options["--plug"] + ",(.*?),.*$",
+ re.IGNORECASE | re.MULTILINE).search(conn.before).group(1)
+ elif options["--hmc-version"] in ["4", "IVM"]:
+ status = re.compile(",state=(.*?),", re.IGNORECASE).search(conn.before).group(1)
+ except AttributeError as e:
+ logging.debug("Command on HMC failed: {}\n{}".format(command, str(e)))
+ fail(EC_STATUS_HMC)
+
+ return _normalize_status(status)
+
+def is_comanaged(conn, options):
+ conn.send("lscomgmt -m " + options["--managed"] + "\n" )
+ conn.readline()
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ try:
+ cm = re.compile(",curr_master_mtms=(.*?),", re.IGNORECASE).search(conn.before).group(1)
+ except AttributeError as e:
+ cm = False
+
+ return cm
+
+def set_power_status(conn, options):
+ if options["--hmc-version"] == "3":
+ conn.send("chsysstate -o " + options["--action"] + " -r lpar -m " + options["--managed"]
+ + " -n " + options["--plug"] + "\n")
+
+ # First line (command) may cause parsing issues if long
+ conn.readline()
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ elif options["--hmc-version"] in ["4", "IVM"]:
+ if options["--action"] == "on":
+ if is_comanaged(conn, options):
+ profile = ""
+ else:
+ profile = " -f `lssyscfg -r lpar -F curr_profile " + \
+ " -m " + options["--managed"] + \
+ " --filter \"lpar_names=" + options["--plug"] + "\"`"
+ conn.send("chsysstate -o on -r lpar" +
+ " -m " + options["--managed"] +
+ " -n " + options["--plug"] +
+ profile +
+ "\n")
+ else:
+ conn.send("chsysstate -o shutdown -r lpar --immed" +
+ " -m " + options["--managed"] + " -n " + options["--plug"] + "\n")
+
+ # First line (command) may cause parsing issues if long
+ conn.readline()
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def get_lpar_list(conn, options):
+ outlets = {}
+ if options["--hmc-version"] == "3":
+ conn.send("query_partition_names -m " + options["--managed"] + "\n")
+
+ ## We have to remove first line (command)
+ conn.readline()
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ ## We have to remove next 2 lines (header) and last line (part of new prompt)
+ ####
+ res = re.search("^(.+?\n){2}(.*)\n.*$", conn.before, re.S)
+
+ if res == None:
+ fail_usage("Unable to parse output of list command")
+
+ lines = res.group(2).split("\n")
+ for outlet_line in lines:
+ outlets[outlet_line.rstrip()] = ("", "")
+ elif options["--hmc-version"] in ["4", "IVM"]:
+ sep = ":" if options["--hmc-version"] == "4" else ","
+
+ conn.send("lssyscfg -r lpar -m " + options["--managed"] +
+ " -F name" + sep + "state\n")
+
+ ## We have to remove first line (command)
+ conn.readline()
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+ ## We have to remove last line (part of new prompt)
+ ####
+ res = re.search("^(.*)\n.*$", conn.before, re.S)
+
+ if res == None:
+ fail_usage("Unable to parse output of list command")
+
+ lines = res.group(1).split("\n")
+ for outlet_line in lines:
+ try:
+ (port, status) = outlet_line.rstrip().split(sep)
+ except ValueError:
+ fail_usage('Output does not match expected HMC version, try different one');
+ outlets[port] = ("", _normalize_status(status))
+
+ return outlets
+
+def define_new_opts():
+ all_opt["managed"] = {
+ "getopt" : "s:",
+ "longopt" : "managed",
+ "help" : "-s, --managed=[id] Name of the managed system",
+ "required" : "1",
+ "shortdesc" : "Managed system name",
+ "order" : 1}
+ all_opt["hmc_version"] = {
+ "getopt" : "H:",
+ "longopt" : "hmc-version",
+ "help" : "-H, --hmc-version=[version] Force HMC version to use: (3|4|ivm) (default: 4)",
+ "required" : "0",
+ "shortdesc" : "Force HMC version to use",
+ "default" : "4",
+ "choices" : ["3", "4", "ivm"],
+ "order" : 1}
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", \
+ "port", "managed", "hmc_version"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["login_timeout"]["default"] = "15"
+ all_opt["secure"]["default"] = "1"
+ all_opt["cmd_prompt"]["default"] = [r":~>", r"]\$", r"\$ "]
+
+ options = check_input(device_opt, process_input(device_opt), other_conditions = True)
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM LPAR"
+ docs["longdesc"] = ""
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ if "--managed" not in options:
+ fail_usage("Failed: You have to enter name of managed system")
+
+ if options["--action"] == "validate-all":
+ sys.exit(0)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_lpar_list)
+ fence_logout(conn, "quit\r\n")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/manual/fence_ack_manual.8 b/agents/manual/fence_ack_manual.8
new file mode 100644
index 0000000..6b4cd14
--- /dev/null
+++ b/agents/manual/fence_ack_manual.8
@@ -0,0 +1,39 @@
+.TH FENCE_ACK_MANUAL 8 2009-12-21 cluster cluster
+
+.SH NAME
+fence_ack_manual \- a program to override fenced fencing operations
+
+.SH SYNOPSIS
+.B fence_ack_manual
+[OPTIONS]
+.I nodename
+
+.SH DESCRIPTION
+When
+.BR fenced (8)
+fails to fence a node, it retries indefinately.
+.BR fence_ack_manual (8)
+tells fenced to stop retrying and consider the node fenced.
+
+.P
+It is important that this only be done after the node has been manually
+turned off or prevented from writing to shared storage.
+Without this manual action and verification, the storage that fencing
+protects may become corrupted.
+
+.P
+When fenced fences a node that has no fence devices defined in the cluster
+configuration, the fencing operation fails. This failure will be repeated
+indefinately until fence_ack_manual is run by an operator to indicate
+the node is in a safe state to proceed.
+(Defining no fencing devices for node is the equivalent of using the
+fence_manual agent in previous versions.)
+
+.SH OPTIONS
+.TP
+.B \-h
+Print a help message describing available options, then exit.
+
+.SH SEE ALSO
+.BR fenced (8)
+
diff --git a/agents/manual/fence_ack_manual.in b/agents/manual/fence_ack_manual.in
new file mode 100644
index 0000000..e8b4998
--- /dev/null
+++ b/agents/manual/fence_ack_manual.in
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Manual override after fencing has failed.
+#
+
+if [ "$1" = "-n" ]; then
+ shift
+fi
+
+if [ -z "$1" ] || [ "${1:0:1}" = "-" ]; then
+ echo "usage:"
+ echo " $0 <nodename>"
+ echo " $0 -n <nodename>"
+ echo
+ echo "The -n flag exists to preserve compatibility with previous "
+ echo "releases of $0, and is no longer required."
+ exit 1
+fi
+
+declare answer
+
+echo "About to override fencing for $1."
+echo "Improper use of this command can cause severe file system damage."
+echo
+read -p "Continue [NO/absolutely]? " answer
+
+if [ "$answer" != "absolutely" ]; then
+ echo "Aborted."
+ exit 1
+fi
+
+while ! [ -e @clustervarrun@/fenced_override ]; do
+ sleep 1
+done
+
+echo $1>@clustervarrun@/fenced_override
+echo Done
diff --git a/agents/mpath/fence_mpath.py b/agents/mpath/fence_mpath.py
new file mode 100644
index 0000000..ee81eab
--- /dev/null
+++ b/agents/mpath/fence_mpath.py
@@ -0,0 +1,341 @@
+#!@PYTHON@ -tt
+
+import sys
+import stat
+import re
+import os
+import time
+import logging
+import atexit
+import ctypes
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import fail_usage, run_command, atexit_handler, check_input, process_input, show_docs
+from fencing import fence_action, all_opt, run_delay
+
+def get_status(conn, options):
+ del conn
+ status = "off"
+ for dev in options["devices"]:
+ is_block_device(dev)
+ if options["--plug"] in get_registration_keys(options, dev):
+ status = "on"
+ else:
+ logging.debug("No registration for key "\
+ + options["--plug"] + " on device " + dev + "\n")
+
+ if options["--action"] == "monitor":
+ dev_read(options)
+
+ return status
+
+
+def set_status(conn, options):
+ del conn
+ count = 0
+ if options["--action"] == "on":
+ for dev in options["devices"]:
+ is_block_device(dev)
+
+ register_dev(options, dev)
+ if options["--plug"] not in get_registration_keys(options, dev):
+ count += 1
+ logging.debug("Failed to register key "\
+ + options["--plug"] + "on device " + dev + "\n")
+ continue
+ dev_write(options, dev)
+
+ if get_reservation_key(options, dev) is None \
+ and not reserve_dev(options, dev) \
+ and get_reservation_key(options, dev) is None:
+ count += 1
+ logging.debug("Failed to create reservation (key="\
+ + options["--plug"] + ", device=" + dev + ")\n")
+
+ else:
+ dev_keys = dev_read(options)
+
+ for dev in options["devices"]:
+ is_block_device(dev)
+
+ if options["--plug"] in get_registration_keys(options, dev):
+ preempt_abort(options, dev_keys[dev], dev)
+
+ for dev in options["devices"]:
+ if options["--plug"] in get_registration_keys(options, dev):
+ count += 1
+ logging.debug("Failed to remove key "\
+ + options["--plug"] + " on device " + dev + "\n")
+ continue
+
+ if not get_reservation_key(options, dev):
+ count += 1
+ logging.debug("No reservation exists on device " + dev + "\n")
+ if count:
+ logging.error("Failed to verify " + str(count) + " device(s)")
+ sys.exit(1)
+
+
+# run command, returns dict, ret["rc"] = exit code; ret["out"] = output;
+# ret["err"] = error
+def run_cmd(options, cmd):
+ ret = {}
+
+ if "--use-sudo" in options:
+ prefix = options["--sudo-path"] + " "
+ else:
+ prefix = ""
+
+ (ret["rc"], ret["out"], ret["err"]) = run_command(options,
+ prefix + cmd)
+ ret["out"] = "".join([i for i in ret["out"] if i is not None])
+ ret["err"] = "".join([i for i in ret["err"] if i is not None])
+ return ret
+
+
+# check if device exist and is block device
+def is_block_device(dev):
+ if not os.path.exists(dev):
+ fail_usage("Failed: device \"" + dev + "\" does not exist")
+ if not stat.S_ISBLK(os.stat(dev).st_mode):
+ fail_usage("Failed: device \"" + dev + "\" is not a block device")
+
+# cancel registration
+def preempt_abort(options, host, dev):
+ cmd = options["--mpathpersist-path"] + " -o --preempt-abort --prout-type=5 --param-rk=" + host +" --param-sark=" + options["--plug"] +" -d " + dev
+ return not bool(run_cmd(options, cmd)["rc"])
+
+def register_dev(options, dev):
+ cmd = options["--mpathpersist-path"] + " -o --register --param-sark=" + options["--plug"] + " -d " + dev
+ #cmd return code != 0 but registration can be successful
+ return not bool(run_cmd(options, cmd)["rc"])
+
+def reserve_dev(options, dev):
+ cmd = options["--mpathpersist-path"] + " -o --reserve --prout-type=5 --param-rk=" + options["--plug"] + " -d " + dev
+ return not bool(run_cmd(options, cmd)["rc"])
+
+def get_reservation_key(options, dev):
+ cmd = options["--mpathpersist-path"] + " -i -r -d " + dev
+ out = run_cmd(options, cmd)
+ if out["rc"]:
+ fail_usage('Cannot get reservation key on device "' + dev
+ + '": ' + out["err"])
+ match = re.search(r"\s+key\s*=\s*0x(\S+)\s+", out["out"], re.IGNORECASE)
+ return match.group(1) if match else None
+
+def get_registration_keys(options, dev, fail=True):
+ keys = []
+ cmd = options["--mpathpersist-path"] + " -i -k -d " + dev
+ out = run_cmd(options, cmd)
+ if out["rc"]:
+ fail_usage('Cannot get registration keys on device "' + dev
+ + '": ' + out["err"], fail)
+ if not fail:
+ return []
+ for line in out["out"].split("\n"):
+ match = re.search(r"\s+0x(\S+)\s*", line)
+ if match:
+ keys.append(match.group(1))
+ return keys
+
+def dev_write(options, dev):
+ file_path = options["--store-path"] + "/mpath.devices"
+
+ if not os.path.isdir(options["--store-path"]):
+ os.makedirs(options["--store-path"])
+
+ try:
+ store_fh = open(file_path, "a+")
+ except IOError:
+ fail_usage("Failed: Cannot open file \""+ file_path + "\"")
+ out = store_fh.read()
+ if not re.search(r"^" + dev + r"\s+", out):
+ store_fh.write(dev + "\t" + options["--plug"] + "\n")
+ store_fh.close()
+
+def dev_read(options, fail=True):
+ dev_key = {}
+ file_path = options["--store-path"] + "/mpath.devices"
+ try:
+ store_fh = open(file_path, "r")
+ except IOError:
+ if fail:
+ fail_usage("Failed: Cannot open file \"" + file_path + "\"")
+ else:
+ return None
+ # get not empty lines from file
+ for (device, key) in [line.strip().split() for line in store_fh if line.strip()]:
+ dev_key[device] = key
+ store_fh.close()
+ return dev_key
+
+def mpath_check_get_options(options):
+ try:
+ f = open("/etc/sysconfig/stonith", "r")
+ except IOError:
+ return options
+
+ match = re.findall(r"^\s*(\S*)\s*=\s*(\S*)\s*", "".join(f.readlines()), re.MULTILINE)
+
+ for m in match:
+ options[m[0].lower()] = m[1].lower()
+
+ f.close()
+
+ return options
+
+def mpath_check(hardreboot=False):
+ if len(sys.argv) >= 3 and sys.argv[1] == "repair":
+ return int(sys.argv[2])
+ options = {}
+ options["--mpathpersist-path"] = "/usr/sbin/mpathpersist"
+ options["--store-path"] = "@STORE_PATH@"
+ options["--power-timeout"] = "5"
+ options["retry"] = "0"
+ options["retry-sleep"] = "1"
+ options = mpath_check_get_options(options)
+ if "verbose" in options and options["verbose"] == "yes":
+ logging.getLogger().setLevel(logging.DEBUG)
+ devs = dev_read(options, fail=False)
+ if not devs:
+ if "--suppress-errors" not in options:
+ logging.error("No devices found")
+ return 0
+ for dev, key in list(devs.items()):
+ for n in range(int(options["retry"]) + 1):
+ if n > 0:
+ logging.debug("retry: " + str(n) + " of " + options["retry"])
+ if key in get_registration_keys(options, dev, fail=False):
+ logging.debug("key " + key + " registered with device " + dev)
+ return 0
+ else:
+ logging.debug("key " + key + " not registered with device " + dev)
+
+ if n < int(options["retry"]):
+ time.sleep(float(options["retry-sleep"]))
+ logging.debug("key " + key + " registered with any devices")
+
+ if hardreboot == True:
+ libc = ctypes.cdll['libc.so.6']
+ libc.reboot(0x1234567)
+ return 2
+
+def define_new_opts():
+ all_opt["devices"] = {
+ "getopt" : "d:",
+ "longopt" : "devices",
+ "help" : "-d, --devices=[devices] List of devices to use for current operation",
+ "required" : "0",
+ "shortdesc" : "List of devices to use for current operation. Devices can \
+be comma-separated list of device-mapper multipath devices (eg. /dev/mapper/3600508b400105df70000e00000ac0000 or /dev/mapper/mpath1). \
+Each device must support SCSI-3 persistent reservations.",
+ "order": 1
+ }
+ all_opt["key"] = {
+ "getopt" : "k:",
+ "longopt" : "key",
+ "help" : "-k, --key=[key] Replaced by -n, --plug",
+ "required" : "0",
+ "shortdesc" : "Replaced by port/-n/--plug",
+ "order": 1
+ }
+ all_opt["suppress-errors"] = {
+ "getopt" : "",
+ "longopt" : "suppress-errors",
+ "help" : "--suppress-errors Suppress error log. Suppresses error logging when run from the watchdog service before pacemaker starts.",
+ "required" : "0",
+ "shortdesc" : "Error log suppression.",
+ "order": 4
+ }
+ all_opt["mpathpersist_path"] = {
+ "getopt" : ":",
+ "longopt" : "mpathpersist-path",
+ "help" : "--mpathpersist-path=[path] Path to mpathpersist binary",
+ "required" : "0",
+ "shortdesc" : "Path to mpathpersist binary",
+ "default" : "@MPATH_PATH@",
+ "order": 200
+ }
+ all_opt["store_path"] = {
+ "getopt" : ":",
+ "longopt" : "store-path",
+ "help" : "--store-path=[path] Path to directory containing cached keys",
+ "required" : "0",
+ "shortdesc" : "Path to directory where fence agent can store information",
+ "default" : "@STORE_PATH@",
+ "order": 200
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["no_login", "no_password", "devices", "key", "sudo", \
+ "fabric_fencing", "on_target", "store_path", \
+ "suppress-errors", "mpathpersist_path", "force_on", "port", "no_port"]
+
+ define_new_opts()
+
+ all_opt["port"]["required"] = "0"
+ all_opt["port"]["help"] = "-n, --plug=[key] Key to use for the current operation"
+ all_opt["port"]["shortdesc"] = "Key to use for the current operation. \
+This key should be unique to a node and have to be written in \
+/etc/multipath.conf. For the \"on\" action, the key specifies the key use to \
+register the local node. For the \"off\" action, this key specifies the key to \
+be removed from the device(s)."
+
+ # fence_mpath_check
+ if os.path.basename(sys.argv[0]) == "fence_mpath_check":
+ sys.exit(mpath_check())
+ elif os.path.basename(sys.argv[0]) == "fence_mpath_check_hardreboot":
+ sys.exit(mpath_check(hardreboot=True))
+
+ options = check_input(device_opt, process_input(device_opt), other_conditions=True)
+
+ # hack to remove list/list-status actions which are not supported
+ options["device_opt"] = [ o for o in options["device_opt"] if o != "separator" ]
+
+ # workaround to avoid regressions
+ if "--key" in options:
+ options["--plug"] = options["--key"]
+ del options["--key"]
+ elif "--help" not in options and options["--action"] in ["off", "on", \
+ "reboot", "status", "validate-all"] and "--plug" not in options:
+ stop_after_error = False if options["--action"] == "validate-all" else True
+ fail_usage("Failed: You have to enter plug number or machine identification", stop_after_error)
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for multipath persistent reservation"
+ docs["longdesc"] = "fence_mpath is an I/O fencing agent that uses SCSI-3 \
+persistent reservations to control access multipath devices. Underlying \
+devices must support SCSI-3 persistent reservations (SPC-3 or greater) as \
+well as the \"preempt-and-abort\" subcommand.\nThe fence_mpath agent works by \
+having a unique key for each node that has to be set in /etc/multipath.conf. \
+Once registered, a single node will become the reservation holder \
+by creating a \"write exclusive, registrants only\" reservation on the \
+device(s). The result is that only registered nodes may write to the \
+device(s). When a node failure occurs, the fence_mpath agent will remove the \
+key belonging to the failed node from the device(s). The failed node will no \
+longer be able to write to the device(s). A manual reboot is required.\
+\n.P\n\
+When used as a watchdog device you can define e.g. retry=1, retry-sleep=2 and \
+verbose=yes parameters in /etc/sysconfig/stonith if you have issues with it \
+failing."
+ docs["vendorurl"] = "https://www.sourceware.org/dm/"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # Input control BEGIN
+ if options["--action"] == "validate-all":
+ sys.exit(0)
+
+ if not ("--devices" in options and options["--devices"]):
+ fail_usage("Failed: No devices found")
+
+ options["devices"] = [d for d in re.split("\s*,\s*|\s+", options["--devices"].strip()) if d]
+ # Input control END
+
+ result = fence_action(None, options, set_status, get_status)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/netio/fence_netio.py b/agents/netio/fence_netio.py
new file mode 100755
index 0000000..4fb59cf
--- /dev/null
+++ b/agents/netio/fence_netio.py
@@ -0,0 +1,94 @@
+#!@PYTHON@ -tt
+
+import sys, re, pexpect
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fspawn, fail, EC_LOGIN_DENIED, run_delay
+
+def get_power_status(conn, options):
+ conn.send_eol("port %s" % options["--plug"])
+ re_status = re.compile("250 [01imt]")
+ conn.log_expect(re_status, int(options["--shell-timeout"]))
+ status = {
+ "0" : "off",
+ "1" : "on",
+ "i" : "reboot",
+ "m" : "manual",
+ "t" : "timer"
+ }[conn.after.split()[1]]
+
+ return status
+
+def set_power_status(conn, options):
+ action = {
+ "on" : "1",
+ "off" : "0",
+ "reboot" : "i"
+ }[options["--action"]]
+
+ conn.send_eol("port %s %s" % (options["--plug"], action))
+ conn.log_expect("250 OK", int(options["--shell-timeout"]))
+
+def get_outlet_list(conn, options):
+ result = {}
+
+ try:
+ # the NETIO-230B has 4 ports, counting start at 1
+ for plug in ["1", "2", "3", "4"]:
+ conn.send_eol("port setup %s" % plug)
+ conn.log_expect("250 .+", int(options["--shell-timeout"]))
+ # the name is enclosed in "", drop those with [1:-1]
+ name = conn.after.split()[1][1:-1]
+ result[plug] = (name, "unknown")
+ except Exception as exn:
+ print(str(exn))
+
+ return result
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "port", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["ipport"]["default"] = "1234"
+
+ opt = process_input(device_opt)
+ opt["eol"] = "\r\n"
+ options = check_input(device_opt, opt)
+
+ docs = {}
+ docs["shortdesc"] = "I/O Fencing agent for Koukaam NETIO-230B"
+ docs["longdesc"] = "fence_netio is an I/O Fencing agent which can be \
+used with the Koukaam NETIO-230B Power Distribution Unit. It logs into \
+device via telnet and reboots a specified outlet. Lengthy telnet connections \
+should be avoided while a GFS cluster is running because the connection will \
+block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.koukaam.se/"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ## We can not use fence_login(), username and passwd are sent on one line
+ ####
+ run_delay(options)
+ try:
+ conn = fspawn(options, options["--telnet-path"])
+ conn.send("set binary\n")
+ conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
+
+ conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ conn.log_expect("100 HELLO .*", int(options["--shell-timeout"]))
+ conn.send_eol("login %s %s" % (options["--username"], options["--password"]))
+ conn.log_expect("250 OK", int(options["--shell-timeout"]))
+ except pexpect.EOF:
+ fail(EC_LOGIN_DENIED)
+ except pexpect.TIMEOUT:
+ fail(EC_LOGIN_DENIED)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_outlet_list)
+ fence_logout(conn, "quit\n")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/openstack/fence_openstack.py b/agents/openstack/fence_openstack.py
new file mode 100644
index 0000000..666016d
--- /dev/null
+++ b/agents/openstack/fence_openstack.py
@@ -0,0 +1,381 @@
+#!@PYTHON@ -tt
+
+import atexit
+import logging
+import sys
+import os
+
+import urllib3
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, run_delay, source_env
+
+try:
+ from novaclient import client
+ from novaclient.exceptions import Conflict, NotFound
+except ImportError:
+ pass
+
+urllib3.disable_warnings(urllib3.exceptions.SecurityWarning)
+
+
+def translate_status(instance_status):
+ if instance_status == "ACTIVE":
+ return "on"
+ elif instance_status == "SHUTOFF":
+ return "off"
+ return "unknown"
+
+def get_cloud(options):
+ import yaml
+
+ clouds_yaml = "~/.config/openstack/clouds.yaml"
+ if not os.path.exists(os.path.expanduser(clouds_yaml)):
+ clouds_yaml = "/etc/openstack/clouds.yaml"
+ if not os.path.exists(os.path.expanduser(clouds_yaml)):
+ fail_usage("Failed: ~/.config/openstack/clouds.yaml and /etc/openstack/clouds.yaml does not exist")
+
+ clouds_yaml = os.path.expanduser(clouds_yaml)
+ if os.path.exists(clouds_yaml):
+ with open(clouds_yaml, "r") as yaml_stream:
+ try:
+ clouds = yaml.safe_load(yaml_stream)
+ except yaml.YAMLError as exc:
+ fail_usage("Failed: Unable to read: " + clouds_yaml)
+
+ cloud = clouds.get("clouds").get(options["--cloud"])
+ if not cloud:
+ fail_usage("Cloud: {} not found.".format(options["--cloud"]))
+
+ return cloud
+
+
+def get_nodes_list(conn, options):
+ logging.info("Running %s action", options["--action"])
+ result = {}
+ response = conn.servers.list(detailed=True)
+ if response is not None:
+ for item in response:
+ instance_id = item.id
+ instance_name = item.name
+ instance_status = item.status
+ result[instance_id] = (instance_name, translate_status(instance_status))
+ return result
+
+
+def get_power_status(conn, options):
+ logging.info("Running %s action on %s", options["--action"], options["--plug"])
+ server = None
+ try:
+ server = conn.servers.get(options["--plug"])
+ except NotFound as e:
+ fail_usage("Failed: Not Found: " + str(e))
+ if server is None:
+ fail_usage("Server %s not found", options["--plug"])
+ state = server.status
+ status = translate_status(state)
+ logging.info("get_power_status: %s (state: %s)" % (status, state))
+ return status
+
+
+def set_power_status(conn, options):
+ logging.info("Running %s action on %s", options["--action"], options["--plug"])
+ action = options["--action"]
+ server = None
+ try:
+ server = conn.servers.get(options["--plug"])
+ except NotFound as e:
+ fail_usage("Failed: Not Found: " + str(e))
+ if server is None:
+ fail_usage("Server %s not found", options["--plug"])
+ if action == "on":
+ logging.info("Starting instance " + server.name)
+ try:
+ server.start()
+ except Conflict as e:
+ fail_usage(e)
+ logging.info("Called start API call for " + server.id)
+ if action == "off":
+ logging.info("Stopping instance " + server.name)
+ try:
+ server.stop()
+ except Conflict as e:
+ fail_usage(e)
+ logging.info("Called stop API call for " + server.id)
+ if action == "reboot":
+ logging.info("Rebooting instance " + server.name)
+ try:
+ server.reboot("HARD")
+ except Conflict as e:
+ fail_usage(e)
+ logging.info("Called reboot hard API call for " + server.id)
+
+
+def nova_login(username, password, projectname, auth_url, user_domain_name,
+ project_domain_name, ssl_insecure, cacert, apitimeout):
+ legacy_import = False
+
+ try:
+ from keystoneauth1 import loading
+ from keystoneauth1 import session as ksc_session
+ from keystoneauth1.exceptions.discovery import DiscoveryFailure
+ from keystoneauth1.exceptions.http import Unauthorized
+ except ImportError:
+ try:
+ from keystoneclient import session as ksc_session
+ from keystoneclient.auth.identity import v3
+
+ legacy_import = True
+ except ImportError:
+ fail_usage("Failed: Keystone client not found or not accessible")
+
+ if not legacy_import:
+ loader = loading.get_plugin_loader("password")
+ auth = loader.load_from_options(
+ auth_url=auth_url,
+ username=username,
+ password=password,
+ project_name=projectname,
+ user_domain_name=user_domain_name,
+ project_domain_name=project_domain_name,
+ )
+ else:
+ auth = v3.Password(
+ auth_url=auth_url,
+ username=username,
+ password=password,
+ project_name=projectname,
+ user_domain_name=user_domain_name,
+ project_domain_name=project_domain_name,
+ cacert=cacert,
+ )
+
+ caverify=True
+ if ssl_insecure:
+ caverify=False
+ elif cacert:
+ caverify=cacert
+
+ session = ksc_session.Session(auth=auth, verify=caverify, timeout=apitimeout)
+ nova = client.Client("2", session=session, timeout=apitimeout)
+ apiversion = None
+ try:
+ apiversion = nova.versions.get_current()
+ except DiscoveryFailure as e:
+ fail_usage("Failed: Discovery Failure: " + str(e))
+ except Unauthorized as e:
+ fail_usage("Failed: Unauthorized: " + str(e))
+ except Exception as e:
+ logging.error(e)
+ logging.debug("Nova version: %s", apiversion)
+ return nova
+
+
+def define_new_opts():
+ all_opt["auth-url"] = {
+ "getopt": ":",
+ "longopt": "auth-url",
+ "help": "--auth-url=[authurl] Keystone Auth URL",
+ "required": "0",
+ "shortdesc": "Keystone Auth URL",
+ "order": 2,
+ }
+ all_opt["project-name"] = {
+ "getopt": ":",
+ "longopt": "project-name",
+ "help": "--project-name=[project] Tenant Or Project Name",
+ "required": "0",
+ "shortdesc": "Keystone Project",
+ "default": "admin",
+ "order": 3,
+ }
+ all_opt["user-domain-name"] = {
+ "getopt": ":",
+ "longopt": "user-domain-name",
+ "help": "--user-domain-name=[domain] Keystone User Domain Name",
+ "required": "0",
+ "shortdesc": "Keystone User Domain Name",
+ "default": "Default",
+ "order": 4,
+ }
+ all_opt["project-domain-name"] = {
+ "getopt": ":",
+ "longopt": "project-domain-name",
+ "help": "--project-domain-name=[domain] Keystone Project Domain Name",
+ "required": "0",
+ "shortdesc": "Keystone Project Domain Name",
+ "default": "Default",
+ "order": 5,
+ }
+ all_opt["cloud"] = {
+ "getopt": ":",
+ "longopt": "cloud",
+ "help": "--cloud=[cloud] Openstack cloud (from ~/.config/openstack/clouds.yaml or /etc/openstack/clouds.yaml).",
+ "required": "0",
+ "shortdesc": "Cloud from clouds.yaml",
+ "order": 6,
+ }
+ all_opt["openrc"] = {
+ "getopt": ":",
+ "longopt": "openrc",
+ "help": "--openrc=[openrc] Path to the openrc config file",
+ "required": "0",
+ "shortdesc": "openrc config file",
+ "order": 7,
+ }
+ all_opt["uuid"] = {
+ "getopt": ":",
+ "longopt": "uuid",
+ "help": "--uuid=[uuid] Replaced by -n, --plug",
+ "required": "0",
+ "shortdesc": "Replaced by port/-n/--plug",
+ "order": 8,
+ }
+ all_opt["cacert"] = {
+ "getopt": ":",
+ "longopt": "cacert",
+ "help": "--cacert=[cacert] Path to the PEM file with trusted authority certificates (override global CA trust)",
+ "required": "0",
+ "shortdesc": "SSL X.509 certificates file",
+ "default": "",
+ "order": 9,
+ }
+ all_opt["apitimeout"] = {
+ "getopt": ":",
+ "type": "second",
+ "longopt": "apitimeout",
+ "help": "--apitimeout=[seconds] Timeout to use for API calls",
+ "shortdesc": "Timeout in seconds to use for API calls, default is 60.",
+ "required": "0",
+ "default": 60,
+ "order": 10,
+ }
+
+
+def main():
+ conn = None
+
+ device_opt = [
+ "login",
+ "no_login",
+ "passwd",
+ "no_password",
+ "auth-url",
+ "project-name",
+ "user-domain-name",
+ "project-domain-name",
+ "cloud",
+ "openrc",
+ "port",
+ "no_port",
+ "uuid",
+ "ssl_insecure",
+ "cacert",
+ "apitimeout",
+ ]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["port"]["required"] = "0"
+ all_opt["port"]["help"] = "-n, --plug=[UUID] UUID of the node to be fenced"
+ all_opt["port"]["shortdesc"] = "UUID of the node to be fenced."
+ all_opt["power_timeout"]["default"] = "60"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ # workaround to avoid regressions
+ if "--uuid" in options:
+ options["--plug"] = options["--uuid"]
+ del options["--uuid"]
+ elif ("--help" not in options
+ and options["--action"] in ["off", "on", "reboot", "status", "validate-all"]
+ and "--plug" not in options):
+ stop_after_error = False if options["--action"] == "validate-all" else True
+ fail_usage(
+ "Failed: You have to enter plug number or machine identification",
+ stop_after_error,
+ )
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for OpenStack's Nova service"
+ docs["longdesc"] = "fence_openstack is a Fencing agent \
+which can be used with machines controlled by the Openstack's Nova service. \
+This agent calls the python-novaclient and it is mandatory to be installed "
+ docs["vendorurl"] = "https://wiki.openstack.org/wiki/Nova"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if options.get("--cloud"):
+ cloud = get_cloud(options)
+ username = cloud.get("auth").get("username")
+ password = cloud.get("auth").get("password")
+ projectname = cloud.get("auth").get("project_name")
+ auth_url = None
+ try:
+ auth_url = cloud.get("auth").get("auth_url")
+ except KeyError:
+ fail_usage("Failed: You have to set the Keystone service endpoint for authorization")
+ user_domain_name = cloud.get("auth").get("user_domain_name")
+ project_domain_name = cloud.get("auth").get("project_domain_name")
+ caverify = cloud.get("verify")
+ if caverify in [True, False]:
+ options["--ssl-insecure"] = caverify
+ else:
+ options["--cacert"] = caverify
+ elif options.get("--openrc"):
+ if not os.path.exists(os.path.expanduser(options["--openrc"])):
+ fail_usage("Failed: {} does not exist".format(options.get("--openrc")))
+ source_env(options["--openrc"])
+ env = os.environ
+ username = env.get("OS_USERNAME")
+ password = env.get("OS_PASSWORD")
+ projectname = env.get("OS_PROJECT_NAME")
+ auth_url = None
+ try:
+ auth_url = env["OS_AUTH_URL"]
+ except KeyError:
+ fail_usage("Failed: You have to set the Keystone service endpoint for authorization")
+ user_domain_name = env.get("OS_USER_DOMAIN_NAME")
+ project_domain_name = env.get("OS_PROJECT_DOMAIN_NAME")
+ else:
+ username = options["--username"]
+ password = options["--password"]
+ projectname = options["--project-name"]
+ auth_url = None
+ try:
+ auth_url = options["--auth-url"]
+ except KeyError:
+ fail_usage("Failed: You have to set the Keystone service endpoint for authorization")
+ user_domain_name = options["--user-domain-name"]
+ project_domain_name = options["--project-domain-name"]
+
+ ssl_insecure = "--ssl-insecure" in options
+ cacert = options["--cacert"]
+ apitimeout = options["--apitimeout"]
+
+ try:
+ conn = nova_login(
+ username,
+ password,
+ projectname,
+ auth_url,
+ user_domain_name,
+ project_domain_name,
+ ssl_insecure,
+ cacert,
+ apitimeout,
+ )
+ except Exception as e:
+ fail_usage("Failed: Unable to connect to Nova: " + str(e))
+
+ # Operate the fencing device
+ result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list)
+ sys.exit(result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/ovh/fence_ovh.py b/agents/ovh/fence_ovh.py
new file mode 100644
index 0000000..2b7eb86
--- /dev/null
+++ b/agents/ovh/fence_ovh.py
@@ -0,0 +1,164 @@
+#!@PYTHON@ -tt
+# Copyright 2013 Adrian Gibanel Lopez (bTactic)
+# Adrian Gibanel improved this script at 2013 to add verification of success and to output metadata
+
+# Based on:
+# This is a fence agent for use at OVH
+# As there are no other fence devices available, we must use OVH's SOAP API #Quick-and-dirty
+# assemled by Dennis Busch, secofor GmbH, Germany
+# This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
+
+import sys, time
+import shutil, tempfile
+import logging
+import atexit
+from datetime import datetime
+from suds.client import Client
+from suds.xsd.doctor import ImportDoctor, Import
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, EC_LOGIN_DENIED, run_delay
+
+OVH_RESCUE_PRO_NETBOOT_ID = '28'
+OVH_HARD_DISK_NETBOOT_ID = '1'
+
+STATUS_HARD_DISK_SLEEP = 240 # Wait 4 minutes to SO to boot
+STATUS_RESCUE_PRO_SLEEP = 150 # Wait 2 minutes 30 seconds to Rescue-Pro to run
+
+def define_new_opts():
+ all_opt["email"] = {
+ "getopt" : "Z:",
+ "longopt" : "email",
+ "help" : "-Z, --email=[email] email for reboot message: admin@domain.com",
+ "required" : "1",
+ "shortdesc" : "Reboot email",
+ "order" : 1}
+
+def netboot_reboot(conn, options, mode):
+ # dedicatedNetbootModifyById changes the mode of the next reboot
+ conn.service.dedicatedNetbootModifyById(options["session"], options["--plug"], mode, '', options["--email"])
+
+ # dedicatedHardRebootDo initiates a hard reboot on the given node
+ conn.service.dedicatedHardRebootDo(options["session"],
+ options["--plug"], 'Fencing initiated by cluster', '', 'en')
+
+ conn.logout(options["session"])
+
+def reboot_time(conn, options):
+ result = conn.service.dedicatedHardRebootStatus(options["session"], options["--plug"])
+ tmpstart = datetime.strptime(result.start, '%Y-%m-%d %H:%M:%S')
+ tmpend = datetime.strptime(result.end, '%Y-%m-%d %H:%M:%S')
+ result.start = tmpstart
+ result.end = tmpend
+
+ return result
+
+def soap_login(options):
+ imp = Import('http://schemas.xmlsoap.org/soap/encoding/')
+ url = 'https://www.ovh.com/soapi/soapi-re-1.59.wsdl'
+ imp.filter.add('http://soapi.ovh.com/manager')
+ d = ImportDoctor(imp)
+
+ tmp_dir = tempfile.mkdtemp()
+ tempfile.tempdir = tmp_dir
+ atexit.register(remove_tmp_dir, tmp_dir)
+
+ try:
+ soap = Client(url, doctor=d)
+ session = soap.service.login(options["--username"], options["--password"], 'en', 0)
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_LOGIN_DENIED)
+
+ options["session"] = session
+ return soap
+
+def remove_tmp_dir(tmp_dir):
+ shutil.rmtree(tmp_dir)
+
+def main():
+ device_opt = ["login", "passwd", "port", "email", "no_status", "web"]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+ options = check_input(device_opt, process_input(device_opt), other_conditions=True)
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for OVH"
+ docs["longdesc"] = "fence_ovh is an Power Fencing agent \
+which can be used within OVH datecentre. \
+Poweroff is simulated with a reboot into rescue-pro mode."
+
+ docs["vendorurl"] = "http://www.ovh.net"
+ show_docs(options, docs)
+
+ if options["--action"] == "list":
+ fail_usage("Action 'list' is not supported in this fence agent")
+
+ if options["--action"] == "list-status":
+ fail_usage("Action 'list-status' is not supported in this fence agent")
+
+ if "--email" not in options:
+ fail_usage("You have to enter e-mail address which is notified by fence agent")
+
+ if options["--action"] == "validate-all":
+ sys.exit(0)
+
+ if options["--action"] != "monitor" and not options["--plug"].endswith(".ovh.net"):
+ options["--plug"] += ".ovh.net"
+
+ run_delay(options)
+
+ conn = soap_login(options)
+
+ if options["--action"] == 'monitor':
+ try:
+ conn.service.logout(options["session"])
+ except Exception:
+ pass
+ sys.exit(0)
+
+ # Save datetime just before changing netboot
+ before_netboot_reboot = datetime.now()
+
+ if options["--action"] == 'off':
+ # Reboot in Rescue-pro
+ netboot_reboot(conn, options, OVH_RESCUE_PRO_NETBOOT_ID)
+ time.sleep(STATUS_RESCUE_PRO_SLEEP)
+ elif options["--action"] in ['on', 'reboot']:
+ # Reboot from HD
+ netboot_reboot(conn, options, OVH_HARD_DISK_NETBOOT_ID)
+ time.sleep(STATUS_HARD_DISK_SLEEP)
+
+ # Save datetime just after reboot
+ after_netboot_reboot = datetime.now()
+
+ # Verify that action was completed sucesfully
+ reboot_t = reboot_time(conn, options)
+
+ logging.debug("reboot_start_end.start: %s\n",
+ reboot_t.start.strftime('%Y-%m-%d %H:%M:%S'))
+ logging.debug("before_netboot_reboot: %s\n",
+ before_netboot_reboot.strftime('%Y-%m-%d %H:%M:%S'))
+ logging.debug("reboot_start_end.end: %s\n",
+ reboot_t.end.strftime('%Y-%m-%d %H:%M:%S'))
+ logging.debug("after_netboot_reboot: %s\n",
+ after_netboot_reboot.strftime('%Y-%m-%d %H:%M:%S'))
+
+ if reboot_t.start < after_netboot_reboot < reboot_t.end:
+ result = 0
+ logging.debug("Netboot reboot went OK.\n")
+ else:
+ result = 1
+ logging.debug("ERROR: Netboot reboot wasn't OK.\n")
+
+ try:
+ conn.service.logout(options["session"])
+ except Exception:
+ pass
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/powerman/fence_powerman.py b/agents/powerman/fence_powerman.py
new file mode 100755
index 0000000..7aeeaf1
--- /dev/null
+++ b/agents/powerman/fence_powerman.py
@@ -0,0 +1,257 @@
+#!@PYTHON@ -tt
+import os
+import time
+from datetime import datetime
+import sys
+import subprocess
+import re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import is_executable, fail_usage, run_delay
+import logging
+
+#### important!!! #######
+class PowerMan:
+ """Python wrapper for calling powerman commands
+
+ This class makes calls to a powerman deamon for a cluster of computers.
+ The make-up of such a call looks something like:
+ $ pm -h elssd1:10101 <option> <node>
+ where option is something like --off, --on, --cycle and where node is
+ elssd8, or whatever values are setup in powerman.conf. Note that powerman
+ itself must be configured for this fence agent to work.
+ """
+
+ def __init__(self, powerman_path, server_name, port):
+ """
+ Args:
+ server_name: (string) host or ip of powerman server
+ port: (str) port number that the powerman server is listening on
+ """
+ self.powerman_path = powerman_path
+ self.server_name = server_name
+ self.port = port
+ self.server_and_port = server_name + ":" + str(port)
+ self.base_cmd = [
+ self.powerman_path,
+ "--server-host",
+ self.server_and_port
+ ]
+
+ def _run(self, cmd, only_first_line):
+ # Args:
+ # cmd: (list) commands and arguments to pass to the program_name
+
+ run_this = self.base_cmd + cmd
+ try:
+ popen = subprocess.Popen(run_this, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ out = popen.communicate()
+ except OSError as e:
+ logging.error("_run command error: %s\n", e)
+ sys.exit(1)
+ if only_first_line == True:
+ result_line = out[0].decode().strip()
+ return (result_line, popen.returncode)
+ else:
+ result_list = []
+ for line in out:
+ result_list.append(line)
+ return (result_list, popen.returncode)
+
+ def is_running(self):
+ """simple query to see if powerman server is responding. Returns boolean"""
+ cmd = ["-q"] # just check if we get a response from the server
+ result, ret_code = self._run(cmd, True)
+ if ret_code != 0:
+ return False
+ return True
+
+ ## Some devices respond to on or off actions as if the action was successful,
+ ## when it was not.
+ ##
+ ## This is not unique to powerman, and so fence_action ignores the return code
+ ## from the set_power_fn and queries the device to confirm the power status of
+ ## the machine.
+ ##
+ ## For this reason we do not do a query ourself, retry, etc. in on() or off().
+
+ def on(self, host):
+ logging.debug("PowerMan on: %s\n", host)
+ cmd = ["--on", host]
+ try:
+ result, ret_code = self._run(cmd, True)
+ except OSError as e:
+ logging.error("PowerMan Error: The command '--on' failed: %s\n", e)
+ return -1
+ except ValueError as e:
+ logging.error("PowerMan Error: Popen: invalid arguments: %s\n", e)
+ return -1
+ logging.debug("pm.on result: %s ret_code: %s\n", result, ret_code)
+
+ return ret_code
+
+ def off(self, host):
+ logging.debug("PowerMan off: %s\n", host)
+ cmd = ["--off", host]
+ try:
+ result, ret_code = self._run(cmd, True)
+ except OSError as e:
+ logging.error("PowerMan Error: The command '%s' failed: %s\n", cmd, e)
+ return -1
+ except ValueError as e:
+ logging.error("PowerMan Error: Popen: invalid arguments: %s\n", e)
+ return -1
+ logging.debug("pm.off result: %s ret_code: %s\n", result, ret_code)
+
+ return ret_code
+
+ def list(self):
+ ## Error checking here is faulty. Try passing
+ ## invalid args, e.g. --query --exprange to see failure
+ cmd = ["-q","--exprange"]
+ try:
+ result, ret_code = self._run(cmd, False)
+ except OSError as e:
+ logging.error("PowerMan Error: The command '%s' failed: %s\n", cmd, e)
+ return -1
+ except ValueError as e:
+ logging.error("PowerMan Error: Popen: invalid arguments: %s\n", e)
+ return -1
+ if ret_code < 0:
+ # there was an error with the command
+ return ret_code
+ else:
+ state = {}
+ for line in result[0].split('\n'):
+ if len(line) > 2:
+ fields = line.split(':')
+ if len(fields) == 2:
+ state[fields[0]] = (fields[0],fields[1])
+ return state
+
+ def query(self, host):
+ cmd = ["--query", host]
+ try:
+ result, ret_code = self._run(cmd, True)
+ except OSError as e:
+ logging.error("PowerMan Error: The command '%s' failed: %s\n", cmd, e)
+ return -1
+ except ValueError as e:
+ logging.error("PowerMan Error: Popen: invalid arguments: %s\n", e)
+ return -1
+ if ret_code < 0:
+ # there was an error with the command
+ return ret_code
+ else:
+ res = result.split('\n')
+ res = [r.split() for r in res]
+ # find the host in command's returned output
+ for lst in res:
+ if lst[0] == 'No' and lst[1] == 'such' and lst[2] == 'nodes:':
+ return -1
+ if host in lst:
+ return lst[0][:-1] # lst[0] would be 'off:'-- this removes the colon
+ # host isn't in the output
+ return -1
+
+
+def get_power_status(conn, options):
+ logging.debug("get_power_status function:\noptions: %s\n", str(options))
+ pm = PowerMan(options['--powerman-path'], options['--ip'], options['--ipport'])
+ # if Pacemaker is checking the status of the Powerman server...
+ if options['--action'] == 'monitor':
+ if pm.is_running():
+ logging.debug("Powerman is running\n")
+ return "on"
+ logging.debug("Powerman is NOT running\n")
+ return "error"
+ else:
+ status = pm.query(options['--plug'])
+ if isinstance(int, type(status)):
+ # query only returns ints on error
+ logging.error("get_power_status: query returned %s\n", str(status))
+ fail(EC_STATUS)
+ return status
+
+
+def set_power_status(conn, options):
+ logging.debug("set_power_status function:\noptions: %s", str(options))
+ pm = PowerMan(options['--powerman-path'], options['--ip'], options['--ipport'])
+
+ action = options["--action"]
+ if action == "on":
+ pm.on(options['--plug'])
+ elif action == "off":
+ pm.off(options['--plug'])
+
+ return
+
+
+def get_list(conn, options):
+ logging.debug("get_list function:\noptions: %s", str(options))
+ pm = PowerMan(options['--powerman-path'], options['--ip'], options['--ipport'])
+
+ outlets = pm.list()
+ logging.debug("get_list outlets.keys: %s", str(outlets.keys()))
+ return outlets
+
+
+def define_new_opts():
+ all_opt["powerman_path"] = {
+ "getopt" : ":",
+ "longopt" : "powerman-path",
+ "help" : "--powerman-path=[path] Path to powerman binary",
+ "required" : "0",
+ "shortdesc" : "Path to powerman binary",
+ "default" : "@POWERMAN_PATH@",
+ "order": 200
+ }
+
+
+def main():
+ device_opt = [
+ 'ipaddr',
+ 'no_password',
+ 'no_login',
+ 'powerman_path',
+ ]
+
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ # redefine default values for the options given by fencing.py
+ # these 3 different values are derived from the lssd test cluster and may
+ # need to adjusted depending on how other systems fare
+ all_opt['ipport']['default'] = '10101'
+ all_opt['delay']['default'] = '3'
+ all_opt['power_wait']['default'] = '3'
+
+ options = check_input(device_opt, process_input(device_opt))
+ docs = {}
+ docs["shortdesc"] = "Fence Agent for Powerman"
+ docs["longdesc"] = "This is a Pacemaker Fence Agent for the \
+Powerman management utility that was designed for LLNL systems."
+ docs["vendorurl"] = "https://github.com/chaos/powerman"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if not is_executable(options["--powerman-path"]):
+ fail_usage("Powerman not found or not executable at path " + options["--powerman-path"])
+
+ # call the fencing.fence_action function, passing in my various fence functions
+ result = fence_action(
+ None,
+ options,
+ set_power_status,
+ get_power_status,
+ get_list,
+ None
+ )
+ sys.exit(result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/pve/fence_pve.py b/agents/pve/fence_pve.py
new file mode 100755
index 0000000..0d82035
--- /dev/null
+++ b/agents/pve/fence_pve.py
@@ -0,0 +1,240 @@
+#!@PYTHON@ -tt
+
+# This agent uses Proxmox VE API
+# Thanks to Frank Brendel (author of original perl fence_pve)
+# for help with writing and testing this agent.
+
+import sys
+import json
+import pycurl
+import io
+import atexit
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import fail, fail_usage, EC_LOGIN_DENIED, atexit_handler, all_opt, check_input, process_input, show_docs, fence_action, run_delay
+
+if sys.version_info[0] > 2: import urllib.parse as urllib
+else: import urllib
+
+def get_power_status(conn, options):
+ del conn
+ state = {"running" : "on", "stopped" : "off"}
+ if options["--pve-node"] is None:
+ nodes = send_cmd(options, "nodes")
+ if type(nodes) is not dict or "data" not in nodes or type(nodes["data"]) is not list:
+ return None
+ for node in nodes["data"]: # lookup the node holding the vm
+ if type(node) is not dict or "node" not in node:
+ return None
+ options["--pve-node"] = node["node"]
+ status = get_power_status(None, options)
+ if status is not None:
+ logging.info("vm found on node: " + options["--pve-node"])
+ break
+ else:
+ options["--pve-node"] = None
+ return status
+ else:
+ cmd = "nodes/" + options["--pve-node"] + "/" + options["--vmtype"] +"/" + options["--plug"] + "/status/current"
+ result = send_cmd(options, cmd)
+ if type(result) is dict and "data" in result:
+ if type(result["data"]) is dict and "status" in result["data"]:
+ if result["data"]["status"] in state:
+ return state[result["data"]["status"]]
+ return None
+
+
+def set_power_status(conn, options):
+ del conn
+ action = {
+ 'on' : "start",
+ 'off': "stop"
+ }[options["--action"]]
+ cmd = "nodes/" + options["--pve-node"] + "/" + options["--vmtype"] +"/" + options["--plug"] + "/status/" + action
+ send_cmd(options, cmd, post={"skiplock":1})
+
+
+def reboot_cycle(conn, options):
+ del conn
+ cmd = "nodes/" + options["--pve-node"] + "/" + options["--vmtype"] + "/" + options["--plug"] + "/status/reset"
+ result = send_cmd(options, cmd, post={"skiplock":1})
+ return type(result) is dict and "data" in result
+
+
+def get_outlet_list(conn, options):
+ del conn
+ nodes = send_cmd(options, "nodes")
+ outlets = dict()
+ if type(nodes) is not dict or "data" not in nodes or type(nodes["data"]) is not list:
+ return None
+ for node in nodes["data"]:
+ if type(node) is not dict or "node" not in node:
+ return None
+ vms = send_cmd(options, "nodes/" + node["node"] + "/" + options["--vmtype"])
+ if type(vms) is not dict or "data" not in vms or type(vms["data"]) is not list:
+ return None
+ for vm in vms["data"]:
+ outlets[vm["vmid"]] = [vm["name"], vm["status"]]
+ return outlets
+
+
+def get_ticket(options):
+ post = {'username': options["--username"], 'password': options["--password"]}
+ result = send_cmd(options, "access/ticket", post=post)
+ if type(result) is dict and "data" in result:
+ if type(result["data"]) is dict and "ticket" in result["data"] and "CSRFPreventionToken" in result["data"]:
+ return {
+ "ticket" : str("PVEAuthCookie=" + result["data"]["ticket"] + "; " + \
+ "version=0; path=/; domain=" + options["--ip"] + \
+ "; port=" + str(options["--ipport"]) + "; path_spec=0; secure=1; " + \
+ "expires=7200; discard=0"),
+ "CSRF_token" : str("CSRFPreventionToken: " + result["data"]["CSRFPreventionToken"])
+ }
+ return None
+
+
+def send_cmd(options, cmd, post=None):
+ url = options["url"] + cmd
+ conn = pycurl.Curl()
+ output_buffer = io.BytesIO()
+ if logging.getLogger().getEffectiveLevel() < logging.WARNING:
+ conn.setopt(pycurl.VERBOSE, True)
+ conn.setopt(pycurl.HTTPGET, 1)
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+ if "auth" in options and options["auth"] is not None:
+ conn.setopt(pycurl.COOKIE, options["auth"]["ticket"])
+ conn.setopt(pycurl.HTTPHEADER, [options["auth"]["CSRF_token"]])
+ if post is not None:
+ if "skiplock" in post:
+ conn.setopt(conn.CUSTOMREQUEST, 'POST')
+ else:
+ conn.setopt(pycurl.POSTFIELDS, urllib.urlencode(post))
+ conn.setopt(pycurl.WRITEFUNCTION, output_buffer.write)
+ conn.setopt(pycurl.TIMEOUT, int(options["--shell-timeout"]))
+
+ if "--ssl-insecure" in options:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+ else:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+
+ logging.debug("URL: " + url)
+
+ try:
+ conn.perform()
+ result = output_buffer.getvalue().decode()
+
+ logging.debug("RESULT [" + str(conn.getinfo(pycurl.RESPONSE_CODE)) + \
+ "]: " + result)
+ conn.close()
+
+ return json.loads(result)
+ except pycurl.error:
+ logging.error("Connection failed")
+ except:
+ logging.error("Cannot parse json")
+ return None
+
+
+def main():
+ atexit.register(atexit_handler)
+
+ all_opt["pve_node_auto"] = {
+ "getopt" : "A",
+ "longopt" : "pve-node-auto",
+ "help" : "-A, --pve-node-auto "
+ "Automatically select proxmox node",
+ "required" : "0",
+ "shortdesc" : "Automatically select proxmox node. "
+ "(This option overrides --pve-node)",
+ "type": "boolean",
+ "order": 2
+ }
+ all_opt["pve_node"] = {
+ "getopt" : "N:",
+ "longopt" : "pve-node",
+ "help" : "-N, --pve-node=[node_name] "
+ "Proxmox node name on which machine is located",
+ "required" : "0",
+ "shortdesc" : "Proxmox node name on which machine is located. "
+ "(Must be specified if not using --pve-node-auto)",
+ "order": 2
+ }
+ all_opt["node_name"] = {
+ "getopt" : ":",
+ "longopt" : "nodename",
+ "help" : "--nodename "
+ "Replaced by --pve-node",
+ "required" : "0",
+ "shortdesc" : "Replaced by --pve-node",
+ "order": 3
+ }
+ all_opt["vmtype"] = {
+ "getopt" : ":",
+ "longopt" : "vmtype",
+ "default" : "qemu",
+ "help" : "--vmtype "
+ "Virtual machine type lxc or qemu (default: qemu)",
+ "required" : "1",
+ "shortdesc" : "Virtual machine type lxc or qemu. "
+ "(Default: qemu)",
+ "order": 2
+ }
+
+ device_opt = ["ipaddr", "login", "passwd", "ssl", "web", "port", "pve_node", "pve_node_auto", "node_name", "vmtype", "method"]
+
+ all_opt["login"]["required"] = "0"
+ all_opt["login"]["default"] = "root@pam"
+ all_opt["ipport"]["default"] = "8006"
+ all_opt["ssl"]["default"] = "1"
+ all_opt["port"]["shortdesc"] = "Id of the virtual machine."
+ all_opt["ipaddr"]["shortdesc"] = "IP Address or Hostname of a node " +\
+ "within the Proxmox cluster."
+
+ options = check_input(device_opt, process_input(device_opt))
+ docs = {}
+ docs["shortdesc"] = "Fencing agent for the Proxmox Virtual Environment"
+ docs["longdesc"] = "The fence_pve agent can be used to fence virtual \
+machines acting as nodes in a virtualized cluster."
+ docs["vendorurl"] = "http://www.proxmox.com/"
+
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if "--pve-node-auto" in options:
+ # Force pve-node to None to allow autodiscovery
+ options["--pve-node"] = None
+ elif "--pve-node" in options and options["--pve-node"]:
+ # Leave pve-node alone
+ pass
+ elif "--nodename" in options and options["--nodename"]:
+ # map nodename into pve-node to support legacy implementations
+ options["--pve-node"] = options["--nodename"]
+ else:
+ fail_usage("At least one of pve-node-auto or pve-node must be supplied")
+
+
+ if options["--vmtype"] != "qemu":
+ # For vmtypes other than qemu, only the onoff method is valid
+ options["--method"] = "onoff"
+
+ options["url"] = "https://" + options["--ip"] + ":" + str(options["--ipport"]) + "/api2/json/"
+
+ options["auth"] = get_ticket(options)
+ if options["auth"] is None:
+ fail(EC_LOGIN_DENIED)
+
+ # Workaround for unsupported API call on some Proxmox hosts
+ outlets = get_outlet_list(None, options) # Unsupported API-Call will result in value: None
+ if outlets is None:
+ result = fence_action(None, options, set_power_status, get_power_status, None, reboot_cycle)
+ sys.exit(result)
+
+ result = fence_action(None, options, set_power_status, get_power_status, get_outlet_list, reboot_cycle)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/raritan/fence_raritan.py b/agents/raritan/fence_raritan.py
new file mode 100644
index 0000000..169fa81
--- /dev/null
+++ b/agents/raritan/fence_raritan.py
@@ -0,0 +1,87 @@
+#!@PYTHON@ -tt
+
+import sys, re, pexpect
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fspawn, fail, EC_LOGIN_DENIED, run_delay
+
+def get_power_status(conn, options):
+ conn.send_eol("show -d properties=powerState %s" % options["--plug"])
+ re_status = re.compile(".*powerState is [12].*")
+ conn.log_expect(re_status, int(options["--shell-timeout"]))
+ status = {
+ #"0" : "off",
+ "1" : "on",
+ "2" : "off",
+ }[conn.after.split()[2]]
+
+ return status
+
+def set_power_status(conn, options):
+ action = {
+ "on" : "on",
+ "off" : "off",
+ }[options["--action"]]
+
+ conn.send_eol("set %s powerState=%s" % (options["--plug"], action))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "port", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ opt = process_input(device_opt)
+
+ all_opt["ipport"]["default"] = "23"
+
+ opt["eol"] = "\r\n"
+ options = check_input(device_opt, opt)
+
+ docs = {}
+ docs["shortdesc"] = "I/O Fencing agent for Raritan Dominion PX"
+ docs["longdesc"] = "fence_raritan is an I/O Fencing agent which can be \
+used with the Raritan DPXS12-20 Power Distribution Unit. It logs into \
+device via telnet and reboots a specified outlet. Lengthy telnet connections \
+should be avoided while a GFS cluster is running because the connection will \
+block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.raritan.com/"
+ show_docs(options, docs)
+
+ # add support also for delay before login which is very useful for 2-node clusters
+ run_delay(options)
+
+ # Convert pure port/plug number to /system1/outlet${plug}
+ try:
+ plug_int = int(options["--plug"])
+ options["--plug"] = "/system1/outlet" + str(plug_int)
+ except ValueError:
+ pass
+ ##
+ ## Operate the fencing device
+ ## We can not use fence_login(), username and passwd are sent on one line
+ ####
+ try:
+ conn = fspawn(options, options["--telnet-path"], encoding="latin1")
+ conn.send("set binary\n")
+ conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
+ conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ conn.log_expect("Login.*", int(options["--shell-timeout"]))
+ conn.send_eol("%s" % (options["--username"]))
+ conn.log_expect("Password.*", int(options["--shell-timeout"]))
+ conn.send_eol("%s" % (options["--password"]))
+ conn.log_expect("clp.*", int(options["--shell-timeout"]))
+ except pexpect.EOF:
+ fail(EC_LOGIN_DENIED)
+ except pexpect.TIMEOUT:
+ fail(EC_LOGIN_DENIED)
+
+ result = 0
+ if options["--action"] != "monitor":
+ result = fence_action(conn, options, set_power_status, get_power_status)
+
+ fence_logout(conn, "exit\n")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/raritan_px3/fence_raritan_px3.py b/agents/raritan_px3/fence_raritan_px3.py
new file mode 100644
index 0000000..137f160
--- /dev/null
+++ b/agents/raritan_px3/fence_raritan_px3.py
@@ -0,0 +1,195 @@
+#!@PYTHON@ -tt
+
+import logging
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import EC_STATUS
+
+"""
+Raritan PX3 family is totaly different the PX family (PX2 seem to be
+compatible with PX3 and seem to share the same BIOS, so this fence should
+work with PX2 as well).
+It has another command line prompt and totally other commands
+and output.
+
+It follows the concept of separating outlets and outletgroups (if created).
+You can reach outlets via a fixed, not changeble "plug" number
+(from 1-20 on my device).
+Additionally one can, but does not need to assign names to each plug.
+
+Plugs/outlets can be combined to outletgroups.
+There can be zero to N (N = No. outlets) outletgroups.
+
+While it's possible to create outletgroups with one plug, this does not
+make sense and might slow things down.
+
+--plug=X paramter can be:
+1. X == outlet No
+2. X == outlet Name (if one got assigned)
+3. X == outlet group Name
+
+-> One cannot reach a group by number
+-> Groups need an extra call (first single outlet devices are
+ searched for given No/Name, then OutletGroups
+"""
+
+
+class FenceRaritanPX3:
+ outlets={}
+ # Plug id of outlet
+ plug=None
+ outletgroups={}
+ # Group name if outlet plug id/name have not been found
+ group_name=None
+
+def px3_get_outlet_group(conn, options):
+
+ conn.send_eol("show outletgroups")
+ conn.expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ for line in conn.after.splitlines():
+ split_line = line.split(" ")
+ """
+ Groups always have a name assigned:
+ ```
+ Outlet Group 1 - test:
+ Member outlets: 10-11
+ State: 2 on
+ ```
+ """
+ if len(split_line) == 5 and split_line[0] == "Outlet" and split_line[1] == "Group":
+ group_no = split_line[2]
+ group_name = split_line[4][:-1]
+
+ if len(split_line) > 0 and split_line[0] == "State:":
+ group_state = split_line[-1]
+ FenceRaritanPX3.outletgroups[group_no] = [ group_name, group_state ]
+ logging.debug("Outletgroups found:\n%s", FenceRaritanPX3.outletgroups)
+ return FenceRaritanPX3.outletgroups
+
+def px3_get_outlet_list(conn, options):
+
+ conn.send_eol("show outlets")
+ conn.expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ for line in conn.after.splitlines():
+ split_line = line.split(" ")
+ """
+ Plug with no name assigned:
+ ```
+ Outlet 1:
+ Power state: On
+ ```
+ """
+ if len(split_line) == 2 and split_line[0] == "Outlet":
+ outlet_no = split_line[1][:-1]
+ outlet_name = ""
+ """
+ Plug with name assigned:
+ ```
+ Outlet 8 - Test:
+ Power state: On
+ ```
+ """
+ if len(split_line) == 4 and split_line[0] == "Outlet":
+ outlet_no = split_line[1]
+ outlet_name = split_line[3][:-1]
+
+ # fetch state of previously parsed outlet from next line/iter
+ if len(split_line) == 3 and split_line[0] == "Power" and split_line[1] == "state:":
+ outlet_state = split_line[2]
+ FenceRaritanPX3.outlets[outlet_no] = [outlet_name, outlet_state]
+ logging.debug("Outlets found:\n%s", FenceRaritanPX3.outlets)
+ return FenceRaritanPX3.outlets
+
+def get_power_status(conn, options):
+
+ if FenceRaritanPX3.plug:
+ return FenceRaritanPX3.outlets[str(FenceRaritanPX3.plug)][1].lower()
+ elif FenceRaritanPX3.group_name:
+ return FenceRaritanPX3.outletgroups[FenceRaritanPX3.group_name][1].lower()
+ sys.exit(EC_STATUS)
+
+def set_power_status(conn, options):
+ action = {
+ "on" : "on",
+ "off" : "off",
+ "reboot" : "cycle",
+ }[options["--action"]]
+
+ if FenceRaritanPX3.plug:
+ conn.send_eol("power outlets %s %s" % (FenceRaritanPX3.plug, action))
+ # Do you wish to turn outlet 5 off? [y/n]
+ elif FenceRaritanPX3.group_name:
+ conn.send_eol("power outletgroup %s %s" % (FenceRaritanPX3.group_name, action))
+ # Do you wish to turn on all 2 outlets in group 1? [y/n]
+ conn.log_expect("Do you wish to turn.*", int(options["--shell-timeout"]))
+ conn.send_eol("y")
+ print("YYYYY")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ print("XXXXXXXX")
+
+def disconnect(conn):
+ conn.sendline("EXIT")
+ conn.close()
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "port", "telnet", "cmd_prompt", "secure"]
+
+ atexit.register(atexit_handler)
+
+ opt = process_input(device_opt)
+ all_opt["cmd_prompt"]["default"] = ".*\[My PDU\] #"
+ all_opt["ipport"]["default"] = "23"
+ all_opt["shell_timeout"]["default"] = "8"
+
+ opt["eol"] = "\r\n"
+ options = check_input(device_opt, opt)
+
+ docs = {}
+ docs["shortdesc"] = "I/O Fencing agent for Raritan Dominion PX2 and PX3"
+ docs["longdesc"] = "fence_raritan is an I/O Fencing agent which can be \
+used with the Raritan PX2 and PX3 Power Distribution Unit series. It logs into \
+device via telnet or ssh and reboots a specified outlet. Single outlets and \
+grouped outlets are supported. The fence is tested on this model: PX3-5466V. \
+There have been issues seen with the telnet prompt on 3.4.x and 3.5.x Raritan \
+firmware versions. It's recommended to update to at least version 3.6.x"
+ docs["vendorurl"] = "http://www.raritan.com/"
+ show_docs(options, docs)
+
+ conn = fence_login(options, re_login_string="Username.*")
+
+ px3_get_outlet_list(conn, options)
+ try:
+ FenceRaritanPX3.plug = int(options["--plug"])
+ if FenceRaritanPX3.plug > len(FenceRaritanPX3.outlets):
+ logging.error("Plug no exceeds no of outlets")
+ sys.exit(EC_STATUS)
+ except ValueError:
+ for no, values in FenceRaritanPX3.outlets.items():
+ if values[0] == options["--plug"]:
+ FenceRaritanPX3.plug = no
+ break
+ if not FenceRaritanPX3.plug:
+ px3_get_outlet_group(conn, options)
+ for no, values in FenceRaritanPX3.outletgroups.items():
+ if values[0] == options["--plug"]:
+ FenceRaritanPX3.group_name = no
+ break
+ if not FenceRaritanPX3.group_name:
+ logging.error("Plug %s not found", options["--plug"])
+ sys.exit(EC_STATUS)
+
+ logging.debug("\nSingle outlet: %s\nGroup outlet: %s" % (FenceRaritanPX3.plug, FenceRaritanPX3.group_name))
+
+ result = 0
+ if options["--action"] != "monitor":
+ result = fence_action(conn, options, set_power_status, get_power_status,
+ get_outlet_list=px3_get_outlet_list, reboot_cycle_fn=set_power_status)
+
+ atexit.register(disconnect, conn)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/rcd_serial/fence_rcd_serial.py b/agents/rcd_serial/fence_rcd_serial.py
new file mode 100644
index 0000000..2614772
--- /dev/null
+++ b/agents/rcd_serial/fence_rcd_serial.py
@@ -0,0 +1,100 @@
+#!@PYTHON@ -tt
+
+# Copyright 2018 Infoxchange, Danielle Madeley, Sam McLeod-Jones
+
+# Controls an RCD serial device
+# Ported from stonith/rcd_serial.c
+
+# The Following Agent Has Been Tested On:
+# CentOS Linux release 7.5.1804
+
+# Resource example:
+# primitive stonith_node_1 ocf:rcd_serial_py params port="/dev/ttyS0" time=1000 hostlist=stonith_node_1 stonith-timeout=5s
+
+import sys
+import atexit
+import os
+import struct
+import logging
+import time
+from fcntl import ioctl
+from termios import TIOCMBIC, TIOCMBIS, TIOCM_RTS, TIOCM_DTR
+from time import sleep
+
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+class RCDSerial(object):
+ """Control class for serial device"""
+
+ def __init__(self, port='/dev/ttyS0'):
+ self.fd = fd = os.open(port, os.O_RDONLY | os.O_NDELAY)
+ logging.debug("Opened %s on fd %i", port, fd)
+ ioctl(fd, TIOCMBIC, struct.pack('I', TIOCM_RTS | TIOCM_DTR))
+
+ def close(self):
+ """Close the serial device"""
+ logging.debug("Closing serial device")
+ ret = os.close(self.fd)
+
+ return ret
+
+ def toggle_pin(self, pin=TIOCM_DTR, time=1000):
+ """Toggle the pin high for the time specified"""
+
+ logging.debug("Set pin high")
+ ioctl(self.fd, TIOCMBIS, struct.pack('I', pin))
+
+ sleep(float(time) / 1000.)
+
+ logging.debug("Set pin low")
+ ioctl(self.fd, TIOCMBIC, struct.pack('I', pin))
+
+def reboot_device(conn, options):
+ conn.toggle_pin(time=options["--power-wait"])
+ return True
+
+def main():
+ device_opt = ["serial_port", "no_status", "no_password", "no_login", "method", "no_on", "no_off"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["serial_port"] = {
+ "getopt" : ":",
+ "longopt" : "serial-port",
+ "help":"--serial-port=[port] Port of the serial device (e.g. /dev/ttyS0)",
+ "required" : "1",
+ "shortdesc" : "Port of the serial device",
+ "default" : "/dev/ttyS0",
+ "order": 1
+ }
+
+ all_opt["method"]["default"] = "cycle"
+ all_opt["power_wait"]["default"] = "2"
+ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "rcd_serial fence agent"
+ docs["longdesc"] = "fence_rcd_serial operates a serial cable that toggles a \
+reset of an opposing server using the reset switch on its motherboard. The \
+cable itself is simple with no power, network or moving parts. An example of \
+the cable is available here: https://smcleod.net/rcd-stonith/ and the circuit \
+design is available in the fence-agents src as SVG"
+ docs["vendorurl"] = "https://github.com/sammcj/fence_rcd_serial"
+ show_docs(options, docs)
+
+ if options["--action"] in ["off", "reboot"]:
+ time.sleep(int(options["--delay"]))
+
+ ## Operate the fencing device
+ conn = RCDSerial(port=options["--serial-port"])
+ result = fence_action(conn, options, None, None, reboot_cycle_fn=reboot_device)
+ conn.close()
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
+
diff --git a/agents/rcd_serial/rcd_serial_cable_diagram.svg b/agents/rcd_serial/rcd_serial_cable_diagram.svg
new file mode 100644
index 0000000..36f219f
--- /dev/null
+++ b/agents/rcd_serial/rcd_serial_cable_diagram.svg
@@ -0,0 +1,276 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg viewBox="24 24 1460 442" preserveAspectRatio="xMinYMin meet" version="1.1" xmlns="http://www.w3.org/2000/svg">
+<g class="Diode">
+<line x1="320" y1="128" x2="342" y2="128" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="361" y1="128" x2="384" y2="128" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polygon fill="#000000" stroke="none" points="342,115 342,141 361,128 " />
+<polygon stroke="#000000" stroke-width="2" fill="none" points="342,115 342,141 361,128 " />
+<line x1="361" y1="115" x2="361" y2="141" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<text x="322" y="103" font-family="sans-serif">1N4148</text>
+</g>
+<g class="Diode">
+<line x1="320" y1="288" x2="342" y2="288" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="361" y1="288" x2="384" y2="288" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polygon fill="#000000" stroke="none" points="342,275 342,301 361,288 " />
+<polygon stroke="#000000" stroke-width="2" fill="none" points="342,275 342,301 361,288 " />
+<line x1="361" y1="275" x2="361" y2="301" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<text x="317" y="263" font-family="sans-serif">1N4148.</text>
+</g>
+<g class="Resistor">
+<line x1="448" y1="128" x2="464" y2="128" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="496" y1="128" x2="512" y2="128" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="464,128 466.6667,120 469.3333,128 472,136 474.6667,128 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="474.6667,128 477.3333,120 480,128 482.6667,136 485.3333,128 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="485.3333,128 488,120 490.6667,128 493.3333,136 496,128 " />
+<text x="465" y="113" font-family="sans-serif">10k</text>
+</g>
+<g class="Resistor">
+<line x1="448" y1="288" x2="464" y2="288" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="496" y1="288" x2="512" y2="288" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="464,288 466.6667,280 469.3333,288 472,296 474.6667,288 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="474.6667,288 477.3333,280 480,288 482.6667,296 485.3333,288 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="485.3333,288 488,280 490.6667,288 493.3333,296 496,288 " />
+<text x="465" y="273" font-family="sans-serif">10k</text>
+</g>
+<g class="Resistor">
+<line x1="576" y1="384" x2="576" y2="368" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="576" y1="336" x2="576" y2="320" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="576,368 568,365.3333 576,362.6667 584,360 576,357.3333 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="576,357.3333 568,354.6667 576,352 584,349.3333 576,346.6667 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="576,346.6667 568,344 576,341.3333 584,338.6667 576,336 " />
+<text x="591" y="357" font-family="sans-serif">20k</text>
+</g>
+<g class="Resistor">
+<line x1="672" y1="224" x2="672" y2="208" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="672" y1="176" x2="672" y2="160" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="672,208 664,205.3333 672,202.6667 680,200 672,197.3333 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="672,197.3333 664,194.6667 672,192 680,189.3333 672,186.6667 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="672,186.6667 664,184 672,181.3333 680,178.6667 672,176 " />
+<text x="687" y="197" font-family="sans-serif">120</text>
+</g>
+<g class="Wire">
+<line x1="448" y1="128" x2="384" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+<g class="Wire">
+<line x1="448" y1="288" x2="384" y2="288" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+<g class="Wire">
+<line x1="512" y1="288" x2="576" y2="288" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="576" cy="288" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="576" y1="288" x2="608" y2="288" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="576" cy="288" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="512" y1="128" x2="672" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="672" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="672" y1="128" x2="672" y2="160" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="672" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="672" y1="256" x2="672" y2="224" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+<g class="Wire">
+<line x1="672" y1="416" x2="576" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="672" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+<ellipse cx="576" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="320" y1="128" x2="288" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+<g class="Wire">
+<line x1="288" y1="288" x2="320" y2="288" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+<g class="Resistor">
+<line x1="800" y1="320" x2="800" y2="304" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="800" y1="272" x2="800" y2="256" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="800,304 792,301.3333 800,298.6667 808,296 800,293.3333 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="800,293.3333 792,290.6667 800,288 808,285.3333 800,282.6667 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="800,282.6667 792,280 800,277.3333 808,274.6667 800,272 " />
+<text x="815" y="293" font-family="sans-serif">100k</text>
+</g>
+<g class="Capacitor">
+<line x1="896" y1="320" x2="896" y2="292" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="884" y1="292" x2="908" y2="292" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="896" y1="256" x2="896" y2="284" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<path d="M 907.313708566442 279.313708431527 A 16 16 0 0 1 884.686291748284 279.313708746254" stroke="#000000" stroke-width="3" fill="none" />
+<text x="918" y="293" font-family="sans-serif">100uF</text>
+</g>
+<g class="Wire">
+<line x1="800" y1="256" x2="800" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="800" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="896" y1="256" x2="896" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="896" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="896" y1="128" x2="800" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="896" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+<ellipse cx="800" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="896" y1="416" x2="800" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="896" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+<ellipse cx="800" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="LED">
+<line x1="992" y1="160" x2="992" y2="182" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="992" y1="201" x2="992" y2="224" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polygon fill="#FFFFFF" stroke="none" points="1005,182 979,182 992,201 " />
+<polygon stroke="#000000" stroke-width="2" fill="none" points="1005,182 979,182 992,201 " />
+<line x1="1005" y1="201" x2="979" y2="201" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<text x="1013" y="197" font-family="sans-serif">Red LED</text>
+<line x1="1003" y1="192" x2="1007" y2="195" stroke="#000000" stroke-width="2" stroke-linecap="round" fill="none" />
+<line x1="1006" y1="188" x2="1010" y2="191" stroke="#000000" stroke-width="2" stroke-linecap="round" fill="none" />
+</g>
+<g class="LED">
+<line x1="992" y1="288" x2="992" y2="310" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="992" y1="329" x2="992" y2="352" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polygon fill="#FFFFFF" stroke="none" points="1005,310 979,310 992,329 " />
+<polygon stroke="#000000" stroke-width="2" fill="none" points="1005,310 979,310 992,329 " />
+<line x1="1005" y1="329" x2="979" y2="329" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="1003" y1="320" x2="1007" y2="323" stroke="#000000" stroke-width="2" stroke-linecap="round" fill="none" />
+<line x1="1006" y1="316" x2="1010" y2="319" stroke="#000000" stroke-width="2" stroke-linecap="round" fill="none" />
+</g>
+<g class="BJT Transistor (NPN)">
+<line x1="1088" y1="288" x2="1060" y2="308" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="1088" y1="352" x2="1060" y2="332" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polygon fill="#000000" stroke="none" points="1088,352 1080,336 1070,349 " />
+<line x1="1024" y1="320" x2="1056" y2="320" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polygon fill="#000000" stroke="none" points="1056,294 1062,294 1062,346 1056,346 " />
+<text x="1087" y="325" font-family="sans-serif">PS2501 Optocoupler</text>
+<ellipse cx="1024" cy="320" rx="4" ry="4" stroke="#000000" stroke-width="1" fill="none" />
+</g>
+<g class="Wire">
+<line x1="992" y1="288" x2="992" y2="224" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<text x="1007" y="261" font-family="sans-serif">1</text>
+</g>
+<g class="Port">
+<polygon fill="#FFFFFF" stroke="none" points="1184,256 1192,246 1248,246 1248,266 1192,266 " />
+<polygon stroke="#000000" stroke-width="1" fill="none" points="1184,256 1192,246 1248,246 1248,266 1192,266 " />
+<text x="1211" y="261" font-family="sans-serif">1</text>
+<text x="1256" y="261" font-family="sans-serif">RWL</text>
+</g>
+<g class="Port">
+<polygon fill="#FFFFFF" stroke="none" points="1184,384 1192,374 1248,374 1248,394 1192,394 " />
+<polygon stroke="#000000" stroke-width="1" fill="none" points="1184,384 1192,374 1248,374 1248,394 1192,394 " />
+<text x="1211" y="389" font-family="sans-serif">2</text>
+<text x="1256" y="389" font-family="sans-serif">RWG</text>
+</g>
+<g class="Port">
+<polygon fill="#FFFFFF" stroke="none" points="288,128 280,138 224,138 224,118 280,118 " />
+<polygon stroke="#000000" stroke-width="1" fill="none" points="288,128 280,138 224,138 224,118 280,118 " />
+<text x="251" y="133" font-family="sans-serif">7</text>
+<text x="186" y="133" font-family="sans-serif">RTS</text>
+</g>
+<g class="Port">
+<polygon fill="#FFFFFF" stroke="none" points="288,288 280,298 224,298 224,278 280,278 " />
+<polygon stroke="#000000" stroke-width="1" fill="none" points="288,288 280,298 224,298 224,278 280,278 " />
+<text x="251" y="293" font-family="sans-serif">4</text>
+<text x="186" y="293" font-family="sans-serif">DTR</text>
+</g>
+<g class="Port">
+<polygon fill="#FFFFFF" stroke="none" points="288,416 280,426 224,426 224,406 280,406 " />
+<polygon stroke="#000000" stroke-width="1" fill="none" points="288,416 280,426 224,426 224,406 280,406 " />
+<text x="251" y="421" font-family="sans-serif">5</text>
+<text x="196" y="421" font-family="sans-serif">SG</text>
+</g>
+<g class="Wire">
+<line x1="576" y1="416" x2="288" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="576" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="896" y1="416" x2="992" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="896" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="896" y1="128" x2="992" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="896" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="992" y1="160" x2="992" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+<g class="Wire">
+<line x1="1088" y1="256" x2="1184" y2="256" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<text x="1131" y="241" font-family="sans-serif">4</text>
+</g>
+<g class="Wire">
+<line x1="1088" y1="384" x2="1184" y2="384" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<text x="1131" y="369" font-family="sans-serif">3</text>
+</g>
+<g class="RS232 Serial Connector">
+<rect x="56" y="248" width="106" height="62" fill="#FFFFFF" stroke="none" />
+<rect x="56" y="248" width="106" height="62" rx="5" ry="5" stroke="#000000" stroke-width="2" fill="none" />
+<text x="84" y="266" font-family="sans-serif">RS232</text>
+<text x="79" y="284" font-family="sans-serif">Serial</text>
+<text x="64" y="302" font-family="sans-serif">Connector</text>
+</g>
+<g class="Motherboard Reset Pins">
+<rect x="1304" y="280" width="126" height="62" fill="#FFFFFF" stroke="none" />
+<rect x="1304" y="280" width="126" height="62" rx="5" ry="5" stroke="#000000" stroke-width="2" fill="none" />
+<text x="1312" y="298" font-family="sans-serif">Motherboard</text>
+<text x="1342" y="316" font-family="sans-serif">Reset</text>
+<text x="1347" y="334" font-family="sans-serif">Pins</text>
+</g>
+<g class="n-MOSFET">
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="640,312 672,312 672,320 " />
+<polyline stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" fill="none" points="640,264 672,264 672,256 " />
+<line x1="640" y1="312" x2="640" y2="288" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="640" y1="288" x2="640" y2="264" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="640" y1="312" x2="640" y2="320" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="640" y1="264" x2="640" y2="256" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<polygon fill="#000000" stroke="none" points="672,312 656,304 656,320 " />
+<line x1="608" y1="288" x2="630" y2="288" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<line x1="630" y1="264" x2="630" y2="312" stroke="#000000" stroke-width="3" stroke-linecap="round" fill="none" />
+<text x="679" y="293" font-family="sans-serif">6512A-ND1</text>
+</g>
+<g class="Wire">
+<line x1="672" y1="128" x2="800" y2="128" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="672" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+<ellipse cx="800" cy="128" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="672" y1="416" x2="800" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="672" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+<ellipse cx="800" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="576" y1="288" x2="576" y2="320" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="576" cy="288" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="576" y1="384" x2="576" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="576" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="992" y1="352" x2="992" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<text x="1007" y="389" font-family="sans-serif">2</text>
+</g>
+<g class="Wire">
+<line x1="672" y1="320" x2="672" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="672" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="896" y1="320" x2="896" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="896" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Wire">
+<line x1="800" y1="320" x2="800" y2="416" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+<ellipse cx="800" cy="416" rx="4" ry="4" fill="#000000" stroke="none" />
+</g>
+<g class="Delayed Serial Cable For STONITH">
+<rect x="536" y="56" width="336" height="26" fill="#FFFFFF" stroke="none" />
+<text x="544" y="74" font-family="sans-serif">Delayed Serial Cable For STONITH</text>
+</g>
+<g class="Wire">
+<line x1="1088" y1="256" x2="1088" y2="288" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+<g class="Wire">
+<line x1="1088" y1="384" x2="1088" y2="352" stroke="#000000" stroke-width="1.5" stroke-linecap="round" fill="none" />
+</g>
+</svg>
diff --git a/agents/redfish/fence_redfish.py b/agents/redfish/fence_redfish.py
new file mode 100644
index 0000000..0f5af52
--- /dev/null
+++ b/agents/redfish/fence_redfish.py
@@ -0,0 +1,177 @@
+#!@PYTHON@ -tt
+
+# Copyright (c) 2018 Dell Inc. or its subsidiaries. All Rights Reserved.
+
+# Fence agent for devices that support the Redfish API Specification.
+
+import sys
+import re
+import logging
+import json
+import requests
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+
+from fencing import *
+from fencing import fail_usage, run_delay
+
+GET_HEADERS = {'accept': 'application/json', 'OData-Version': '4.0'}
+POST_HEADERS = {'content-type': 'application/json', 'accept': 'application/json',
+ 'OData-Version': '4.0'}
+
+
+def get_power_status(conn, options):
+ response = send_get_request(options, options["--systems-uri"])
+ if response['ret'] is False:
+ fail_usage("Couldn't get power information")
+ data = response['data']
+
+ try:
+ logging.debug("PowerState is: " + data[u'PowerState'])
+ except Exception:
+ fail_usage("Unable to get PowerState: " + "https://" + options["--ip"] + ":" + str(options["--ipport"]) + options["--systems-uri"])
+
+ if data[u'PowerState'].strip() == "Off":
+ return "off"
+ else:
+ return "on"
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "On",
+ 'off': "ForceOff",
+ 'reboot': "ForceRestart",
+ 'diag': "Nmi"
+ }[options.get("original-action") or options["--action"]]
+
+ payload = {'ResetType': action}
+
+ # Search for 'Actions' key and extract URI from it
+ response = send_get_request(options, options["--systems-uri"])
+ if response['ret'] is False:
+ return {'ret': False}
+ data = response['data']
+ action_uri = data["Actions"]["#ComputerSystem.Reset"]["target"]
+
+ response = send_post_request(options, action_uri, payload)
+ if response['ret'] is False:
+ fail_usage("Error sending power command")
+ if options.get("original-action") == "diag":
+ return True
+ return
+
+def send_get_request(options, uri):
+ full_uri = "https://" + options["--ip"] + ":" + str(options["--ipport"]) + uri
+ try:
+ resp = requests.get(full_uri, verify=not "--ssl-insecure" in options,
+ headers=GET_HEADERS,
+ auth=(options["--username"], options["--password"]))
+ data = resp.json()
+ except Exception as e:
+ fail_usage("Failed: send_get_request: " + str(e))
+ return {'ret': True, 'data': data}
+
+def send_post_request(options, uri, payload):
+ full_uri = "https://" + options["--ip"] + ":" + str(options["--ipport"]) + uri
+ try:
+ requests.post(full_uri, data=json.dumps(payload),
+ headers=POST_HEADERS, verify=not "--ssl-insecure" in options,
+ auth=(options["--username"], options["--password"]))
+ except Exception as e:
+ fail_usage("Failed: send_post_request: " + str(e))
+ return {'ret': True}
+
+def find_systems_resource(options):
+ response = send_get_request(options, options["--redfish-uri"])
+ if response['ret'] is False:
+ return {'ret': False}
+ data = response['data']
+
+ if 'Systems' not in data:
+ # Systems resource not found"
+ return {'ret': False}
+ else:
+ response = send_get_request(options, data["Systems"]["@odata.id"])
+ if response['ret'] is False:
+ return {'ret': False}
+ data = response['data']
+
+ # need to be able to handle more than one entry
+ for member in data[u'Members']:
+ system_uri = member[u'@odata.id']
+ return {'ret': True, 'uri': system_uri}
+
+def define_new_opts():
+ all_opt["redfish-uri"] = {
+ "getopt" : ":",
+ "longopt" : "redfish-uri",
+ "help" : "--redfish-uri=[uri] Base or starting Redfish URI",
+ "required" : "0",
+ "default" : "/redfish/v1",
+ "shortdesc" : "Base or starting Redfish URI",
+ "order": 1
+ }
+ all_opt["systems-uri"] = {
+ "getopt" : ":",
+ "longopt" : "systems-uri",
+ "help" : "--systems-uri=[uri] Redfish Systems resource URI",
+ "required" : "0",
+ "shortdesc" : "Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1",
+ "order": 1
+ }
+
+def main():
+ atexit.register(atexit_handler)
+ device_opt = ["ipaddr", "login", "passwd", "redfish-uri", "systems-uri",
+ "ssl", "diag"]
+ define_new_opts()
+
+ opt = process_input(device_opt)
+
+ all_opt["ssl"]["default"] = "1"
+ options = check_input(device_opt, opt)
+
+ docs = {}
+ docs["shortdesc"] = "I/O Fencing agent for Redfish"
+ docs["longdesc"] = "fence_redfish is an I/O Fencing agent which can be used with \
+Out-of-Band controllers that support Redfish APIs. These controllers provide remote \
+access to control power on a server."
+ docs["vendorurl"] = "http://www.dmtf.org"
+ show_docs(options, docs)
+ run_delay(options)
+
+ ##
+ ## Operate the fencing device
+ ####
+
+ # Disable insecure-certificate-warning message
+ if "--ssl-insecure" in opt:
+ import urllib3
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+ # backwards compatibility for <ip>:<port>
+ if options["--ip"].count(":") == 1:
+ (options["--ip"], options["--ipport"]) = options["--ip"].split(":")
+
+ if "--systems-uri" not in opt:
+ # Systems URI not provided, find it
+ sysresult = find_systems_resource(options)
+ if sysresult['ret'] is False:
+ sys.exit(1)
+ else:
+ options["--systems-uri"] = sysresult["uri"]
+
+ reboot_fn = None
+ if options["--action"] == "diag":
+ # Diag is a special action that can't be verified so we will reuse reboot functionality
+ # to minimize impact on generic library
+ options["original-action"] = options["--action"]
+ options["--action"] = "reboot"
+ options["--method"] = "cycle"
+ reboot_fn = set_power_status
+
+ result = fence_action(None, options, set_power_status, get_power_status, None, reboot_fn)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/rhevm/fence_rhevm.py b/agents/rhevm/fence_rhevm.py
new file mode 100644
index 0000000..5f74d06
--- /dev/null
+++ b/agents/rhevm/fence_rhevm.py
@@ -0,0 +1,249 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import pycurl, io
+import logging
+import atexit
+import tempfile
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_FETCH_VM_UUID, run_delay
+
+RE_GET_ID = re.compile("<vm( .*)? id=\"(.*?)\"", re.IGNORECASE)
+RE_STATUS = re.compile("<status>(.*?)</status>", re.IGNORECASE)
+RE_STATE = re.compile("<state>(.*?)</state>", re.IGNORECASE)
+RE_GET_NAME = re.compile("<name>(.*?)</name>", re.IGNORECASE)
+
+def get_power_status(conn, options):
+ del conn
+
+ ### Obtain real ID from name
+ res = send_command(options, "vms/?search=name%3D" + options["--plug"])
+
+ result = RE_GET_ID.search(res)
+ if result == None:
+ # Unable to obtain ID needed to access virtual machine
+ fail(EC_FETCH_VM_UUID)
+
+ options["id"] = result.group(2)
+
+ if tuple(map(int, options["--api-version"].split(".")))[0] > 3:
+ result = RE_STATUS.search(res)
+ else:
+ result = RE_STATE.search(res)
+ if result == None:
+ # We were able to parse ID so output is correct
+ # in some cases it is possible that RHEV-M output does not
+ # contain <status> line. We can assume machine is OFF then
+ return "off"
+ else:
+ status = result.group(1)
+
+ if status.lower() == "down":
+ return "off"
+ else:
+ return "on"
+
+def set_power_status(conn, options):
+ del conn
+ action = {
+ 'on' : "start",
+ 'off' : "stop"
+ }[options["--action"]]
+
+ url = "vms/" + options["id"] + "/" + action
+ send_command(options, url, "POST")
+
+def get_list(conn, options):
+ del conn
+ outlets = {}
+
+ try:
+ res = send_command(options, "vms")
+
+ lines = res.split("<vm ")
+ for i in range(1, len(lines)):
+ name = RE_GET_NAME.search(lines[i]).group(1)
+ if tuple(map(int, options["--api-version"].split(".")))[0] > 3:
+ status = RE_STATUS.search(lines[i]).group(1)
+ else:
+ status = RE_STATE.search(lines[i]).group(1)
+ outlets[name] = ("", status)
+ except AttributeError:
+ return {}
+ except IndexError:
+ return {}
+
+ return outlets
+
+def send_command(opt, command, method="GET"):
+ if opt["--api-version"] == "auto":
+ opt["--api-version"] = "4"
+ res = send_command(opt, "")
+ if re.search("<title>Error</title>", res):
+ opt["--api-version"] = "3"
+ logging.debug("auto-detected API version: " + opt["--api-version"])
+
+ ## setup correct URL
+ if "--ssl-secure" in opt or "--ssl-insecure" in opt:
+ url = "https:"
+ else:
+ url = "http:"
+ if "--api-path" in opt:
+ api_path = opt["--api-path"]
+ else:
+ api_path = "/ovirt-engine/api"
+ if "--disable-http-filter" in opt:
+ http_filter = 'false'
+ else:
+ http_filter = 'true'
+
+ url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + api_path + "/" + command
+
+ ## send command through pycurl
+ conn = pycurl.Curl()
+ web_buffer = io.BytesIO()
+ conn.setopt(pycurl.URL, url.encode("UTF-8"))
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Version: {}".format(opt["--api-version"]),
+ "Content-type: application/xml",
+ "Accept: application/xml",
+ "Prefer: persistent-auth",
+ "Filter: {}".format(http_filter),
+ ])
+
+ if "cookie" in opt:
+ conn.setopt(pycurl.COOKIE, opt["cookie"])
+ else:
+ conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
+ conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"])
+ if "--use-cookies" in opt:
+ if "--cookie-file" in opt:
+ cookie_file = opt["--cookie-file"]
+ else:
+ cookie_file = tempfile.gettempdir() + "/fence_rhevm_" + opt["--ip"] + "_" + opt["--username"] + "_cookie.dat"
+ conn.setopt(pycurl.COOKIEFILE, cookie_file)
+ conn.setopt(pycurl.COOKIEJAR, cookie_file)
+
+ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
+
+ if "--ssl-secure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ elif "--ssl-insecure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+
+ if method == "POST":
+ conn.setopt(pycurl.POSTFIELDS, "<action />")
+
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+ conn.perform()
+
+ if "cookie" not in opt and "--use-cookies" in opt:
+ cookie = ""
+ for c in conn.getinfo(pycurl.INFO_COOKIELIST):
+ tokens = c.split("\t",7)
+ cookie = cookie + tokens[5] + "=" + tokens[6] + ";"
+
+ opt["cookie"] = cookie
+
+ result = web_buffer.getvalue().decode("UTF-8")
+
+ logging.debug("url: %s\n", url.encode("UTF-8"))
+ logging.debug("command: %s\n", command.encode("UTF-8"))
+ logging.debug("result: %s\n", result.encode("UTF-8"))
+
+ return result
+
+def define_new_opts():
+
+ all_opt["port"] = {
+ "getopt" : "n:",
+ "longopt" : "plug",
+ "help" : "-n, --plug=[name] "
+ "VM name in RHV",
+ "required" : "1",
+ "order" : 1}
+ all_opt["use_cookies"] = {
+ "getopt" : "",
+ "longopt" : "use-cookies",
+ "help" : "--use-cookies Reuse cookies for authentication",
+ "required" : "0",
+ "shortdesc" : "Reuse cookies for authentication",
+ "order" : 1}
+ all_opt["cookie_file"] = {
+ "getopt" : ":",
+ "longopt" : "cookie-file",
+ "help" : "--cookie-file Path to cookie file for authentication\n"
+ "\t\t\t\t (Default: /tmp/fence_rhevm_ip_username_cookie.dat)",
+ "required" : "0",
+ "shortdesc" : "Path to cookie file for authentication",
+ "order" : 2}
+ all_opt["api_version"] = {
+ "getopt" : ":",
+ "longopt" : "api-version",
+ "help" : "--api-version "
+ "Version of RHEV API (default: auto)",
+ "required" : "0",
+ "order" : 2,
+ "default" : "auto",
+ }
+ all_opt["api_path"] = {
+ "getopt" : ":",
+ "longopt" : "api-path",
+ "help" : "--api-path=[path] The path part of the API URL",
+ "default" : "/ovirt-engine/api",
+ "required" : "0",
+ "shortdesc" : "The path part of the API URL",
+ "order" : 3}
+ all_opt["disable_http_filter"] = {
+ "getopt" : "",
+ "longopt" : "disable-http-filter",
+ "help" : "--disable-http-filter Set HTTP Filter header to false",
+ "required" : "0",
+ "shortdesc" : "Set HTTP Filter header to false",
+ "order" : 4}
+
+
+def main():
+ device_opt = [
+ "ipaddr",
+ "login",
+ "passwd",
+ "ssl",
+ "notls",
+ "web",
+ "port",
+ "use_cookies",
+ "cookie_file",
+ "api_version",
+ "api_path",
+ "disable_http_filter",
+ ]
+
+ atexit.register(atexit_handler)
+ define_new_opts()
+
+ all_opt["power_wait"]["default"] = "1"
+ all_opt["shell_timeout"]["default"] = "5"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for RHEV-M REST API"
+ docs["longdesc"] = "fence_rhevm is an I/O Fencing agent which can be \
+used with RHEV-M REST API to fence virtual machines."
+ docs["vendorurl"] = "http://www.redhat.com"
+ show_docs(options, docs)
+
+ ##
+ ## Fence operations
+ ####
+ run_delay(options)
+ result = fence_action(None, options, set_power_status, get_power_status, get_list)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/rsa/fence_rsa.py b/agents/rsa/fence_rsa.py
new file mode 100644
index 0000000..44fdd9d
--- /dev/null
+++ b/agents/rsa/fence_rsa.py
@@ -0,0 +1,63 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+## Main GFEP25A & Boot GFBP25A
+##
+#####
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+def get_power_status(conn, options):
+ conn.send_eol("power state")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ match = re.compile("Power: (.*)", re.IGNORECASE).search(conn.before)
+ if match != None:
+ status = match.group(1)
+ else:
+ status = "undefined"
+
+ return status.lower().strip()
+
+def set_power_status(conn, options):
+ conn.send_eol("power " + options["--action"])
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["login_timeout"]["default"] = 10
+ all_opt["cmd_prompt"]["default"] = [">"]
+ # This device will not allow us to login even with LANG=C
+ all_opt["ssh_options"]["default"] = "-F /dev/null"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IBM RSA"
+ docs["longdesc"] = "fence_rsa is an I/O Fencing agent \
+which can be used with the IBM RSA II management interface. It \
+logs into an RSA II device via telnet and reboots the associated \
+machine. Lengthy telnet connections to the RSA II device should \
+be avoided while a GFS cluster is running because the connection \
+will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ######
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, None)
+ fence_logout(conn, "exit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/rsb/fence_rsb.py b/agents/rsb/fence_rsb.py
new file mode 100755
index 0000000..45355f5
--- /dev/null
+++ b/agents/rsb/fence_rsb.py
@@ -0,0 +1,70 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+def get_power_status(conn, options):
+ conn.send("2")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ status = re.compile(r"Power Status[\s]*: (on|off)", re.IGNORECASE).search(conn.before).group(1)
+ conn.send("0")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ return status.lower().strip()
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "4",
+ 'off': "1"
+ }[options["--action"]]
+
+ conn.send("2")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.send_eol(action)
+ conn.log_expect(["want to power " + options["--action"],
+ "yes/no", "'yes' or 'no'"], int(options["--shell-timeout"]))
+ conn.send_eol("yes")
+ conn.log_expect("any key to continue", int(options["--power-timeout"]))
+ conn.send_eol("")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ conn.send_eol("0")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure", "cmd_prompt", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["to quit:"]
+
+ opt = process_input(device_opt)
+
+ if "--ssh" not in opt and "--ipport" not in opt:
+ # set default value like it should be set as usually
+ all_opt["ipport"]["default"] = "3172"
+ opt["--ipport"] = all_opt["ipport"]["default"]
+
+ options = check_input(device_opt, opt)
+
+ docs = {}
+ docs["shortdesc"] = "I/O Fencing agent for Fujitsu-Siemens RSB"
+ docs["longdesc"] = "fence_rsb is an I/O Fencing agent \
+which can be used with the Fujitsu-Siemens RSB management interface. It logs \
+into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh \
+connections should be avoided while a GFS cluster is running because the connection \
+will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.fujitsu.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, None)
+ fence_logout(conn, "0")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/sanbox2/fence_sanbox2.py b/agents/sanbox2/fence_sanbox2.py
new file mode 100644
index 0000000..179fe0e
--- /dev/null
+++ b/agents/sanbox2/fence_sanbox2.py
@@ -0,0 +1,155 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Version Firmware
+## +-----------------+---------------------------+
+#####
+
+import sys, re, pexpect
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_TIMED_OUT, EC_GENERIC_ERROR
+
+def get_power_status(conn, options):
+ status_trans = {
+ 'online' : "on",
+ 'offline' : "off"
+ }
+ try:
+ conn.send_eol("show port " + options["--plug"])
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ except pexpect.TIMEOUT:
+ try:
+ conn.send_eol("admin end")
+ conn.send_eol("exit")
+ conn.close()
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ pass
+ fail(EC_TIMED_OUT)
+
+ status = re.compile(r".*AdminState\s+(online|offline)\s+",
+ re.IGNORECASE | re.MULTILINE).search(conn.before).group(1)
+
+ try:
+ return status_trans[status.lower().strip()]
+ except KeyError:
+ return "PROBLEM"
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "online",
+ 'off' : "offline"
+ }[options["--action"]]
+
+ try:
+ conn.send_eol("set port " + options["--plug"] + " state " + action)
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ except pexpect.TIMEOUT:
+ try:
+ conn.send_eol("admin end")
+ conn.send_eol("exit")
+ conn.close()
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ pass
+ fail(EC_TIMED_OUT)
+
+ try:
+ conn.send_eol("set port " + options["--plug"] + " state " + action)
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ except pexpect.TIMEOUT:
+ try:
+ conn.send_eol("admin end")
+ conn.send_eol("exit")
+ conn.close()
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ pass
+ fail(EC_TIMED_OUT)
+
+def get_list_devices(conn, options):
+ outlets = {}
+
+ try:
+ conn.send_eol("show port")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ list_re = re.compile(r"^\s+(\d+?)\s+(Online|Offline)\s+", re.IGNORECASE)
+ for line in conn.before.splitlines():
+ if list_re.search(line):
+ status = {
+ 'online' : "ON",
+ 'offline' : "OFF"
+ }[list_re.search(line).group(2).lower()]
+ outlets[list_re.search(line).group(1)] = ("", status)
+
+ except pexpect.TIMEOUT:
+ try:
+ conn.send_eol("admin end")
+ conn.send_eol("exit")
+ conn.close()
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ pass
+ fail(EC_TIMED_OUT)
+
+ return outlets
+
+def main():
+ device_opt = ["fabric_fencing", "ipaddr", "login", "passwd", "cmd_prompt", \
+ "port", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = [" #> "]
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for QLogic SANBox2 FC switches"
+ docs["longdesc"] = "fence_sanbox2 is an I/O Fencing agent which can be used with \
+QLogic SANBox2 FC switches. It logs into a SANBox2 switch via telnet and disables a specified \
+port. Disabling the port which a machine is connected to effectively fences that machine. \
+Lengthy telnet connections to the switch should be avoided while a GFS cluster is running \
+because the connection will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.qlogic.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ##
+ conn = fence_login(options)
+
+ conn.send_eol("admin start")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ if re.search(r"\(admin\)", conn.before, re.MULTILINE) == None:
+ ## Someone else is in admin section, we can't enable/disable
+ ## ports so we will rather exit
+ logging.error("Failed: Unable to switch to admin section\n")
+ sys.exit(EC_GENERIC_ERROR)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_list_devices)
+
+ ##
+ ## Logout from system
+ ######
+ try:
+ conn.send_eol("admin end")
+ conn.send_eol("exit\n")
+ conn.close()
+ except OSError:
+ pass
+ except pexpect.ExceptionPexpect:
+ pass
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/sbd/fence_sbd.py b/agents/sbd/fence_sbd.py
new file mode 100644
index 0000000..2b0127d
--- /dev/null
+++ b/agents/sbd/fence_sbd.py
@@ -0,0 +1,435 @@
+#!@PYTHON@ -tt
+
+import sys, stat
+import logging
+import os
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import fail_usage, run_commands, fence_action, all_opt
+from fencing import atexit_handler, check_input, process_input, show_docs
+from fencing import run_delay
+import itertools
+
+DEVICE_INIT = 1
+DEVICE_NOT_INIT = -3
+PATH_NOT_EXISTS = -1
+PATH_NOT_BLOCK = -2
+
+def is_block_device(filename):
+ """Checks if a given path is a valid block device
+
+ Key arguments:
+ filename -- the file to check
+
+ Return codes:
+ True if it's a valid block device
+ False, otherwise
+ """
+
+ try:
+ mode = os.lstat(filename).st_mode
+ except OSError:
+ return False
+ else:
+ return stat.S_ISBLK(mode)
+
+def is_link(filename):
+ """Checks if a given path is a link.
+
+ Key arguments:
+ filename -- the file to check
+
+ Return codes:
+ True if it's a link
+ False, otherwise
+ """
+
+ try:
+ mode = os.lstat(filename).st_mode
+ except OSError:
+ return False
+ else:
+ return stat.S_ISLNK(mode)
+
+def check_sbd_device(options, device_path):
+ """checks that a given sbd device exists and is initialized
+
+ Key arguments:
+ options -- options dictionary
+ device_path -- device path to check
+
+ Return Codes:
+ 1 / DEVICE_INIT if the device exists and is initialized
+ -1 / PATH_NOT_EXISTS if the path does not exists
+ -2 / PATH_NOT_BLOCK if the path exists but is not a valid block device
+ -3 / DEVICE_NOT_INIT if the sbd device is not initialized
+ """
+
+ # First of all we need to check if the device is valid
+ if not os.path.exists(device_path):
+ return PATH_NOT_EXISTS
+
+ # We need to check if device path is a symbolic link. If so we resolve that
+ # link.
+ if is_link(device_path):
+ link_target = os.readlink(device_path)
+ device_path = os.path.join(os.path.dirname(device_path), link_target)
+
+ # As second step we make sure it's a valid block device
+ if not is_block_device(device_path):
+ return PATH_NOT_BLOCK
+
+ cmd = "%s -d %s dump" % (options["--sbd-path"], device_path)
+
+ (return_code, out, err) = run_commands(options, [ cmd ])
+
+ for line in itertools.chain(out.split("\n"), err.split("\n")):
+ if len(line) == 0:
+ continue
+
+ # If we read "NOT dumped" something went wrong, e.g. the device is not
+ # initialized.
+ if "NOT dumped" in line:
+ return DEVICE_NOT_INIT
+
+ return DEVICE_INIT
+
+
+def generate_sbd_command(options, command, arguments=None):
+ """Generates a sbd command based on given arguments.
+
+ Return Value:
+ generated list of sbd commands (strings) depending
+ on command multiple commands with a device each
+ or a single command with multiple devices
+ """
+ cmds = []
+
+ if not command in ["list", "dump"]:
+ cmd = options["--sbd-path"]
+
+ # add "-d" for each sbd device
+ for device in parse_sbd_devices(options):
+ cmd += " -d %s" % device
+
+ cmd += " %s %s" % (command, arguments)
+ cmds.append(cmd)
+
+ else:
+ for device in parse_sbd_devices(options):
+ cmd = options["--sbd-path"]
+ cmd += " -d %s" % device
+ cmd += " %s %s" % (command, arguments)
+ cmds.append(cmd)
+
+ return cmds
+
+def send_sbd_message(conn, options, plug, message):
+ """Sends a message to all sbd devices.
+
+ Key arguments:
+ conn -- connection structure
+ options -- options dictionary
+ plug -- plug to sent the message to
+ message -- message to send
+
+ Return Value:
+ (return_code, out, err) Tuple containing the error code,
+ """
+
+ del conn
+
+ arguments = "%s %s" % (plug, message)
+ cmd = generate_sbd_command(options, "message", arguments)
+
+ (return_code, out, err) = run_commands(options, cmd)
+
+ return (return_code, out, err)
+
+def get_msg_timeout(options):
+ """Reads the configured sbd message timeout from each device.
+
+ Key arguments:
+ options -- options dictionary
+
+ Return Value:
+ msg_timeout (integer, seconds)
+ """
+
+ # get the defined msg_timeout
+ msg_timeout = -1 # default sbd msg timeout
+
+ cmd = generate_sbd_command(options, "dump")
+
+ (return_code, out, err) = run_commands(options, cmd)
+
+ for line in itertools.chain(out.split("\n"), err.split("\n")):
+ if len(line) == 0:
+ continue
+
+ if "msgwait" in line:
+ tmp_msg_timeout = int(line.split(':')[1])
+ if -1 != msg_timeout and tmp_msg_timeout != msg_timeout:
+ logging.warn(\
+ "sbd message timeouts differ in different devices")
+ # we only save the highest timeout
+ if tmp_msg_timeout > msg_timeout:
+ msg_timeout = tmp_msg_timeout
+
+ return msg_timeout
+
+def set_power_status(conn, options):
+ """send status to sbd device (poison pill)
+
+ Key arguments:
+ conn -- connection structure
+ options -- options dictionary
+
+ Return Value:
+ return_code -- action result (bool)
+ """
+
+ target_status = options["--action"]
+ plug = options["--plug"]
+ return_code = 99
+ out = ""
+ err = ""
+
+ # Map fencing actions to sbd messages
+ if "on" == target_status:
+ (return_code, out, err) = send_sbd_message(conn, options, plug, "clear")
+ elif "off" == target_status:
+ (return_code, out, err) = send_sbd_message(conn, options, plug, "off")
+ elif "reboot" == target_status:
+ (return_code, out, err) = send_sbd_message(conn, options, plug, "reset")
+
+ if 0 != return_code:
+ logging.error("sending message to sbd device(s) \
+ failed with return code %d", return_code)
+ logging.error("DETAIL: output on stdout was \"%s\"", out)
+ logging.error("DETAIL: output on stderr was \"%s\"", err)
+
+ return not bool(return_code)
+
+def reboot_cycle(conn, options):
+ """" trigger reboot by sbd messages
+
+ Key arguments:
+ conn -- connection structure
+ options -- options dictionary
+
+ Return Value:
+ return_code -- action result (bool)
+ """
+
+ plug = options["--plug"]
+ return_code = 99
+ out = ""
+ err = ""
+
+ (return_code, out, err) = send_sbd_message(conn, options, plug, "reset")
+ return not bool(return_code)
+
+def get_power_status(conn, options):
+ """Returns the status of a specific node.
+
+ Key arguments:
+ conn -- connection structure
+ options -- option dictionary
+
+ Return Value:
+ status -- status code (string)
+ """
+
+ status = "UNKWNOWN"
+ plug = options["--plug"]
+
+ nodelist = get_node_list(conn, options)
+
+ # We need to check if the specified plug / node a already a allocated slot
+ # on the device.
+ if plug not in nodelist:
+ logging.error("node \"%s\" not found in node list", plug)
+ else:
+ status = nodelist[plug][1]
+
+
+ return status
+
+def translate_status(sbd_status):
+ """Translates the sbd status to fencing status.
+
+ Key arguments:
+ sbd_status -- status to translate (string)
+
+ Return Value:
+ status -- fencing status (string)
+ """
+
+ status = "UNKNOWN"
+
+
+ # Currently we only accept "clear" to be marked as online. Eventually we
+ # should also check against "test"
+ online_status = ["clear"]
+
+ offline_status = ["reset", "off"]
+
+ if any(online_status_element in sbd_status \
+ for online_status_element in online_status):
+ status = "on"
+
+ if any(offline_status_element in sbd_status \
+ for offline_status_element in offline_status):
+ status = "off"
+
+ return status
+
+def get_node_list(conn, options):
+ """Returns a list of hostnames, registerd on the sbd device.
+
+ Key arguments:
+ conn -- connection options
+ options -- options
+
+ Return Value:
+ nodelist -- dictionary wich contains all node names and there status
+ """
+
+ del conn
+
+ nodelist = {}
+
+ cmd = generate_sbd_command(options, "list")
+
+ (return_code, out, err) = run_commands(options, cmd)
+
+ for line in out.split("\n"):
+ if len(line) == 0:
+ continue
+
+ # if we read "unreadable" something went wrong
+ if "NOT dumped" in line:
+ return nodelist
+
+ words = line.split()
+ port = words[1]
+ sbd_status = words[2]
+ nodelist[port] = (port, translate_status(sbd_status))
+
+ return nodelist
+
+def parse_sbd_devices(options):
+ """Returns an array of all sbd devices.
+
+ Key arguments:
+ options -- options dictionary
+
+ Return Value:
+ devices -- array of device paths
+ """
+
+ devices = [str.strip(dev) \
+ for dev in str.split(options["--devices"], ",")]
+
+ return devices
+
+def define_new_opts():
+ """Defines the all opt list
+ """
+ all_opt["devices"] = {
+ "getopt" : ":",
+ "longopt" : "devices",
+ "help":"--devices=[device_a,device_b] \
+Comma separated list of sbd devices",
+ "required" : "1",
+ "shortdesc" : "SBD Device",
+ "order": 1
+ }
+
+ all_opt["sbd_path"] = {
+ "getopt" : ":",
+ "longopt" : "sbd-path",
+ "help" : "--sbd-path=[path] Path to SBD binary",
+ "required" : "0",
+ "default" : "@SBD_PATH@",
+ "order": 200
+ }
+
+def main():
+ """Main function
+ """
+ # We need to define "no_password" otherwise we will be ask about it if
+ # we don't provide any password.
+ device_opt = ["no_password", "devices", "port", "method", "sbd_path"]
+
+ # close stdout if we get interrupted
+ atexit.register(atexit_handler)
+
+ define_new_opts()
+
+ all_opt["method"]["default"] = "cycle"
+ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: cycle)"
+ all_opt["power_timeout"]["default"] = "30"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ # fill the needed variables to generate metadata and help text output
+ docs = {}
+ docs["shortdesc"] = "Fence agent for sbd"
+ docs["longdesc"] = "fence_sbd is I/O Fencing agent \
+which can be used in environments where sbd can be used (shared storage)."
+ docs["vendorurl"] = ""
+ show_docs(options, docs)
+
+ # We need to check if --devices is given and not empty.
+ if "--devices" not in options:
+ fail_usage("No SBD devices specified. \
+ At least one SBD device is required.")
+
+ run_delay(options)
+
+ # We need to check if the provided sbd_devices exists. We need to do
+ # that for every given device.
+ # Just for the case we are really rebooting / powering off a device
+ # (pacemaker as well uses the list command to generate a dynamic list)
+ # we leave it to sbd to try and decide if it was successful
+ if not options["--action"] in ["reboot", "off", "list"]:
+ for device_path in parse_sbd_devices(options):
+ logging.debug("check device \"%s\"", device_path)
+
+ return_code = check_sbd_device(options, device_path)
+ if PATH_NOT_EXISTS == return_code:
+ logging.error("\"%s\" does not exist", device_path)
+ elif PATH_NOT_BLOCK == return_code:
+ logging.error("\"%s\" is not a valid block device", device_path)
+ elif DEVICE_NOT_INIT == return_code:
+ logging.error("\"%s\" is not initialized", device_path)
+ elif DEVICE_INIT != return_code:
+ logging.error("UNKNOWN error while checking \"%s\"", device_path)
+
+ # If we get any error while checking the device we need to exit at this
+ # point.
+ if DEVICE_INIT != return_code:
+ exit(return_code)
+
+ # we check against the defined timeouts. If the pacemaker timeout is smaller
+ # then that defined within sbd we should report this.
+ power_timeout = int(options["--power-timeout"])
+ sbd_msg_timeout = get_msg_timeout(options)
+ if 0 < power_timeout <= sbd_msg_timeout:
+ logging.warn("power timeout needs to be \
+ greater then sbd message timeout")
+
+ result = fence_action(\
+ None, \
+ options, \
+ set_power_status, \
+ get_power_status, \
+ get_node_list, \
+ reboot_cycle)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/scsi/fence_scsi.py b/agents/scsi/fence_scsi.py
new file mode 100644
index 0000000..f9e6823
--- /dev/null
+++ b/agents/scsi/fence_scsi.py
@@ -0,0 +1,598 @@
+#!@PYTHON@ -tt
+
+import sys
+import stat
+import re
+import os
+import time
+import logging
+import atexit
+import hashlib
+import ctypes
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import fail_usage, run_command, atexit_handler, check_input, process_input, show_docs, fence_action, all_opt
+from fencing import run_delay
+
+STORE_PATH = "@STORE_PATH@"
+
+
+def get_status(conn, options):
+ del conn
+ status = "off"
+ for dev in options["devices"]:
+ is_block_device(dev)
+ reset_dev(options, dev)
+ if options["--key"] in get_registration_keys(options, dev):
+ status = "on"
+ else:
+ logging.debug("No registration for key "\
+ + options["--key"] + " on device " + dev + "\n")
+ if options["--action"] == "on":
+ status = "off"
+ break
+ return status
+
+
+def set_status(conn, options):
+ del conn
+ count = 0
+ if options["--action"] == "on":
+ set_key(options)
+ for dev in options["devices"]:
+ is_block_device(dev)
+
+ register_dev(options, dev)
+ if options["--key"] not in get_registration_keys(options, dev):
+ count += 1
+ logging.debug("Failed to register key "\
+ + options["--key"] + "on device " + dev + "\n")
+ continue
+ dev_write(dev, options)
+
+ if get_reservation_key(options, dev) is None \
+ and not reserve_dev(options, dev) \
+ and get_reservation_key(options, dev) is None:
+ count += 1
+ logging.debug("Failed to create reservation (key="\
+ + options["--key"] + ", device=" + dev + ")\n")
+
+ else:
+ host_key = get_key()
+ if host_key == options["--key"].lower():
+ fail_usage("Failed: keys cannot be same. You can not fence yourself.")
+ for dev in options["devices"]:
+ is_block_device(dev)
+
+ if options["--key"] in get_registration_keys(options, dev):
+ preempt_abort(options, host_key, dev)
+
+ for dev in options["devices"]:
+ if options["--key"] in get_registration_keys(options, dev):
+ count += 1
+ logging.debug("Failed to remove key "\
+ + options["--key"] + " on device " + dev + "\n")
+ continue
+
+ if not get_reservation_key(options, dev):
+ count += 1
+ logging.debug("No reservation exists on device " + dev + "\n")
+ if count:
+ logging.error("Failed to verify " + str(count) + " device(s)")
+ sys.exit(1)
+
+
+# check if host is ready to execute actions
+def do_action_monitor(options):
+ # Check if required binaries are installed
+ if bool(run_cmd(options, options["--sg_persist-path"] + " -V")["rc"]):
+ logging.error("Unable to run " + options["--sg_persist-path"])
+ return 1
+ elif bool(run_cmd(options, options["--sg_turs-path"] + " -V")["rc"]):
+ logging.error("Unable to run " + options["--sg_turs-path"])
+ return 1
+ elif ("--devices" not in options and
+ bool(run_cmd(options, options["--vgs-path"] + " --version")["rc"])):
+ logging.error("Unable to run " + options["--vgs-path"])
+ return 1
+
+ # Keys have to be present in order to fence/unfence
+ get_key()
+ dev_read()
+
+ return 0
+
+
+# run command, returns dict, ret["rc"] = exit code; ret["out"] = output;
+# ret["err"] = error
+def run_cmd(options, cmd):
+ ret = {}
+ (ret["rc"], ret["out"], ret["err"]) = run_command(options, cmd)
+ ret["out"] = "".join([i for i in ret["out"] if i is not None])
+ ret["err"] = "".join([i for i in ret["err"] if i is not None])
+ return ret
+
+
+# check if device exist and is block device
+def is_block_device(dev):
+ if not os.path.exists(dev):
+ fail_usage("Failed: device \"" + dev + "\" does not exist")
+ if not stat.S_ISBLK(os.stat(dev).st_mode):
+ fail_usage("Failed: device \"" + dev + "\" is not a block device")
+
+
+# cancel registration
+def preempt_abort(options, host, dev):
+ reset_dev(options,dev)
+ cmd = options["--sg_persist-path"] + " -n -o -A -T 5 -K " + host + " -S " + options["--key"] + " -d " + dev
+ return not bool(run_cmd(options, cmd)["rc"])
+
+
+def reset_dev(options, dev):
+ return run_cmd(options, options["--sg_turs-path"] + " " + dev)["rc"]
+
+
+def register_dev(options, dev):
+ dev = os.path.realpath(dev)
+ if re.search(r"^dm", dev[5:]):
+ for slave in get_mpath_slaves(dev):
+ register_dev(options, slave)
+ return True
+ if get_reservation_key(options, dev, False) == options["--key"]:
+ return True
+ reset_dev(options, dev)
+ cmd = options["--sg_persist-path"] + " -n -o -I -S " + options["--key"] + " -d " + dev
+ cmd += " -Z" if "--aptpl" in options else ""
+ #cmd return code != 0 but registration can be successful
+ return not bool(run_cmd(options, cmd)["rc"])
+
+
+def reserve_dev(options, dev):
+ reset_dev(options,dev)
+ cmd = options["--sg_persist-path"] + " -n -o -R -T 5 -K " + options["--key"] + " -d " + dev
+ return not bool(run_cmd(options, cmd)["rc"])
+
+
+def get_reservation_key(options, dev, fail=True):
+ reset_dev(options,dev)
+ opts = ""
+ if "--readonly" in options:
+ opts = "-y "
+ cmd = options["--sg_persist-path"] + " -n -i " + opts + "-r -d " + dev
+ out = run_cmd(options, cmd)
+ if out["rc"] and fail:
+ fail_usage('Cannot get reservation key on device "' + dev
+ + '": ' + out["err"])
+ match = re.search(r"\s+key=0x(\S+)\s+", out["out"], re.IGNORECASE)
+ return match.group(1) if match else None
+
+
+def get_registration_keys(options, dev, fail=True):
+ reset_dev(options,dev)
+ keys = []
+ opts = ""
+ if "--readonly" in options:
+ opts = "-y "
+ cmd = options["--sg_persist-path"] + " -n -i " + opts + "-k -d " + dev
+ out = run_cmd(options, cmd)
+ if out["rc"]:
+ fail_usage('Cannot get registration keys on device "' + dev
+ + '": ' + out["err"], fail)
+ if not fail:
+ return []
+ for line in out["out"].split("\n"):
+ match = re.search(r"\s+0x(\S+)\s*", line)
+ if match:
+ keys.append(match.group(1))
+ return keys
+
+
+def get_cluster_id(options):
+ cmd = options["--corosync-cmap-path"] + " totem.cluster_name"
+
+ match = re.search(r"\(str\) = (\S+)\n", run_cmd(options, cmd)["out"])
+
+ if not match:
+ fail_usage("Failed: cannot get cluster name")
+
+ try:
+ return hashlib.md5(match.group(1).encode('ascii')).hexdigest()
+ except ValueError:
+ # FIPS requires usedforsecurity=False and might not be
+ # available on all distros: https://bugs.python.org/issue9216
+ return hashlib.md5(match.group(1).encode('ascii'), usedforsecurity=False).hexdigest()
+
+
+def get_node_id(options):
+ cmd = options["--corosync-cmap-path"] + " nodelist"
+ out = run_cmd(options, cmd)["out"]
+
+ match = re.search(r".(\d+).name \(str\) = " + options["--plug"] + "\n", out)
+
+ # try old format before failing
+ if not match:
+ match = re.search(r".(\d+).ring._addr \(str\) = " + options["--plug"] + "\n", out)
+
+ return match.group(1) if match else fail_usage("Failed: unable to parse output of corosync-cmapctl or node does not exist")
+
+def get_node_hash(options):
+ try:
+ return hashlib.md5(options["--plug"].encode('ascii')).hexdigest()
+ except ValueError:
+ # FIPS requires usedforsecurity=False and might not be
+ # available on all distros: https://bugs.python.org/issue9216
+ return hashlib.md5(options["--plug"].encode('ascii'), usedforsecurity=False).hexdigest()
+
+
+def generate_key(options):
+ if options["--key-value"] == "hash":
+ return "%.4s%.4s" % (get_cluster_id(options), get_node_hash(options))
+ else:
+ return "%.4s%.4d" % (get_cluster_id(options), int(get_node_id(options)))
+
+
+# save node key to file
+def set_key(options):
+ file_path = options["store_path"] + ".key"
+ if not os.path.isdir(os.path.dirname(options["store_path"])):
+ os.makedirs(os.path.dirname(options["store_path"]))
+ try:
+ f = open(file_path, "w")
+ except IOError:
+ fail_usage("Failed: Cannot open file \""+ file_path + "\"")
+ f.write(options["--key"].lower() + "\n")
+ f.close()
+
+
+# read node key from file
+def get_key(fail=True):
+ file_path = STORE_PATH + ".key"
+ try:
+ f = open(file_path, "r")
+ except IOError:
+ fail_usage("Failed: Cannot open file \""+ file_path + "\"", fail)
+ if not fail:
+ return None
+ return f.readline().strip().lower()
+
+
+def dev_write(dev, options):
+ file_path = options["store_path"] + ".dev"
+ if not os.path.isdir(os.path.dirname(options["store_path"])):
+ os.makedirs(os.path.dirname(options["store_path"]))
+ try:
+ f = open(file_path, "a+")
+ except IOError:
+ fail_usage("Failed: Cannot open file \""+ file_path + "\"")
+ f.seek(0)
+ out = f.read()
+ if not re.search(r"^" + dev + "\s+", out, flags=re.MULTILINE):
+ f.write(dev + "\n")
+ f.close()
+
+
+def dev_read(fail=True, opt=None):
+ file_path = STORE_PATH + ".dev"
+ try:
+ f = open(file_path, "r")
+ except IOError:
+ if "--suppress-errors" not in opt:
+ fail_usage("Failed: Cannot open file \"" + file_path + "\"", fail)
+ if not fail:
+ return None
+ # get not empty lines from file
+ devs = [line.strip() for line in f if line.strip()]
+ f.close()
+ return devs
+
+
+def get_clvm_devices(options):
+ devs = []
+ cmd = options["--vgs-path"] + " " +\
+ "--noheadings " +\
+ "--separator : " +\
+ "--sort pv_uuid " +\
+ "--options vg_attr,pv_name "+\
+ "--config 'global { locking_type = 0 } devices { preferred_names = [ \"^/dev/dm\" ] }'"
+ out = run_cmd(options, cmd)
+ if out["rc"]:
+ fail_usage("Failed: Cannot get clvm devices")
+ for line in out["out"].split("\n"):
+ if 'c' in line.split(":")[0]:
+ devs.append(line.split(":")[1])
+ return devs
+
+
+def get_mpath_slaves(dev):
+ if dev[:5] == "/dev/":
+ dev = dev[5:]
+ slaves = [i for i in os.listdir("/sys/block/" + dev + "/slaves/") if i[:1] != "."]
+ if slaves[0][:2] == "dm":
+ slaves = get_mpath_slaves(slaves[0])
+ else:
+ slaves = ["/dev/" + x for x in slaves]
+ return slaves
+
+
+def define_new_opts():
+ all_opt["devices"] = {
+ "getopt" : "d:",
+ "longopt" : "devices",
+ "help" : "-d, --devices=[devices] List of devices to use for current operation",
+ "required" : "0",
+ "shortdesc" : "List of devices to use for current operation. Devices can \
+be comma-separated list of raw devices (eg. /dev/sdc). Each device must support SCSI-3 \
+persistent reservations.",
+ "order": 1
+ }
+ all_opt["nodename"] = {
+ "getopt" : ":",
+ "longopt" : "nodename",
+ "help" : "",
+ "required" : "0",
+ "shortdesc" : "",
+ "order": 1
+ }
+ all_opt["key"] = {
+ "getopt" : "k:",
+ "longopt" : "key",
+ "help" : "-k, --key=[key] Key to use for the current operation",
+ "required" : "0",
+ "shortdesc" : "Key to use for the current operation. This key should be \
+unique to a node. For the \"on\" action, the key specifies the key use to \
+register the local node. For the \"off\" action, this key specifies the key to \
+be removed from the device(s).",
+ "order": 1
+ }
+ all_opt["aptpl"] = {
+ "getopt" : "a",
+ "longopt" : "aptpl",
+ "help" : "-a, --aptpl Use the APTPL flag for registrations",
+ "required" : "0",
+ "shortdesc" : "Use the APTPL flag for registrations. This option is only used for the 'on' action.",
+ "order": 1
+ }
+ all_opt["readonly"] = {
+ "getopt" : "",
+ "longopt" : "readonly",
+ "help" : "--readonly Open DEVICE read-only. May be useful with PRIN commands if there are unwanted side effects with the default read-write open.",
+ "required" : "0",
+ "shortdesc" : "Open DEVICE read-only.",
+ "order": 4
+ }
+ all_opt["suppress-errors"] = {
+ "getopt" : "",
+ "longopt" : "suppress-errors",
+ "help" : "--suppress-errors Suppress error log. Suppresses error logging when run from the watchdog service before pacemaker starts.",
+ "required" : "0",
+ "shortdesc" : "Error log suppression.",
+ "order": 5
+ }
+ all_opt["logfile"] = {
+ "getopt" : ":",
+ "longopt" : "logfile",
+ "help" : "-f, --logfile Log output (stdout and stderr) to file",
+ "required" : "0",
+ "shortdesc" : "Log output (stdout and stderr) to file",
+ "order": 6
+ }
+ all_opt["corosync_cmap_path"] = {
+ "getopt" : ":",
+ "longopt" : "corosync-cmap-path",
+ "help" : "--corosync-cmap-path=[path] Path to corosync-cmapctl binary",
+ "required" : "0",
+ "shortdesc" : "Path to corosync-cmapctl binary",
+ "default" : "@COROSYNC_CMAPCTL_PATH@",
+ "order": 300
+ }
+ all_opt["sg_persist_path"] = {
+ "getopt" : ":",
+ "longopt" : "sg_persist-path",
+ "help" : "--sg_persist-path=[path] Path to sg_persist binary",
+ "required" : "0",
+ "shortdesc" : "Path to sg_persist binary",
+ "default" : "@SG_PERSIST_PATH@",
+ "order": 300
+ }
+ all_opt["sg_turs_path"] = {
+ "getopt" : ":",
+ "longopt" : "sg_turs-path",
+ "help" : "--sg_turs-path=[path] Path to sg_turs binary",
+ "required" : "0",
+ "shortdesc" : "Path to sg_turs binary",
+ "default" : "@SG_TURS_PATH@",
+ "order": 300
+ }
+ all_opt["vgs_path"] = {
+ "getopt" : ":",
+ "longopt" : "vgs-path",
+ "help" : "--vgs-path=[path] Path to vgs binary",
+ "required" : "0",
+ "shortdesc" : "Path to vgs binary",
+ "default" : "@VGS_PATH@",
+ "order": 300
+ }
+ all_opt["key_value"] = {
+ "getopt" : ":",
+ "longopt" : "key-value",
+ "help" : "--key-value=<id|hash> SCSI key node generation method",
+ "required" : "0",
+ "shortdesc" : "Method used to generate the SCSI key. \"id\" (default) \
+uses the positional ID from \"corosync-cmactl nodelist\" output which can get inconsistent \
+when nodes are removed from cluster without full cluster restart. \"hash\" uses part of hash \
+made out of node names which is not affected over time but there is theoretical chance that \
+hashes can collide as size of SCSI key is quite limited.",
+ "default" : "id",
+ "order": 300
+ }
+
+
+def scsi_check_get_options(options):
+ try:
+ f = open("/etc/sysconfig/stonith", "r")
+ except IOError:
+ return options
+
+ match = re.findall(r"^\s*(\S*)\s*=\s*(\S*)\s*", "".join(f.readlines()), re.MULTILINE)
+
+ for m in match:
+ options[m[0].lower()] = m[1].lower()
+
+ f.close()
+
+ return options
+
+
+def scsi_check(hardreboot=False):
+ if len(sys.argv) >= 3 and sys.argv[1] == "repair":
+ return int(sys.argv[2])
+ options = {}
+ options["--sg_turs-path"] = "@SG_TURS_PATH@"
+ options["--sg_persist-path"] = "@SG_PERSIST_PATH@"
+ options["--power-timeout"] = "5"
+ options["retry"] = "0"
+ options["retry-sleep"] = "1"
+ options = scsi_check_get_options(options)
+ if "verbose" in options and options["verbose"] == "yes":
+ logging.getLogger().setLevel(logging.DEBUG)
+ devs = dev_read(fail=False,opt=options)
+ if not devs:
+ if "--suppress-errors" not in options:
+ logging.error("No devices found")
+ return 0
+ key = get_key(fail=False)
+ if not key:
+ logging.error("Key not found")
+ return 0
+ for dev in devs:
+ for n in range(int(options["retry"]) + 1):
+ if n > 0:
+ logging.debug("retry: " + str(n) + " of " + options["retry"])
+ if key in get_registration_keys(options, dev, fail=False):
+ logging.debug("key " + key + " registered with device " + dev)
+ return 0
+ else:
+ logging.debug("key " + key + " not registered with device " + dev)
+
+ if n < int(options["retry"]):
+ time.sleep(float(options["retry-sleep"]))
+
+ logging.debug("key " + key + " registered with any devices")
+
+ if hardreboot == True:
+ libc = ctypes.cdll['libc.so.6']
+ libc.reboot(0x1234567)
+ return 2
+
+
+def main():
+
+ atexit.register(atexit_handler)
+
+ device_opt = ["no_login", "no_password", "devices", "nodename", "port",\
+ "no_port", "key", "aptpl", "fabric_fencing", "on_target", "corosync_cmap_path",\
+ "sg_persist_path", "sg_turs_path", "readonly", "suppress-errors", "logfile", "vgs_path",\
+ "force_on", "key_value"]
+
+ define_new_opts()
+
+ all_opt["delay"]["getopt"] = "H:"
+
+ all_opt["port"]["help"] = "-n, --plug=[nodename] Name of the node to be fenced"
+ all_opt["port"]["shortdesc"] = "Name of the node to be fenced. The node name is used to \
+generate the key value used for the current operation. This option will be \
+ignored when used with the -k option."
+
+ #fence_scsi_check
+ if os.path.basename(sys.argv[0]) == "fence_scsi_check":
+ sys.exit(scsi_check())
+ elif os.path.basename(sys.argv[0]) == "fence_scsi_check_hardreboot":
+ sys.exit(scsi_check(True))
+
+ options = check_input(device_opt, process_input(device_opt), other_conditions=True)
+
+ # hack to remove list/list-status actions which are not supported
+ options["device_opt"] = [ o for o in options["device_opt"] if o != "separator" ]
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for SCSI persistent reservation"
+ docs["longdesc"] = "fence_scsi is an I/O fencing agent that uses SCSI-3 \
+persistent reservations to control access to shared storage devices. These \
+devices must support SCSI-3 persistent reservations (SPC-3 or greater) as \
+well as the \"preempt-and-abort\" subcommand.\nThe fence_scsi agent works by \
+having each node in the cluster register a unique key with the SCSI \
+device(s). Reservation key is generated from \"node id\" (default) or from \
+\"node name hash\" (RECOMMENDED) by adjusting \"key_value\" option. \
+Using hash is recommended to prevent issues when removing nodes \
+from cluster without full cluster restart. \
+Once registered, a single node will become the reservation holder \
+by creating a \"write exclusive, registrants only\" reservation on the \
+device(s). The result is that only registered nodes may write to the \
+device(s). When a node failure occurs, the fence_scsi agent will remove the \
+key belonging to the failed node from the device(s). The failed node will no \
+longer be able to write to the device(s). A manual reboot is required.\
+\n.P\n\
+When used as a watchdog device you can define e.g. retry=1, retry-sleep=2 and \
+verbose=yes parameters in /etc/sysconfig/stonith if you have issues with it \
+failing."
+ docs["vendorurl"] = ""
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # backward compatibility layer BEGIN
+ if "--logfile" in options:
+ try:
+ logfile = open(options["--logfile"], 'w')
+ sys.stderr = logfile
+ sys.stdout = logfile
+ except IOError:
+ fail_usage("Failed: Unable to create file " + options["--logfile"])
+ # backward compatibility layer END
+
+ options["store_path"] = STORE_PATH
+
+ # Input control BEGIN
+ stop_after_error = False if options["--action"] == "validate-all" else True
+
+ if options["--action"] == "monitor":
+ sys.exit(do_action_monitor(options))
+
+ # workaround to avoid regressions
+ if "--nodename" in options and options["--nodename"]:
+ options["--plug"] = options["--nodename"]
+ del options["--nodename"]
+
+ if not (("--plug" in options and options["--plug"])\
+ or ("--key" in options and options["--key"])):
+ fail_usage("Failed: nodename or key is required", stop_after_error)
+
+ if options["--action"] != "validate-all":
+ if not ("--key" in options and options["--key"]):
+ options["--key"] = generate_key(options)
+
+ if options["--key"] == "0" or not options["--key"]:
+ fail_usage("Failed: key cannot be 0", stop_after_error)
+
+ if "--key-value" in options\
+ and (options["--key-value"] != "id" and options["--key-value"] != "hash"):
+ fail_usage("Failed: key-value has to be 'id' or 'hash'", stop_after_error)
+
+ if options["--action"] == "validate-all":
+ sys.exit(0)
+
+ options["--key"] = options["--key"].lstrip('0')
+
+ if not ("--devices" in options and options["--devices"].split(",")):
+ options["devices"] = get_clvm_devices(options)
+ else:
+ options["devices"] = options["--devices"].split(",")
+
+ if not options["devices"]:
+ fail_usage("Failed: No devices found")
+ # Input control END
+
+ result = fence_action(None, options, set_status, get_status)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/skalar/fence_skalar.py b/agents/skalar/fence_skalar.py
new file mode 100644
index 0000000..0e11d83
--- /dev/null
+++ b/agents/skalar/fence_skalar.py
@@ -0,0 +1,226 @@
+#!@PYTHON@ -tt
+# -*- coding: utf-8 -*-
+
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS, EC_LOGIN_DENIED, EC_INVALID_PRIVILEGES, run_delay
+import requests
+import ast
+import urllib3
+import json
+import logging
+
+from requests.exceptions import ConnectionError
+
+
+###################################################################################
+# Inner functions
+
+
+def authorize_and_get_cookie(skala_ip, login, password, options):
+ URL0 = proto + str(skala_ip) + '/api/0/auth'
+ cred = {
+ "login" : str(login),
+ "password" : str(password)
+ }
+
+ try:
+ with requests.Session() as session:
+ session.post(url=URL0, data=cred, verify=ssl_verify)
+ cookie = session.cookies.get_dict()
+ except:
+ logging.exception('Exception occured.')
+ fail(EC_LOGIN_DENIED)
+ if 'api_token' in cookie:
+ return cookie
+ else:
+ fail(EC_LOGIN_DENIED)
+
+
+def logout(skala_ip):
+ URL1 = proto + str(skala_ip) + '/api/0/logout'
+
+ try:
+ with requests.Session() as session:
+ session.post(url=URL1, verify=ssl_verify, cookies=cookie)
+ except:
+ ## Logout; we do not care about result as we will end in any case
+ pass
+
+
+def get_vm_id(skala_ip, uuid, options, cookie):
+ URL2 = proto + str(skala_ip) + '/api/0/vm'
+ parameters = {
+ "uuid": str(uuid)
+ }
+
+ vm_info = requests.get(url=URL2, verify=ssl_verify, params=parameters, cookies=cookie)
+ jvm_info = vm_info.json()
+ if jvm_info["vm_list"]["items"] == []:
+ raise NameError('Can not find VM by uuid.')
+ logging.debug("VM_INFO:\n{}".format(json.dumps(vm_info.json(), indent=4, sort_keys=True)))
+ return jvm_info["vm_list"]["items"][0]["vm_id"]
+
+
+def vm_task(skala_ip, vm_id, command, options, cookie):
+
+ # command(str) – Command for vm: ‘vm_start’, ‘vm_stop’, ‘vm_restart’,
+ # ‘vm_suspend’, ‘vm_resume’, ‘vm_pause’, ‘vm_reset’
+ # main_request_id(TaskId) – Parent task id
+ # graceful(bool) – vm_stop command parameter, graceful or not, default
+ # false - *args[0]
+ # force(bool) – vm_stop command parameter, force stop or not, default
+ # false - *args[1]
+
+ if "--graceful" in options:
+ graceful = True
+ else:
+ graceful = False
+ if "--force" in options:
+ force = True
+ else:
+ force = False
+
+ URL3 = proto + str(skala_ip) + '/api/0/vm/' + str(vm_id) + '/task'
+
+ logging.debug("vm_task skala_ip: " + str(skala_ip))
+ logging.debug("vm_task vm_id: " + str(vm_id))
+ logging.debug("vm_task command: " + str(command))
+ logging.debug("vm_task cookie: " + str(cookie))
+
+
+ def checking(vm_id, command, graceful, force):
+ firstcondition = type(vm_id) is int
+ secondcondition = command in ['vm_start', 'vm_stop', 'vm_restart', 'vm_suspend', 'vm_resume', 'vm_pause', 'vm_reset']
+ thirdcondition = type(graceful) is bool
+ fourthcondition = type(force) is bool
+ return firstcondition * secondcondition * thirdcondition * fourthcondition
+
+ if not checking(vm_id, command, graceful, force):
+ print('Wrong parameters! \n'
+ 'command(str) – Command for vm: ‘vm_start’, ‘vm_stop’, \n'
+ '‘vm_restart’,‘vm_suspend’, ‘vm_resume’, ‘vm_pause’, ‘vm_reset’ \n'
+ 'graceful(bool) – vm_stop command parameter, graceful or not, default false \n'
+ 'force(bool) – vm_stop command parameter, force stop or not, default false \n'
+ )
+ else:
+ parameters = {
+ "command": command,
+ "graceful": graceful,
+ "force": force
+ }
+
+ with requests.Session() as session:
+ response = session.post(url=URL3, params=parameters, verify=ssl_verify, cookies=cookie)
+ if response.status_code != 200:
+ raise Exception('Invalid response code from server: {}.'.format(response.status_code))
+ return
+
+######################################################################################
+
+def get_power_status(conn, options):
+ state = {"RUNNING": "on", "PAUSED": "on", "STOPPED": "off", "SUSPENDED": "off", "ERROR": "off", "DELETED": "off",
+ "CREATING": "off", "FAILED_TO_CREATE": "off", "NODE_OFFLINE": "off", "STARTING": "off", "STOPPING": "on"}
+
+ URL4 = proto + options["--ip"] + '/api/0/vm/'
+ parameters = {
+ "uuid": str(options["--plug"])
+ }
+
+ vm_info = requests.get(url=URL4, params=parameters, verify=ssl_verify, cookies=cookie)
+ jvm_info = vm_info.json()
+ if jvm_info["vm_list"]["items"] == []:
+ raise NameError('Can not find VM by uuid.')
+ logging.debug("VM_INFO:\n{}".format(json.dumps(vm_info.json(), indent=4, sort_keys=True)))
+ status_v = jvm_info["vm_list"]["items"][0]["status"]
+ if status_v not in state:
+ raise Exception('Unknown VM state: {}.'.format(status_v))
+ return state[status_v]
+
+
+def set_power_status(conn, options):
+ action = {
+ "on" : "vm_start",
+ "reboot": "vm_restart",
+ "off" : "vm_stop"
+ }
+
+ vm_id_v = get_vm_id(options["--ip"], options["--plug"], options, cookie)
+ vm_task(options["--ip"], vm_id_v, action[options["--action"]], options, cookie)
+ return
+
+
+def get_list(conn, options):
+ outlets = {}
+ URL5 = proto + options["--ip"] + '/api/0/vm'
+
+ vm_info = requests.get(url=URL5, verify=ssl_verify, cookies=cookie)
+ jvm_info = vm_info.json()
+ list_jvm = jvm_info["vm_list"]["items"]
+ for elem in list_jvm:
+ outlets[elem["name"]] = (elem["uuid"], None)
+ return outlets
+
+
+def define_new_opts():
+ all_opt["graceful"] = {
+ "getopt" : "",
+ "longopt" : "graceful",
+ "help" : "--graceful vm_stop command parameter, graceful stop or not, default false",
+ "required" : "0",
+ "shortdesc" : "vm_stop command parameter, graceful stop or not, default false",
+ "order" : 1}
+
+ all_opt["force"] = {
+ "getopt" : "",
+ "longopt" : "force",
+ "help" : "--force vm_stop command parameter, force stop or not, default false",
+ "required" : "0",
+ "shortdesc" : "vm_stop command parameter, force stop or not, default false",
+ "order" : 1}
+
+
+def main():
+ global cookie, proto, ssl_verify
+ define_new_opts()
+ device_opt = ["ipaddr", "login", "passwd", "port", "web", "ssl", "verbose", "graceful", "force"]
+
+ atexit.register(atexit_handler)
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Skala-R Fence agent"
+ docs["longdesc"] = "A fence agent for Skala-R."
+ docs["vendorurl"] = "https://www.skala-r.ru/"
+ show_docs(options, docs)
+ options["eol"] = "\r"
+
+ run_delay(options)
+
+ proto = "https://"
+ if "--ssl-secure" in options:
+ ssl_verify = True
+ elif "--ssl-insecure" in options:
+ ssl_verify = False
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+ else:
+ proto = "http://"
+ ssl_verify = False
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+ cookie = authorize_and_get_cookie(options["--ip"], options["--username"], options["--password"], options)
+ atexit.register(logout, options["--ip"])
+
+ logging.debug("OPTIONS: " + str(options) + "\n")
+
+ try:
+ result = fence_action(None, options, set_power_status, get_power_status, get_list)
+ sys.exit(result)
+ except Exception:
+ logging.exception('Exception occured.')
+ fail(EC_STATUS)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/vbox/fence_vbox.py b/agents/vbox/fence_vbox.py
new file mode 100644
index 0000000..c2df288
--- /dev/null
+++ b/agents/vbox/fence_vbox.py
@@ -0,0 +1,135 @@
+#!@PYTHON@ -tt
+
+# The Following Agent Has Been Tested On:
+#
+# VirtualBox 5.0.4 x64 on openSUSE 13.2
+#
+
+import sys
+import re
+import time
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+
+from fencing import *
+from fencing import fail_usage
+
+def _invoke(conn, options, *cmd):
+ prefix = options["--sudo-path"] + " " if "--use-sudo" in options else ""
+ conn.send_eol(prefix + options["--vboxmanage-path"] + " " + " ".join(cmd))
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+def get_outlets_status(conn, options):
+ _domain_re = re.compile(r'^\"(.*)\" \{(.*)\}$')
+ result = {}
+
+ _invoke(conn, options, "list", "vms")
+ for line in conn.before.splitlines():
+ # format: "<domain>" {<uuid>}
+ domain = _domain_re.search(line.strip())
+ if domain is not None:
+ result[domain.group(1)] = (domain.group(2), "off")
+
+ _invoke(conn, options, "list", "runningvms")
+ for line in conn.before.splitlines():
+ # format: "<domain>" {<uuid>}
+ domain = _domain_re.search(line.strip())
+ if domain is not None:
+ result[domain.group(1)] = (domain.group(2), "on")
+
+ return result
+
+
+def get_power_status(conn, options):
+ outlets = get_outlets_status(conn, options)
+
+ if options["--plug"] in outlets:
+ return outlets[options["--plug"]][1]
+
+ right_uuid_line = [outlets[o] for o in outlets.keys() if outlets[o][0] == options["--plug"]]
+
+ if len(right_uuid_line):
+ return right_uuid_line[0][1]
+
+ if "--missing-as-off" in options:
+ return "off"
+
+ fail_usage("Failed: You have to enter existing name/UUID of virtual machine!")
+
+
+def set_power_status(conn, options):
+ if options["--action"] == "on":
+ _invoke(conn, options, "startvm", '"%s"' % options["--plug"], "--type", "headless")
+ else:
+ _invoke(conn, options, "controlvm", '"%s"' % options["--plug"], "poweroff")
+
+def define_new_opts():
+ all_opt["vboxmanage_path"] = {
+ "getopt" : ":",
+ "longopt" : "vboxmanage-path",
+ "help" : "--vboxmanage-path=[path] Path to VBoxManage on the host",
+ "required" : "0",
+ "shortdesc" : "Path to VBoxManage on the host",
+ "default" : "VBoxManage",
+ "order" : 200
+ }
+ all_opt["host_os"] = {
+ "getopt" : ":",
+ "longopt" : "host-os",
+ "help" : "--host-os=[os] Operating system of the host",
+ "required" : "0",
+ "shortdesc" : "Operating system of the host",
+ "choices" : ["linux", "macos", "windows"],
+ "default" : "linux",
+ "order" : 200
+ }
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", "port", "sudo",
+ "missing_as_off", "vboxmanage_path", "host_os"]
+ define_new_opts()
+
+ atexit.register(atexit_handler)
+
+ all_opt["secure"]["default"] = "1"
+
+ all_opt["cmd_prompt"]["default"] = [r"\[EXPECT\]#"]
+ all_opt["ssh_options"]["default"] = "-t '/bin/bash -c \"" + r"PS1=\\[EXPECT\\]# HISTFILE=/dev/null " + "/bin/bash --noprofile --norc\"'"
+
+ opt = process_input(device_opt)
+
+ opt["logout_string"] = "quit"
+ if "--host-os" in opt and "--vboxmanage-path" not in opt:
+ if opt["--host-os"] == "linux":
+ opt["--vboxmanage-path"] = "VBoxManage"
+ elif opt["--host-os"] == "macos":
+ opt["--vboxmanage-path"] = "/Applications/VirtualBox.app/Contents/MacOS/VBoxManage"
+ opt["logout_string"] = "exit"
+ elif opt["--host-os"] == "windows":
+ opt["--vboxmanage-path"] = "\"/Program Files/Oracle/VirtualBox/VBoxManage.exe"
+ opt["--command-prompt"] = ""
+ opt["--ssh-options"] = ""
+
+ options = check_input(device_opt, opt)
+ options["eol"] = "\n"
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for VirtualBox"
+ docs["longdesc"] = "fence_vbox is an I/O Fencing agent \
+which can be used with the virtual machines managed by VirtualBox. \
+It logs via ssh to a dom0 where it runs VBoxManage to do all of \
+the work. \
+\n.P\n\
+By default, vbox needs to log in as a user that is a member of the \
+vboxusers group. Also, you must allow ssh login in your sshd_config."
+ docs["vendorurl"] = "https://www.virtualbox.org/"
+ show_docs(options, docs)
+
+ # Operate the fencing device
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_outlets_status)
+ fence_logout(conn, opt["logout_string"])
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/virsh/fence_virsh.py b/agents/virsh/fence_virsh.py
new file mode 100644
index 0000000..88cee48
--- /dev/null
+++ b/agents/virsh/fence_virsh.py
@@ -0,0 +1,96 @@
+#!@PYTHON@ -tt
+
+# The Following Agent Has Been Tested On:
+#
+# Virsh 0.3.3 on RHEL 5.2 with xen-3.0.3-51
+#
+
+import sys, re
+import time
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage
+
+def get_name_or_uuid(options):
+ return options["--uuid"] if "--uuid" in options else options["--plug"]
+
+def get_outlets_status(conn, options):
+ if "--use-sudo" in options:
+ prefix = options["--sudo-path"] + " "
+ else:
+ prefix = ""
+
+ conn.sendline(prefix + "virsh list --all")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ result = {}
+
+ #This is status of mini finite automata. 0 = we didn't found Id and Name, 1 = we did
+ fa_status = 0
+
+ for line in conn.before.splitlines():
+ domain = re.search(r"^\s*(\S+)\s+(\S+)\s+(\S+).*$", line)
+
+ if domain != None:
+ if fa_status == 0 and domain.group(1).lower() == "id" and domain.group(2).lower() == "name":
+ fa_status = 1
+ elif fa_status == 1:
+ result[domain.group(2)] = ("",
+ (domain.group(3).lower() in ["running", "blocked", "idle", "no state", "paused"] and "on" or "off"))
+ return result
+
+def get_power_status(conn, options):
+ prefix = options["--sudo-path"] + " " if "--use-sudo" in options else ""
+ conn.sendline(prefix + "virsh domstate %s" % (get_name_or_uuid(options)))
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+
+ for line in conn.before.splitlines():
+ if line.strip() in ["running", "blocked", "idle", "no state", "paused"]:
+ return "on"
+ if "error: failed to get domain" in line.strip() and "--missing-as-off" in options:
+ return "off"
+ if "error:" in line.strip():
+ fail_usage("Failed: You have to enter existing name/UUID of virtual machine!")
+
+ return "off"
+
+def set_power_status(conn, options):
+ prefix = options["--sudo-path"] + " " if "--use-sudo" in options else ""
+ conn.sendline(prefix + "virsh %s " %
+ (options["--action"] == "on" and "start" or "destroy") + get_name_or_uuid(options))
+
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+ time.sleep(int(options["--power-wait"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "cmd_prompt", "secure", "port", "sudo", "missing_as_off"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["secure"]["default"] = "1"
+ all_opt["cmd_prompt"]["default"] = [r"\[EXPECT\]#"]
+ all_opt["ssh_options"]["default"] = "-t '/bin/bash -c \"" + r"PS1=\\[EXPECT\\]# " + "/bin/bash --noprofile --norc\"'"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for virsh"
+ docs["longdesc"] = "fence_virsh is an I/O Fencing agent \
+which can be used with the virtual machines managed by libvirt. \
+It logs via ssh to a dom0 and there run virsh command, which does \
+all work. \
+\n.P\n\
+By default, virsh needs root account to do properly work. So you \
+must allow ssh login in your sshd_config."
+ docs["vendorurl"] = "http://libvirt.org"
+ show_docs(options, docs)
+
+ ## Operate the fencing device
+ conn = fence_login(options)
+ result = fence_action(conn, options, set_power_status, get_power_status, get_outlets_status)
+ fence_logout(conn, "quit")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/virt/Makefile.am b/agents/virt/Makefile.am
new file mode 100644
index 0000000..4f50c60
--- /dev/null
+++ b/agents/virt/Makefile.am
@@ -0,0 +1,31 @@
+###############################################################################
+###############################################################################
+##
+## Copyright (C) 2009-2021 Red Hat, Inc.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2.
+##
+###############################################################################
+###############################################################################
+
+MAINTAINERCLEANFILES = Makefile.in
+
+EXTRA_DIST = docs/architecture.txt docs/fence_virt.txt \
+ docs/README docs/TODO include \
+ fence_virtd.service.in
+
+SUBDIRS = config common client server man
+
+all-local: fence_virtd.service
+
+clean-local:
+ rm -f $(SPEC) fence_virtd.service
+
+fence_virtd.service: fence_virtd.service.in
+ SBINDIR="@sbindir@"; \
+ INITCONFDIR="@initconfdir@"; \
+ cat $^ > $@ ; \
+ echo "EnvironmentFile=-$$INITCONFDIR/fence_virtd" >> $@ ;\
+ echo "ExecStart=$$SBINDIR/fence_virtd \$$FENCE_VIRTD_ARGS" >> $@
diff --git a/agents/virt/client/Makefile.am b/agents/virt/client/Makefile.am
new file mode 100644
index 0000000..4a1997b
--- /dev/null
+++ b/agents/virt/client/Makefile.am
@@ -0,0 +1,40 @@
+###############################################################################
+###############################################################################
+##
+## Copyright (C) 2009-2019 Red Hat, Inc.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2
+##
+###############################################################################
+###############################################################################
+
+MAINTAINERCLEANFILES = Makefile.in
+
+sbin_PROGRAMS = fence_virt
+
+TARGET = $(sbin_PROGRAMS)
+
+fence_virt_SOURCES = mcast.c serial.c main.c options.c tcp.c vsock.c
+
+fence_virt_CFLAGS = $(VIRT_AM_CFLAGS) $(nss_CFLAGS) $(xml2_CFLAGS) $(PTHREAD_CFLAGS) $(AM_CFLAGS)
+
+fence_virt_LDFLAGS = $(VIRT_AM_LDFLAGS) $(COMMON_LDFLAGS)
+fence_virt_LDADD = $(VIRT_COMMON_LIBS) $(nss_LIBS) $(xml2_LIBS) $(PTHREAD_LIBS)
+
+if xvmcompat
+install-exec-hook: fence_virt
+ (cd $(DESTDIR)/${sbindir}; $(LN_S) -nf $^ fence_xvm)
+
+uninstall-hook:
+ (cd $(DESTDIR)/${sbindir}; rm -f fence_xvm)
+endif
+
+fence_virt.delay-check: fence_virt
+ $(eval INPUT=$(subst .delay-check,,$@))
+ test `/usr/bin/time -p ./$(INPUT) -w 10 -n test $(FENCE_TEST_ARGS) -- 2>&1 |\
+ awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}' | tail -n 1` -ge 1000 || \
+ /usr/bin/time -p ./$(INPUT) -w 0 -n test $(FENCE_TEST_ARGS) --
+
+include $(top_srcdir)/make/agentccheck.mk
diff --git a/agents/virt/client/main.c b/agents/virt/client/main.c
new file mode 100644
index 0000000..188c05d
--- /dev/null
+++ b/agents/virt/client/main.c
@@ -0,0 +1,198 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/*
+ * Author: Lon Hohberger <lhh at redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <pthread.h>
+#include <libgen.h>
+#include <syslog.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "options.h"
+#include "debug.h"
+#include "client.h"
+
+
+int
+main(int argc, char **argv)
+{
+ fence_virt_args_t args;
+ const char *my_options;
+ int ret = 0;
+
+ args_init(&args);
+ if (!strcmp(basename(argv[0]), "fence_xvm")) {
+ my_options = "di:a:p:r:C:c:k:M:n:H:uo:t:?hVw:";
+ args.mode = MODE_MULTICAST;
+ } else {
+ my_options = "dD:P:A:p:M:n:H:o:t:?hVT:S::C:c:k:w:";
+ args.mode = MODE_SERIAL;
+ }
+
+ if (argc == 1) {
+ args_get_stdin(my_options, &args);
+ } else {
+ args_get_getopt(argc, argv, my_options, &args);
+ }
+
+ if (args.flags & F_HELP) {
+ args_usage(argv[0], my_options, 0);
+
+ printf("With no command line argument, arguments are "
+ "read from standard input.\n");
+ printf("Arguments read from standard input take "
+ "the form of:\n\n");
+ printf(" arg1=value1\n");
+ printf(" arg2=value2\n\n");
+
+ args_usage(argv[0], my_options, 1);
+ exit(0);
+ }
+
+ if (args.flags & F_VERSION) {
+ printf("%s %s\n", basename(argv[0]), XVM_VERSION);
+#ifdef VERSION
+ printf("fence release %s\n", VERSION);
+#endif
+ exit(0);
+ }
+
+ openlog(basename(argv[0]), LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
+ args_finalize(&args);
+ dset(args.debug);
+
+ if (args.debug > 0)
+ args_print(&args);
+
+ /* Additional validation here */
+ if (!args.domain && (args.op != FENCE_DEVSTATUS &&
+ args.op != FENCE_HOSTLIST &&
+ args.op != FENCE_METADATA)) {
+ printf("No domain specified!\n");
+ syslog(LOG_NOTICE, "No domain specified");
+ args.flags |= F_ERR;
+ }
+
+ if (args.net.ipaddr)
+ args.mode = MODE_TCP;
+
+ if (args.net.cid >= 2)
+ args.mode = MODE_VSOCK;
+
+ if (args.flags & F_ERR) {
+ if (args.op != FENCE_VALIDATEALL)
+ args_usage(argv[0], my_options, (argc == 1));
+ exit(1);
+ }
+
+ if (args.op == FENCE_VALIDATEALL)
+ exit(0);
+
+ if (args.op == FENCE_METADATA) {
+ args_metadata(argv[0], my_options);
+ exit(0);
+ }
+
+ if (args.delay > 0 &&
+ args.op != FENCE_STATUS &&
+ args.op != FENCE_DEVSTATUS &&
+ args.op != FENCE_HOSTLIST)
+ sleep(args.delay);
+
+ switch(args.mode) {
+ case MODE_MULTICAST:
+ ret = mcast_fence_virt(&args);
+ break;
+ case MODE_SERIAL:
+ ret = serial_fence_virt(&args);
+ break;
+ case MODE_TCP:
+ ret = tcp_fence_virt(&args);
+ break;
+ case MODE_VSOCK:
+ ret = vsock_fence_virt(&args);
+ break;
+ default:
+ ret = 1;
+ goto out;
+ }
+
+ switch(ret) {
+ case RESP_OFF:
+ if (args.op == FENCE_STATUS)
+ printf("Status: OFF\n");
+ else if (args.domain)
+ syslog(LOG_NOTICE, "Domain \"%s\" is OFF", args.domain);
+ break;
+ case 0:
+ if (args.op == FENCE_STATUS)
+ printf("Status: ON\n");
+ else if (args.domain)
+ syslog(LOG_NOTICE, "Domain \"%s\" is ON", args.domain);
+ break;
+ case RESP_FAIL:
+ if (args.domain) {
+ syslog(LOG_NOTICE, "Fence operation failed for domain \"%s\"",
+ args.domain);
+ } else
+ syslog(LOG_NOTICE, "Fence operation failed");
+ printf("Operation failed\n");
+ break;
+ case RESP_PERM:
+ if (args.domain) {
+ syslog(LOG_NOTICE,
+ "Permission denied for Fence operation for domain \"%s\"",
+ args.domain);
+ } else
+ syslog(LOG_NOTICE, "Permission denied for fence operation");
+ printf("Permission denied\n");
+ break;
+ default:
+ if (args.domain) {
+ syslog(LOG_NOTICE, "Unknown response (%d) for domain \"%s\"",
+ ret, args.domain);
+ } else
+ syslog(LOG_NOTICE, "Unknown response (%d)", ret);
+ printf("Unknown response (%d)\n", ret);
+ break;
+ }
+
+out:
+ closelog();
+ exit(ret);
+}
diff --git a/agents/virt/client/mcast.c b/agents/virt/client/mcast.c
new file mode 100644
index 0000000..42f0a6b
--- /dev/null
+++ b/agents/virt/client/mcast.c
@@ -0,0 +1,393 @@
+/*
+ Copyright Red Hat, Inc. 2006-2017
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/*
+ * Author: Lon Hohberger <lhh at redhat.com>
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <libgen.h>
+#include <nss.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "ip_lookup.h"
+#include "simple_auth.h"
+#include "options.h"
+#include "tcp.h"
+#include "mcast.h"
+#include "debug.h"
+#include "fdops.h"
+#include "client.h"
+
+
+static int
+tcp_wait_connect(int lfd, int retry_tenths)
+{
+ int fd;
+ fd_set rfds;
+ int n;
+ struct timeval tv;
+
+ dbg_printf(3, "Waiting for connection from XVM host daemon.\n");
+ FD_ZERO(&rfds);
+ FD_SET(lfd, &rfds);
+ tv.tv_sec = retry_tenths / 10;
+ tv.tv_usec = (retry_tenths % 10) * 100000;
+
+ n = select(lfd + 1, &rfds, NULL, NULL, &tv);
+ if (n == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ } else if (n < 0) {
+ return -1;
+ }
+
+ fd = accept(lfd, NULL, 0);
+ if (fd < 0)
+ return -1;
+
+ return fd;
+}
+
+
+void
+do_read_hostlist(int fd, int timeout)
+{
+ host_state_t hinfo;
+ fd_set rfds;
+ struct timeval tv;
+ int ret;
+
+ do {
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ ret = _select_retry(fd+1, &rfds, NULL, NULL, &tv);
+ if (ret == 0) {
+ printf("Timed out!\n");
+ break;
+ }
+
+ ret = _read_retry(fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret < sizeof(hinfo)) {
+ printf("Bad read!\n");
+ break;
+ }
+
+ if (strlen((char *)hinfo.uuid) == 0 &&
+ strlen((char *)hinfo.domain) == 0)
+ break;
+
+ printf("%-32s %s %s\n", hinfo.domain, hinfo.uuid,
+ (hinfo.state == 1) ? "on" : "off");
+ } while (1);
+}
+
+
+static int
+tcp_exchange(int fd, fence_auth_type_t auth, void *key,
+ size_t key_len, int timeout)
+{
+ fd_set rfds;
+ struct timeval tv;
+ char ret = 1;
+
+ /* Ok, we're connected */
+ dbg_printf(3, "Issuing TCP challenge\n");
+ if (sock_challenge(fd, auth, key, key_len, timeout) <= 0) {
+ /* Challenge failed */
+ printf("Invalid response to challenge\n");
+ return 1;
+ }
+
+ /* Now they'll send us one, so we need to respond here */
+ dbg_printf(3, "Responding to TCP challenge\n");
+ if (sock_response(fd, auth, key, key_len, timeout) <= 0) {
+ printf("Invalid response to challenge\n");
+ return 1;
+ }
+
+ dbg_printf(2, "TCP Exchange + Authentication done... \n");
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ ret = 1;
+ dbg_printf(3, "Waiting for return value from XVM host\n");
+ if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0)
+ return -1;
+
+ /* Read return code */
+ if (_read_retry(fd, &ret, 1, &tv) < 0)
+ ret = 1;
+
+ if (ret == (char)RESP_HOSTLIST) /* hostlist */ {
+ do_read_hostlist(fd, timeout);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+
+static int
+send_multicast_packets(ip_list_t *ipl, fence_virt_args_t *args,
+ uint32_t seqno, void *key, size_t key_len)
+{
+ fence_req_t freq;
+ int mc_sock;
+ ip_addr_t *ipa;
+ struct sockaddr_in tgt4;
+ struct sockaddr_in6 tgt6;
+ struct sockaddr *tgt;
+ socklen_t tgt_len;
+
+ for (ipa = ipl->tqh_first; ipa; ipa = ipa->ipa_entries.tqe_next) {
+
+ if (ipa->ipa_family != args->net.family) {
+ dbg_printf(2, "Ignoring %s: wrong family\n", ipa->ipa_address);
+ continue;
+ }
+
+ if (args->net.family == PF_INET) {
+ mc_sock = ipv4_send_sk(ipa->ipa_address, args->net.addr,
+ args->net.port,
+ (struct sockaddr *)&tgt4,
+ sizeof(struct sockaddr_in));
+ tgt = (struct sockaddr *)&tgt4;
+ tgt_len = sizeof(tgt4);
+ } else if (args->net.family == PF_INET6) {
+ mc_sock = ipv6_send_sk(ipa->ipa_address, args->net.addr,
+ args->net.port,
+ (struct sockaddr *)&tgt6,
+ sizeof(struct sockaddr_in6));
+ tgt = (struct sockaddr *)&tgt6;
+ tgt_len = sizeof(tgt6);
+ } else {
+ dbg_printf(2, "Unsupported family %d\n", args->net.family);
+ return -1;
+ }
+
+ if (mc_sock < 0)
+ continue;
+
+ /* Build our packet */
+ memset(&freq, 0, sizeof(freq));
+ if (args->domain && strlen((char *)args->domain)) {
+ strncpy((char *)freq.domain, args->domain,
+ sizeof(freq.domain) - 1);
+ }
+ freq.request = args->op;
+ freq.hashtype = args->net.hash;
+ freq.seqno = seqno;
+
+ /* Store source address */
+ if (ipa->ipa_family == PF_INET) {
+ freq.addrlen = sizeof(struct in_addr);
+ /* XXX Swap order for in_addr ? XXX */
+ if (inet_pton(PF_INET, ipa->ipa_address, freq.address) != 1) {
+ dbg_printf(2, "Unable to convert address\n");
+ close(mc_sock);
+ return -1;
+ }
+ } else if (ipa->ipa_family == PF_INET6) {
+ freq.addrlen = sizeof(struct in6_addr);
+ if (inet_pton(PF_INET6, ipa->ipa_address, freq.address) != 1) {
+ dbg_printf(2, "Unable to convert address\n");
+ close(mc_sock);
+ return -1;
+ }
+ }
+
+ freq.flags = 0;
+ if (args->flags & F_USE_UUID)
+ freq.flags |= RF_UUID;
+ freq.family = ipa->ipa_family;
+ freq.port = args->net.port;
+
+ sign_request(&freq, key, key_len);
+
+ dbg_printf(3, "Sending to %s via %s\n", args->net.addr,
+ ipa->ipa_address);
+
+ if(sendto(mc_sock, &freq, sizeof(freq), 0,
+ (struct sockaddr *)tgt, tgt_len) < 0) {
+ dbg_printf(3, "Unable to send packet to %s via %s\n",
+ args->net.addr, ipa->ipa_address);
+ }
+
+ close(mc_sock);
+ }
+
+ return 0;
+}
+
+
+/* TODO: Clean this up!!! */
+int
+mcast_fence_virt(fence_virt_args_t *args)
+{
+ ip_list_t ipl;
+ char key[MAX_KEY_LEN];
+ struct timeval tv;
+ int lfd = -1, key_len = 0, fd, ret;
+ int attempts = 0;
+ uint32_t seqno;
+
+ /* Initialize NSS; required to do hashing, as silly as that
+ sounds... */
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ printf("Could not initialize NSS\n");
+ return 1;
+ }
+
+ if (args->net.auth != AUTH_NONE || args->net.hash != HASH_NONE) {
+ key_len = read_key_file(args->net.key_file, key, sizeof(key));
+ if (key_len < 0) {
+ printf("Could not read %s; trying without "
+ "authentication\n", args->net.key_file);
+ args->net.auth = AUTH_NONE;
+ args->net.hash = HASH_NONE;
+ key_len = 0;
+ }
+ }
+
+ /* Do the real work */
+ if (ip_build_list(&ipl) < 0) {
+ printf("Error building IP address list\n");
+ return 1;
+ }
+
+ attempts = args->timeout * 10 / args->retr_time;
+
+ listen_loop:
+ do {
+ switch (args->net.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ if (args->net.family == PF_INET) {
+ lfd = ipv4_listen(NULL, args->net.port, 10);
+ } else {
+ lfd = ipv6_listen(NULL, args->net.port, 10);
+ }
+ break;
+ /*case AUTH_X509:*/
+ /* XXX Setup SSL listener socket here */
+ default:
+ return 1;
+ }
+
+ if (lfd < 0) {
+ printf("Failed to listen: %s\n", strerror(errno));
+ usleep(args->retr_time * 100000);
+ if (--attempts > 0)
+ goto listen_loop;
+ }
+ } while (0);
+
+ if (lfd < 0)
+ return -1;
+
+ gettimeofday(&tv, NULL);
+ seqno = (uint32_t)tv.tv_usec;
+
+ do {
+ if (send_multicast_packets(&ipl, args, seqno,
+ key, key_len)) {
+ close(lfd);
+ return -1;
+ }
+
+ switch (args->net.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ fd = tcp_wait_connect(lfd, args->retr_time);
+ if (fd < 0 && (errno == ETIMEDOUT ||
+ errno == EINTR))
+ continue;
+ break;
+ /* case AUTH_X509:
+ ... = ssl_wait_connect... */
+ break;
+ default:
+ close(lfd);
+ return 1;
+ }
+
+ break;
+ } while (--attempts);
+
+ if (lfd >= 0)
+ close(lfd);
+
+ if (fd < 0) {
+ if (attempts <= 0) {
+ printf("Timed out waiting for response\n");
+ return 1;
+ }
+ printf("Operation failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ switch (args->net.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ ret = tcp_exchange(fd, args->net.auth, key, key_len,
+ args->timeout);
+ break;
+ /* case AUTH_X509:
+ return ssl_exchange(...); */
+ default:
+ ret = 1;
+ break;
+ }
+
+ close(fd);
+ return ret;
+}
diff --git a/agents/virt/client/options.c b/agents/virt/client/options.c
new file mode 100644
index 0000000..ddd6bc4
--- /dev/null
+++ b/agents/virt/client/options.c
@@ -0,0 +1,1000 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <libgen.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "simple_auth.h"
+#include "mcast.h"
+#include "tcp_listener.h"
+#include "options.h"
+
+#define SCHEMA_COMPAT '\xfe'
+
+
+/* Assignment functions */
+
+static inline void
+assign_debug(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value) {
+ /* GNU getopt sets optarg to NULL for options w/o a param
+ We rely on this here... */
+ args->debug++;
+ return;
+ }
+
+ args->debug = atoi(value);
+ if (args->debug < 0) {
+ args->debug = 1;
+ }
+}
+
+
+static inline void
+assign_family(fence_virt_args_t *args, struct arg_info *arg,
+ char *value)
+{
+ if (!value)
+ return;
+
+ if (!strcasecmp(value, "ipv4")) {
+ args->net.family = PF_INET;
+ } else if (!strcasecmp(value, "ipv6")) {
+ args->net.family = PF_INET6;
+ } else if (!strcasecmp(value, "auto")) {
+ args->net.family = 0;
+ } else {
+ printf("Unsupported family: '%s'\n", value);
+ args->flags |= F_ERR;
+ }
+}
+
+
+static inline void
+assign_address(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ if (args->net.addr)
+ free(args->net.addr);
+ args->net.addr = strdup(value);
+}
+
+static inline void
+assign_ip_address(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ if (args->net.ipaddr)
+ free(args->net.ipaddr);
+ args->net.ipaddr = strdup(value);
+}
+
+static inline void
+assign_channel_address(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ if (args->serial.address)
+ free(args->serial.address);
+ args->serial.address = strdup(value);
+}
+
+
+static inline void
+assign_port(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ char *p;
+ int ret;
+
+ if (!value)
+ return;
+
+ ret = strtol(value, &p, 0);
+ if (ret <= 0 || ret >= 65536 || *p != '\0') {
+ printf("Invalid port: '%s'\n", value);
+ args->flags |= F_ERR;
+ } else
+ args->net.port = ret;
+}
+
+static inline void
+assign_cid(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ char *p;
+ unsigned long ret;
+
+ if (!value) {
+ args->net.cid = 2;
+ return;
+ }
+
+ ret = strtoul(value, &p, 0);
+ if (!p || *p != '\0' || ret < 2 || ret >= 0xffffffff) {
+ printf("Invalid CID: '%s'\n", value);
+ args->flags |= F_ERR;
+ } else
+ args->net.cid = ret;
+}
+
+static inline void
+assign_interface(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ int ret;
+
+ if (!value)
+ return;
+
+ ret = if_nametoindex(value);
+ if (ret <= 0) {
+ printf("Invalid interface: %s: %s\n", value, strerror(errno));
+ args->net.ifindex = 0;
+ }
+
+ args->net.ifindex = ret;
+}
+
+
+static inline void
+assign_retrans(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ char *p;
+ int ret;
+
+ if (!value)
+ return;
+
+ ret = strtol(value, &p, 0);
+ if (ret <= 0 || *p != '\0') {
+ printf("Invalid retransmit time: '%s'\n", value);
+ args->flags |= F_ERR;
+ } else
+ args->retr_time = ret;
+}
+
+static inline void
+assign_hash(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ if (!strcasecmp(value, "none")) {
+ args->net.hash = HASH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->net.hash = HASH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->net.hash = HASH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->net.hash = HASH_SHA512;
+ } else {
+ printf("Unsupported hash: %s\n", value);
+ args->flags |= F_ERR;
+ }
+}
+
+
+static inline void
+assign_auth(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ if (!strcasecmp(value, "none")) {
+ args->net.auth = AUTH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->net.auth = AUTH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->net.auth = AUTH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->net.auth = AUTH_SHA512;
+ } else {
+ printf("Unsupported auth type: %s\n", value);
+ args->flags |= F_ERR;
+ }
+}
+
+static inline void
+assign_key(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ struct stat st;
+
+ if (!value)
+ return;
+
+ if (args->net.key_file)
+ free(args->net.key_file);
+ args->net.key_file = strdup(value);
+
+ if (stat(value, &st) == -1) {
+ printf("Invalid key file: '%s' (%s)\n", value,
+ strerror(errno));
+ args->flags |= F_ERR;
+ }
+}
+
+
+static inline void
+assign_op(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ if (!strcasecmp(value, "null")) {
+ args->op = FENCE_NULL;
+ } else if (!strcasecmp(value, "on")) {
+ args->op = FENCE_ON;
+ } else if (!strcasecmp(value, "off")) {
+ args->op = FENCE_OFF;
+ } else if (!strcasecmp(value, "reboot")) {
+ args->op = FENCE_REBOOT;
+ } else if (!strcasecmp(value, "status")) {
+ args->op = FENCE_STATUS;
+ } else if (!strcasecmp(value, "monitor")) {
+ args->op = FENCE_DEVSTATUS;
+ } else if (!strcasecmp(value, "list") || !strcasecmp(value, "list-status")) {
+ args->op = FENCE_HOSTLIST;
+ } else if (!strcasecmp(value, "metadata")) {
+ args->op = FENCE_METADATA;
+ } else if (!strcasecmp(value, "validate-all")) {
+ args->op = FENCE_VALIDATEALL;
+ } else {
+ printf("Unsupported operation: %s\n", value);
+ args->flags |= F_ERR;
+ }
+}
+
+
+static inline void
+assign_device(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ args->serial.device = strdup(value);
+}
+
+
+static inline void
+assign_params(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value)
+ return;
+
+ args->serial.speed = strdup(value);
+}
+
+
+static inline void
+assign_domain(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (args->domain) {
+ printf("Domain/UUID may not be specified more than once\n");
+ args->flags |= F_ERR;
+ return;
+ }
+
+ if (!value)
+ return;
+
+ args->domain = strdup(value);
+
+ if (strlen(value) <= 0) {
+ printf("Invalid domain name\n");
+ args->flags |= F_ERR;
+ }
+
+ if (strlen(value) >= MAX_DOMAINNAME_LENGTH) {
+ errno = ENAMETOOLONG;
+ printf("Invalid domain name: '%s' (%s)\n",
+ value, strerror(errno));
+ args->flags |= F_ERR;
+ }
+}
+
+
+static inline void
+assign_uuid_lookup(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ if (!value) {
+ /* GNU getopt sets optarg to NULL for options w/o a param
+ We rely on this here... */
+ args->flags |= F_USE_UUID;
+ return;
+ }
+
+ args->flags |= ( !!atoi(value) ? F_USE_UUID : 0);
+}
+
+
+static inline void
+assign_timeout(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ char *p;
+ int ret;
+
+ if (!value)
+ return;
+
+ ret = strtol(value, &p, 0);
+ if (ret <= 0 || *p != '\0') {
+ printf("Invalid timeout: '%s'\n", value);
+ args->flags |= F_ERR;
+ } else
+ args->timeout = ret;
+}
+
+static inline void
+assign_delay(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ char *p;
+ int ret;
+
+ if (!value)
+ return;
+
+ ret = strtol(value, &p, 0);
+ if (ret < 0 || *p != '\0') {
+ printf("Invalid delay: '%s'\n", value);
+ args->flags |= F_ERR;
+ } else
+ args->delay = ret;
+}
+
+static inline void
+assign_help(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ args->flags |= F_HELP;
+}
+
+
+static inline void
+assign_version(fence_virt_args_t *args, struct arg_info *arg, char *value)
+{
+ args->flags |= F_VERSION;
+}
+
+
+static void
+print_desc_xml(const char *desc)
+{
+ const char *d;
+
+ for (d = desc; *d; d++) {
+ switch (*d) {
+ case '<':
+ printf("&lt;");
+ break;
+ case '>':
+ printf("&gt;");
+ break;
+ default:
+ printf("%c", *d);
+ }
+ }
+}
+
+
+/** ALL valid command line and stdin arguments for this fencing agent */
+static struct arg_info _arg_info[] = {
+ { '\xff', NULL, "agent",
+ NULL, 0, 0, "string", NULL,
+ "Not user serviceable",
+ NULL },
+
+ { '\xff', NULL, "self",
+ NULL, 0, 0, "string", NULL,
+ "Not user serviceable",
+ NULL },
+
+ { '\xff', NULL, "nodename",
+ NULL, 0, 0, "string", NULL,
+ "Not user serviceable",
+ NULL },
+
+ { 'd', "-d", "debug",
+ NULL, 0, 0, "boolean", NULL,
+ "Specify (stdin) or increment (command line) debug level",
+ assign_debug },
+
+ { 'i', "-i <family>", "ip_family",
+ NULL, 0, 0, "string", "auto",
+ "IP Family ([auto], ipv4, ipv6)",
+ assign_family },
+
+ { 'a', "-a <address>", "multicast_address",
+ NULL, 0, 0, "string", NULL,
+ "Multicast address (default=" IPV4_MCAST_DEFAULT " / " IPV6_MCAST_DEFAULT ")",
+ assign_address },
+
+ { 'T', "-T <address>", "ipaddr",
+ NULL, 0, 0, "string", "127.0.0.1",
+ "IP address to connect to in TCP mode (default=" IPV4_TCP_ADDR_DEFAULT " / " IPV6_TCP_ADDR_DEFAULT ")",
+ assign_ip_address },
+
+ { 'S', "-S <cid>", "vsock",
+ NULL, 0, 0, "integer", "2",
+ "vm socket CID to connect to in vsock mode",
+ assign_cid },
+
+ { 'A', "-A <address>", "channel_address",
+ NULL, 0, 0, "string", "10.0.2.179",
+ "VM Channel IP address (default=" DEFAULT_CHANNEL_IP ")",
+ assign_channel_address },
+
+ { 'p', "-p <port>", "ipport",
+ NULL, 0, 0, "string", "1229",
+ "TCP, Multicast, VMChannel, or VM socket port (default=1229)",
+ assign_port },
+
+ { 'I', "-I <interface>", "interface",
+ NULL, 0, 0, "string", NULL,
+ "Network interface name to listen on",
+ assign_interface },
+
+ { 'r', "-r <retrans>", "retrans",
+ NULL, 0, 0, "string", "20",
+ "Multicast retransmit time (in 1/10sec; default=20)",
+ assign_retrans },
+
+ { 'c', "-c <hash>", "hash",
+ NULL, 0, 0, "string", "sha256",
+ "Packet hash strength (none, sha1, [sha256], sha512)",
+ assign_hash },
+
+ { 'C', "-C <auth>", "auth",
+ NULL, 0, 0, "string", "sha256",
+ "Authentication (none, sha1, [sha256], sha512)",
+ assign_auth },
+
+ { 'k', "-k <file>", "key_file",
+ NULL, 0, 0, "string", DEFAULT_KEY_FILE,
+ "Shared key file (default=" DEFAULT_KEY_FILE ")",
+ assign_key },
+
+ { 'D', "-D <device>", "serial_device",
+ NULL, 0, 0, "string", DEFAULT_SERIAL_DEVICE,
+ "Serial device (default=" DEFAULT_SERIAL_DEVICE ")",
+ assign_device },
+
+ { 'P', "-P <param>", "serial_params",
+ NULL, 0, 0, "string", DEFAULT_SERIAL_SPEED,
+ "Serial Parameters (default=" DEFAULT_SERIAL_SPEED ")",
+ assign_params },
+
+ { '\xff', NULL, "option",
+ /* Deprecated */
+ NULL, 0, 0, "string", "reboot",
+ "Fencing option (null, off, on, [reboot], status, list, list-status, monitor, validate-all, metadata)",
+ assign_op },
+
+ { 'o', "-o <operation>", "action",
+ NULL, 0, 0, "string", "reboot",
+ "Fencing action (null, off, on, [reboot], status, list, list-status, monitor, validate-all, metadata)",
+ assign_op },
+
+ { 'n', "-n <domain>", "plug",
+ "port", 0, 0, "string", NULL,
+ "Virtual Machine (domain name) to fence",
+ assign_domain },
+
+ { 'H', "-H <domain>", "port",
+ NULL, 1, 0, "string", NULL,
+ "Virtual Machine (domain name) to fence",
+ assign_domain },
+
+ { SCHEMA_COMPAT, NULL, "domain",
+ NULL, 0, 0, "string", NULL,
+ "Virtual Machine (domain name) to fence (deprecated; use port)",
+ assign_domain },
+
+ { 'u', "-u", "use_uuid",
+ NULL, 0, 0, "string", "0",
+ "Treat [domain] as UUID instead of domain name. This is provided for compatibility with older fence_xvmd installations.",
+ assign_uuid_lookup },
+
+ { 't', "-t <timeout>", "timeout",
+ NULL, 0, 0, "string", "30",
+ "Fencing timeout (in seconds; default=30)",
+ assign_timeout },
+
+ { 'h', "-h", NULL,
+ NULL, 0, 0, "boolean", "0",
+ "Help",
+ assign_help },
+
+ { '?', "-?", NULL,
+ NULL, 0, 0, "boolean", "0",
+ "Help (alternate)",
+ assign_help },
+
+ { 'w', "-w <delay>", "delay",
+ NULL, 0, 0, "string", "0",
+ "Fencing delay (in seconds; default=0)",
+ assign_delay },
+
+ { 'V', "-V", NULL,
+ NULL, 0, 0, "boolean", "0",
+ "Display version and exit",
+ assign_version },
+
+ /* Terminator */
+ { 0, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
+
+static struct arg_info *
+find_arg_by_char(char arg)
+{
+ int x = 0;
+
+ for (x = 0; _arg_info[x].opt != 0; x++) {
+ if (_arg_info[x].opt == arg)
+ return &_arg_info[x];
+ }
+
+ return NULL;
+}
+
+
+static struct arg_info *
+find_arg_by_string(char *arg)
+{
+ int x = 0;
+
+ for (x = 0; _arg_info[x].opt != 0; x++) {
+ if (!_arg_info[x].stdin_opt)
+ continue;
+ if (!strcasecmp(_arg_info[x].stdin_opt, arg))
+ return &_arg_info[x];
+ }
+
+ return NULL;
+}
+
+
+/* ============================================================= */
+
+/**
+ Initialize an args structure.
+
+ @param args Pointer to args structure to initialize.
+ */
+void
+args_init(fence_virt_args_t *args)
+{
+ args->domain = NULL;
+ //args->uri = NULL;
+ args->op = FENCE_REBOOT;
+ args->net.key_file = strdup(DEFAULT_KEY_FILE);
+ args->net.hash = DEFAULT_HASH;
+ args->net.auth = DEFAULT_AUTH;
+ args->net.addr = NULL;
+ args->net.ipaddr = NULL;
+ args->net.cid = 0;
+ args->net.port = DEFAULT_MCAST_PORT;
+ args->net.ifindex = 0;
+ args->net.family = 0; /* auto */
+ args->serial.device = NULL;
+ args->serial.speed = strdup(DEFAULT_SERIAL_SPEED);
+ args->serial.address = strdup(DEFAULT_CHANNEL_IP);
+ args->timeout = 30;
+ args->retr_time = 20;
+ args->flags = 0;
+ args->debug = 0;
+ args->delay = 0;
+}
+
+
+#define _pr_int(piece) printf(" %s = %d\n", #piece, piece)
+#define _pr_str(piece) printf(" %s = %s\n", #piece, piece)
+
+
+/**
+ Prints out the contents of an args structure for debugging.
+
+ @param args Pointer to args structure to print out.
+ */
+void
+args_print(fence_virt_args_t *args)
+{
+ printf("-- args @ %p --\n", args);
+ _pr_str(args->domain);
+ _pr_int(args->op);
+ _pr_int(args->mode);
+ _pr_int(args->debug);
+ _pr_int(args->timeout);
+ _pr_int(args->delay);
+ _pr_int(args->retr_time);
+ _pr_int(args->flags);
+
+ _pr_str(args->net.addr);
+ _pr_str(args->net.ipaddr);
+ _pr_int(args->net.cid);
+ _pr_str(args->net.key_file);
+ _pr_int(args->net.port);
+ _pr_int(args->net.hash);
+ _pr_int(args->net.auth);
+ _pr_int(args->net.family);
+ _pr_int(args->net.ifindex);
+
+ _pr_str(args->serial.device);
+ _pr_str(args->serial.speed);
+ _pr_str(args->serial.address);
+ printf("-- end args --\n");
+}
+
+
+/**
+ Print out arguments and help information based on what is allowed in
+ the getopt string optstr.
+
+ @param progname Program name.
+ @param optstr Getopt(3) style options string
+ @param print_stdin 0 = print command line options + description,
+ 1 = print fence-style stdin args + description
+ */
+static char *
+find_rev(const char *start, char *curr, char c)
+{
+
+ while (curr > start) {
+ if (*curr == c)
+ return curr;
+ --curr;
+ }
+
+ return NULL;
+}
+
+
+static void
+output_help_text(int arg_width, int help_width, const char *arg, const char *desc)
+{
+ char out_buf[4096];
+ char *p, *start;
+ const char *arg_print = arg;
+ int len;
+
+ memset(out_buf, 0, sizeof(out_buf));
+ strncpy(out_buf, desc, sizeof(out_buf) - 1);
+ start = out_buf;
+
+ do {
+ p = NULL;
+ len = strlen(start);
+ if (len > help_width) {
+ p = start + help_width;
+ p = find_rev(start, p, ' ');
+ if (p) {
+ *p = 0;
+ p++;
+ }
+ }
+ printf(" %*.*s %*.*s\n",
+ -arg_width, arg_width,
+ arg_print,
+ -help_width, help_width,
+ start);
+ if (!p)
+ return;
+ if (arg == arg_print)
+ arg_print = " ";
+ start = p;
+ } while(1);
+}
+
+
+void
+args_usage(char *progname, const char *optstr, int print_stdin)
+{
+ int x;
+ struct arg_info *arg;
+
+ if (!print_stdin) {
+ if (progname) {
+ printf("usage: %s [args]\n\nNOTE: reboot-action does not power on nodes that are powered off.\n\n", progname);
+ } else {
+ printf("usage: fence_virt [args]\n\nNOTE: reboot-action does not power on nodes that are powered off.\n\n");
+ }
+ }
+
+ for (x = 0; x < strlen(optstr); x++) {
+ arg = find_arg_by_char(optstr[x]);
+ if (!arg || arg->deprecated)
+ continue;
+
+ if (print_stdin) {
+ if (arg && arg->stdin_opt)
+ output_help_text(20, 55, arg->stdin_opt, arg->desc);
+ } else {
+ output_help_text(20, 55, arg->opt_desc, arg->desc);
+ }
+ }
+
+ printf("\n");
+}
+
+
+void
+args_metadata(char *progname, const char *optstr)
+{
+ int x;
+ struct arg_info *arg;
+
+ printf("<?xml version=\"1.0\" ?>\n");
+ printf("<resource-agent name=\"%s\" shortdesc=\"Fence agent for virtual machines\">\n", basename(progname));
+ printf("<longdesc>%s is an I/O Fencing agent which can be used with "
+ "virtual machines.\n\nNOTE: reboot-action does not power on nodes that are powered off."
+ "</longdesc>\n", basename(progname));
+ printf("<vendor-url>https://libvirt.org</vendor-url>\n");
+ printf("<parameters>\n");
+
+ for (x = 0; x < strlen(optstr); x++) {
+ arg = find_arg_by_char(optstr[x]);
+ if (!arg)
+ continue;
+ if (!arg->stdin_opt)
+ continue;
+
+ if (arg->obsoletes)
+ printf("\t<parameter name=\"%s\" unique=\"0\" required=\"%d\" obsoletes=\"%s\">\n", arg->stdin_opt, (!strcmp(arg->content_type, "boolean") || arg->default_value) ? 0 : 1, arg->obsoletes);
+ else if (arg->deprecated)
+ printf("\t<parameter name=\"%s\" unique=\"0\" required=\"%d\" deprecated=\"%d\">\n", arg->stdin_opt, (!strcmp(arg->content_type, "boolean") || arg->default_value) ? 0 : 1, arg->deprecated);
+ else
+ printf("\t<parameter name=\"%s\" unique=\"0\" required=\"%d\">\n", arg->stdin_opt, (!strcmp(arg->content_type, "boolean") || arg->default_value || !strcmp(arg->stdin_opt, "multicast_address")) ? 0 : 1);
+
+ printf("\t\t<getopt mixed=\"-%c\" />\n",arg->opt);
+ if (arg->default_value) {
+ printf("\t\t<content type=\"%s\" default=\"%s\" />\n", arg->content_type, arg->default_value);
+ } else {
+ printf("\t\t<content type=\"%s\" />\n", arg->content_type);
+ }
+ printf("\t\t<shortdesc lang=\"en\">");
+ print_desc_xml(arg->desc);
+ printf("</shortdesc>\n");
+ printf("\t</parameter>\n");
+ }
+
+ for (x = 0; _arg_info[x].opt != 0; x++) {
+ if (_arg_info[x].opt != SCHEMA_COMPAT)
+ continue;
+
+ arg = &_arg_info[x];
+
+ printf("\t<parameter name=\"%s\" unique=\"0\" required=\"%d\" deprecated=\"1\">\n", arg->stdin_opt,
+ (!strcmp(arg->content_type, "boolean") || arg->default_value || !strcmp(arg->stdin_opt, "domain")) ? 0 : 1);
+ printf("\t\t<getopt mixed=\"\" />\n");
+ if (arg->default_value) {
+ printf("\t\t<content type=\"%s\" default=\"%s\" />\n", arg->content_type, arg->default_value);
+ } else {
+ printf("\t\t<content type=\"%s\" />\n", arg->content_type);
+ }
+ printf("\t\t<shortdesc lang=\"en\">");
+ print_desc_xml(arg->desc);
+ printf("</shortdesc>\n");
+ printf("\t</parameter>\n");
+ }
+
+ printf("</parameters>\n");
+ printf("<actions>\n");
+ printf("\t<action name=\"null\" />\n");
+ printf("\t<action name=\"on\" />\n");
+ printf("\t<action name=\"off\" />\n");
+ printf("\t<action name=\"reboot\" />\n");
+ printf("\t<action name=\"metadata\" />\n");
+ printf("\t<action name=\"status\" />\n");
+ printf("\t<action name=\"monitor\" />\n");
+ printf("\t<action name=\"list\" />\n");
+ printf("\t<action name=\"list-status\" />\n");
+ printf("\t<action name=\"validate-all\" />\n");
+ printf("</actions>\n");
+ printf("</resource-agent>\n");
+}
+
+
+/**
+ Remove leading and trailing whitespace from a line of text.
+
+ @param line Line to clean up
+ @param linelen Max size of line
+ @return 0 on success, -1 on failure
+ */
+static int
+cleanup(char *line, size_t linelen)
+{
+ char *p;
+ int x;
+
+ /* Remove leading whitespace. */
+ p = line;
+ for (x = 0; x < linelen; x++) {
+ switch (line[x]) {
+ case '\t':
+ case ' ':
+ break;
+ case '\n':
+ case '\r':
+ return -1;
+ default:
+ goto eol;
+ }
+ }
+eol:
+ /* Move the remainder down by as many whitespace chars as we
+ chewed up */
+ if (x)
+ memmove(p, &line[x], linelen-x);
+
+ /* Remove trailing whitespace. */
+ for (x=0; x < linelen; x++) {
+ switch(line[x]) {
+ case '\t':
+ case ' ':
+ case '\r':
+ case '\n':
+ line[x] = 0;
+ case 0:
+ /* End of line */
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ Parse args from stdin and assign to the specified args structure.
+
+ @param optstr Command line option string in getopt(3) format
+ @param args Args structure to fill in.
+ */
+void
+args_get_stdin(const char *optstr, fence_virt_args_t *args)
+{
+ char in[256];
+ char *name, *val;
+ struct arg_info *arg;
+
+ while (fgets(in, sizeof(in), stdin)) {
+
+ if (in[0] == '#')
+ continue;
+
+ if (cleanup(in, sizeof(in)) == -1)
+ continue;
+
+ name = in;
+ if ((val = strchr(in, '='))) {
+ *val = 0;
+ ++val;
+ }
+
+ arg = find_arg_by_string(name);
+ if (!arg || (arg->opt != '\xff' &&
+ arg->opt != SCHEMA_COMPAT &&
+ !strchr(optstr, arg->opt))) {
+ fprintf(stderr,
+ "Parse error: Ignoring unknown option '%s'\n",
+ name);
+ continue;
+ }
+
+ if (arg->assign)
+ arg->assign(args, arg, val);
+ }
+}
+
+
+/**
+ Parse args from stdin and assign to the specified args structure.
+
+ @param optstr Command line option string in getopt(3) format
+ @param args Args structure to fill in.
+ */
+void
+args_get_getopt(int argc, char **argv, const char *optstr, fence_virt_args_t *args)
+{
+ int opt;
+ struct arg_info *arg;
+
+ while ((opt = getopt(argc, argv, optstr)) != EOF) {
+
+ arg = find_arg_by_char(opt);
+
+ if (!arg) {
+ args->flags |= F_ERR;
+ continue;
+ }
+
+ if (arg->assign)
+ arg->assign(args, arg, optarg);
+ }
+}
+
+
+void
+args_finalize(fence_virt_args_t *args)
+{
+ char *addr = NULL;
+
+ if (!args->net.addr) {
+ switch(args->net.family) {
+ case 0:
+ case PF_INET:
+ addr = (char *)IPV4_MCAST_DEFAULT;
+ break;
+ case PF_INET6:
+ addr = (char *)IPV6_MCAST_DEFAULT;
+ break;
+ default:
+ args->flags |= F_ERR;
+ break;
+ }
+ }
+
+ if (!args->net.addr)
+ args->net.addr = addr;
+
+ if (!args->net.addr) {
+ printf("No multicast address available\n");
+ args->flags |= F_ERR;
+ }
+
+ if (!args->net.addr)
+ return;
+ if (args->net.family)
+ return;
+
+ /* Set family */
+ if (strchr(args->net.addr, ':'))
+ args->net.family = PF_INET6;
+ if (strchr(args->net.addr, '.'))
+ args->net.family = PF_INET;
+ if (!args->net.family) {
+ printf("Could not determine address family\n");
+ args->flags |= F_ERR;
+ }
+}
diff --git a/agents/virt/client/serial.c b/agents/virt/client/serial.c
new file mode 100644
index 0000000..238ef4a
--- /dev/null
+++ b/agents/virt/client/serial.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2002-2003, 2009 Red Hat, Inc.
+ *
+ * License: GPLv2+
+ *
+ * Written by Lon Hohberger <lhh@redhat.com>
+ *
+ * Serial client for fence_virt (incomplete, but
+ * a good start)
+ *
+ * Based on:
+ * Ubersimpledumbterminal "ser" version 1.0.3
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+
+#include "fdops.h"
+#include "xvm.h"
+#include "options.h"
+#include "client.h"
+#include "tcp.h"
+
+
+static int
+char_to_speed(const char *speed)
+{
+ if (!speed || !strlen(speed))
+ return B9600;
+ if (!strcmp(speed,"2400"))
+ return B2400;
+ if (!strcmp(speed,"9600"))
+ return B9600;
+ if (!strcmp(speed,"19200"))
+ return B19200;
+ if (!strcmp(speed,"38400"))
+ return B38400;
+ if (!strcmp(speed,"57600"))
+ return B57600;
+ if (!strcmp(speed,"115200"))
+ return B115200;
+ return -1;
+}
+
+
+static int
+char_to_flags(const char *param)
+{
+ int db_f = CS8, par_f = 0, sb_f = 0, x;
+
+ if (!param || !strlen(param))
+ return (db_f | par_f | sb_f);
+
+ if (strlen(param) < 3) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (x = 0; x < 3; x++) {
+ switch (param[x]) {
+ case '5':
+ db_f = CS5;
+ break;
+ case '6':
+ db_f = CS6;
+ break;
+ case '7':
+ db_f = CS7;
+ break;
+ case '8':
+ db_f = CS8;
+ break;
+ case 'n':
+ case 'N':
+ par_f = 0;
+ break;
+ case 'e':
+ case 'E':
+ par_f = PARENB;
+ break;
+ case 'o':
+ case 'O':
+ par_f = PARENB | PARODD;
+ break;
+ case '1':
+ sb_f = 0;
+ break;
+ case '2':
+ sb_f = CSTOPB;
+ break;
+ default:
+ printf("Fail: %c\n", param[x]);
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ return (db_f | par_f | sb_f);
+}
+
+
+static int
+open_port(char *file, char *cspeed, char *cparam)
+{
+ struct termios ti;
+ int fd, speed = B115200, flags = 0;
+ struct flock lock;
+
+ if ((speed = char_to_speed(cspeed)) == -1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((flags = char_to_flags(cparam)) == -1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((fd = open(file, O_RDWR | O_EXCL)) == -1) {
+ perror("open");
+ return -1;
+ }
+
+ memset(&lock,0,sizeof(lock));
+ lock.l_type = F_WRLCK;
+ if (fcntl(fd, F_SETLK, &lock) == -1) {
+ perror("Failed to lock serial port");
+ close(fd);
+ return -1;
+ }
+
+ memset(&ti, 0, sizeof(ti));
+ ti.c_cflag = (speed | CLOCAL | CRTSCTS | CREAD | flags);
+
+ if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+ perror("tcsetattr");
+ close(fd);
+ return -1;
+ }
+
+ (void) tcflush(fd, TCIOFLUSH);
+
+ return fd;
+}
+
+
+static void
+hangup(int fd, int delay)
+{
+ unsigned int bits;
+
+ if (ioctl(fd, TIOCMGET, &bits)) {
+ perror("ioctl1");
+ return;
+ }
+
+ bits &= ~(TIOCM_DTR | TIOCM_CTS | TIOCM_RTS | TIOCM_DSR | TIOCM_CD);
+
+ if (ioctl(fd, TIOCMSET, &bits)) {
+ perror("ioctl2");
+ return;
+ }
+
+ usleep(delay);
+
+ bits |= (TIOCM_DTR | TIOCM_CTS | TIOCM_RTS | TIOCM_DSR | TIOCM_CD);
+
+ if (ioctl(fd, TIOCMSET, &bits)) {
+ perror("ioctl3");
+ return;
+ }
+}
+
+static int
+wait_for(int fd, const char *pattern, size_t size, struct timeval *tout)
+{
+ char *pos = (char *)pattern;
+ char c;
+ int n;
+ struct timeval tv;
+ size_t remain = size;
+
+ if (tout) {
+ memcpy(&tv, tout, sizeof(tv));
+ tout = &tv;
+ }
+
+ while (remain) {
+ n = _read_retry(fd, &c, 1, &tv);
+ if (n < 1)
+ return -1;
+
+ if (c == *pos) {
+ ++pos;
+ --remain;
+ } else {
+ pos = (char *)pattern;
+ remain = size;
+ }
+ }
+
+ return 0;
+}
+
+int
+serial_fence_virt(fence_virt_args_t *args)
+{
+ struct in_addr ina;
+ struct in6_addr in6a;
+ serial_req_t req;
+ int fd, ret;
+ char speed[32], *flags = NULL;
+ struct timeval tv;
+ serial_resp_t resp;
+
+ if (args->serial.device) {
+ strncpy(speed, args->serial.speed, sizeof(speed) - 1);
+
+ //printf("Port: %s Speed: %s\n", args->serial.device, speed);
+
+ if ((flags = strchr(speed, ','))) {
+ *flags = 0;
+ flags++;
+ }
+
+ fd = open_port(args->serial.device, speed, flags);
+ if (fd == -1) {
+ perror("open_port");
+ return -1;
+ }
+
+ hangup(fd, 300000);
+ } else {
+ fd = -1;
+ if (inet_pton(PF_INET, args->serial.address, &ina)) {
+ fd = ipv4_connect(&ina, args->net.port, 3);
+ } else if (inet_pton(PF_INET6, args->serial.address, &in6a)) {
+ fd = ipv6_connect(&in6a, args->net.port, 3);
+ }
+
+ if (fd < 0) {
+ perror("vmchannel connect");
+ printf("Failed to connect to %s:%d\n", args->serial.address,
+ args->net.port);
+ return -1;
+ }
+ }
+
+
+ memset(&req, 0, sizeof(req));
+ req.magic = SERIAL_MAGIC;
+ req.request = (uint8_t)args->op;
+ gettimeofday(&tv, NULL);
+ req.seqno = (int)tv.tv_usec;
+
+ if (args->domain)
+ strncpy((char *)req.domain, args->domain, sizeof(req.domain) - 1);
+
+ tv.tv_sec = 3;
+ tv.tv_usec = 0;
+ swab_serial_req_t(&req);
+ ret = _write_retry(fd, &req, sizeof(req), &tv);
+ if (ret < sizeof(req)) {
+ if (ret < 0) {
+ close(fd);
+ return ret;
+ }
+ printf("Failed to send request\n");
+ }
+
+ tv.tv_sec = args->timeout;
+ tv.tv_usec = 0;
+ resp.magic = SERIAL_MAGIC;
+ do {
+ if (wait_for(fd, (const char *)&resp.magic,
+ sizeof(resp.magic), &tv) == 0) {
+ ret = _read_retry(fd, &resp.response, sizeof(resp.response), &tv);
+ } else {
+ /* The other end died or closed the connection */
+ close(fd);
+ return -1;
+ }
+
+ swab_serial_resp_t(&resp);
+ } while(resp.magic != SERIAL_MAGIC && (tv.tv_sec || tv.tv_usec));
+
+ if (resp.magic != SERIAL_MAGIC) {
+ close(fd);
+ return -1;
+ }
+ ret = resp.response;
+ if (resp.response == RESP_HOSTLIST) /* hostlist */ {
+ /* ok read hostlist */
+ do_read_hostlist(fd, args->timeout);
+ ret = 0;
+ }
+
+ close(fd);
+ return ret;
+}
diff --git a/agents/virt/client/tcp.c b/agents/virt/client/tcp.c
new file mode 100644
index 0000000..986fdd9
--- /dev/null
+++ b/agents/virt/client/tcp.c
@@ -0,0 +1,171 @@
+/*
+ Copyright Red Hat, Inc. 2006-2012
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <nss.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "simple_auth.h"
+#include "options.h"
+#include "tcp.h"
+#include "debug.h"
+#include "fdops.h"
+#include "client.h"
+
+static int
+tcp_exchange(int fd, fence_auth_type_t auth, void *key,
+ size_t key_len, int timeout)
+{
+ fd_set rfds;
+ struct timeval tv;
+ char ret = 1;
+
+ /* Ok, we're connected */
+ dbg_printf(3, "Issuing TCP challenge\n");
+ if (sock_challenge(fd, auth, key, key_len, timeout) <= 0) {
+ /* Challenge failed */
+ printf("Invalid response to challenge\n");
+ return 1;
+ }
+
+ /* Now they'll send us one, so we need to respond here */
+ dbg_printf(3, "Responding to TCP challenge\n");
+ if (sock_response(fd, auth, key, key_len, timeout) <= 0) {
+ printf("Invalid response to challenge\n");
+ return 1;
+ }
+
+ dbg_printf(2, "TCP Exchange + Authentication done... \n");
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ ret = 1;
+ dbg_printf(3, "Waiting for return value from fence_virtd host\n");
+ if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0)
+ return -1;
+
+ /* Read return code */
+ if (_read_retry(fd, &ret, 1, &tv) < 0)
+ ret = 1;
+
+ if (ret == (char)RESP_HOSTLIST) /* hostlist */ {
+ do_read_hostlist(fd, timeout);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int
+tcp_fence_virt(fence_virt_args_t *args)
+{
+ char key[MAX_KEY_LEN];
+ struct timeval tv;
+ int key_len = 0, fd = -1;
+ int ret;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ fence_req_t freq;
+
+ /* Initialize NSS; required to do hashing, as silly as that
+ sounds... */
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ printf("Could not initialize NSS\n");
+ return 1;
+ }
+
+ if (args->net.auth != AUTH_NONE || args->net.hash != HASH_NONE) {
+ key_len = read_key_file(args->net.key_file, key, sizeof(key));
+ if (key_len < 0) {
+ printf("Could not read %s; trying without "
+ "authentication\n", args->net.key_file);
+ args->net.auth = AUTH_NONE;
+ args->net.hash = HASH_NONE;
+ key_len = 0;
+ }
+ }
+
+ /* Same wire protocol as fence_xvm */
+ memset(&freq, 0, sizeof(freq));
+ if (args->domain && strlen((char *)args->domain))
+ strncpy((char *)freq.domain, args->domain, sizeof(freq.domain) - 1);
+ freq.request = args->op;
+ freq.hashtype = args->net.hash;
+ freq.flags = 0;
+ if (args->flags & F_USE_UUID)
+ freq.flags |= RF_UUID;
+ gettimeofday(&tv, NULL);
+ freq.seqno = (uint32_t) tv.tv_usec;
+ sign_request(&freq, key, key_len);
+
+ /* XXX fixme */
+ if (inet_pton(PF_INET, args->net.ipaddr, &ina)) {
+ fd = ipv4_connect(&ina, args->net.port, 3);
+ } else if (inet_pton(PF_INET6, args->net.ipaddr, &in6a)) {
+ fd = ipv6_connect(&in6a, args->net.port, 3);
+ }
+
+ if (fd < 0) {
+ printf("Unable to connect to fence_virtd host %s:%d %s\n",
+ args->net.ipaddr, args->net.port, strerror(errno));
+ return 1;
+ }
+
+ ret = _write_retry(fd, &freq, sizeof(freq), NULL);
+ if (ret != sizeof(freq)) {
+ perror("write");
+ close(fd);
+ return 1;
+ }
+
+ switch (args->net.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ ret = tcp_exchange(fd, args->net.auth, key, key_len,
+ args->timeout);
+ break;
+ /* case AUTH_X509:
+ return ssl_exchange(...); */
+ default:
+ dbg_printf(3, "Unknown auth type: %d\n", args->net.auth);
+ ret = 1;
+ break;
+ }
+
+ close(fd);
+ return ret;
+}
diff --git a/agents/virt/client/vsock.c b/agents/virt/client/vsock.c
new file mode 100644
index 0000000..7557c54
--- /dev/null
+++ b/agents/virt/client/vsock.c
@@ -0,0 +1,176 @@
+/*
+ Copyright Red Hat, Inc. 2017
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <nss.h>
+#include <sys/socket.h>
+#include <linux/vm_sockets.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "simple_auth.h"
+#include "options.h"
+#include "debug.h"
+#include "fdops.h"
+#include "client.h"
+
+static int
+sock_exchange(int fd, fence_auth_type_t auth, void *key,
+ size_t key_len, int timeout)
+{
+ fd_set rfds;
+ struct timeval tv;
+ char ret = 1;
+
+ /* Ok, we're connected */
+ dbg_printf(3, "Issuing challenge\n");
+ if (sock_challenge(fd, auth, key, key_len, timeout) <= 0) {
+ /* Challenge failed */
+ printf("Invalid response to challenge\n");
+ return 1;
+ }
+
+ /* Now they'll send us one, so we need to respond here */
+ dbg_printf(3, "Responding to challenge\n");
+ if (sock_response(fd, auth, key, key_len, timeout) <= 0) {
+ printf("Invalid response to challenge\n");
+ return 1;
+ }
+
+ dbg_printf(2, "vsock Exchange + Authentication done... \n");
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ ret = 1;
+ dbg_printf(3, "Waiting for return value from fence_virtd host\n");
+ if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0)
+ return -1;
+
+ /* Read return code */
+ if (_read_retry(fd, &ret, 1, &tv) < 0)
+ ret = 1;
+
+ if (ret == (char)RESP_HOSTLIST) /* hostlist */ {
+ do_read_hostlist(fd, timeout);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int
+vsock_fence_virt(fence_virt_args_t *args)
+{
+ char key[MAX_KEY_LEN];
+ struct timeval tv;
+ int key_len = 0, fd = -1;
+ int ret;
+ struct sockaddr_vm svm;
+ fence_req_t freq;
+
+ /* Initialize NSS; required to do hashing, as silly as that
+ sounds... */
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ printf("Could not initialize NSS\n");
+ return 1;
+ }
+
+ if (args->net.auth != AUTH_NONE || args->net.hash != HASH_NONE) {
+ key_len = read_key_file(args->net.key_file, key, sizeof(key));
+ if (key_len < 0) {
+ printf("Could not read %s; trying without "
+ "authentication\n", args->net.key_file);
+ args->net.auth = AUTH_NONE;
+ args->net.hash = HASH_NONE;
+ key_len = 0;
+ }
+ }
+
+ /* Same wire protocol as fence_xvm */
+ memset(&freq, 0, sizeof(freq));
+ if (args->domain && strlen((char *)args->domain))
+ strncpy((char *)freq.domain, args->domain, sizeof(freq.domain) - 1);
+ freq.request = args->op;
+ freq.hashtype = args->net.hash;
+ freq.flags = 0;
+ if (args->flags & F_USE_UUID)
+ freq.flags |= RF_UUID;
+ gettimeofday(&tv, NULL);
+ freq.seqno = (uint32_t) tv.tv_usec;
+ sign_request(&freq, key, key_len);
+
+ fd = socket(PF_VSOCK, SOCK_STREAM, 0);
+ if (fd < 0) {
+ printf("Unable to create vsock: %s", strerror(errno));
+ return 1;
+ }
+
+ memset(&svm, 0, sizeof(svm));
+ svm.svm_family = AF_VSOCK;
+ svm.svm_cid = args->net.cid;
+ svm.svm_port = args->net.port;
+
+ if (connect(fd, (struct sockaddr *) &svm, sizeof(svm)) < 0) {
+ printf("Unable to connect to fence_virtd host %d:%d %s\n",
+ args->net.cid, args->net.port, strerror(errno));
+ close(fd);
+ return 1;
+ }
+
+ ret = _write_retry(fd, &freq, sizeof(freq), NULL);
+ if (ret != sizeof(freq)) {
+ perror("write");
+ close(fd);
+ return 1;
+ }
+
+ switch (args->net.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ ret = sock_exchange(fd, args->net.auth, key, key_len,
+ args->timeout);
+ break;
+ /* case AUTH_X509:
+ return ssl_exchange(...); */
+ default:
+ dbg_printf(3, "Unknown auth type: %d\n", args->net.auth);
+ ret = 1;
+ break;
+ }
+
+ close(fd);
+ return ret;
+}
diff --git a/agents/virt/common/Makefile.am b/agents/virt/common/Makefile.am
new file mode 100644
index 0000000..d5e4314
--- /dev/null
+++ b/agents/virt/common/Makefile.am
@@ -0,0 +1,24 @@
+###############################################################################
+###############################################################################
+##
+## Copyright (C) 2009-2019 Red Hat, Inc.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2.
+##
+###############################################################################
+###############################################################################
+
+MAINTAINERCLEANFILES = Makefile.in
+
+noinst_LTLIBRARIES = libfence_virt.la
+
+libfence_virt_la_SOURCES = mcast.c ip_lookup.c simple_auth.c tcp.c \
+ debug.c fdops.c log.c
+
+libfence_virt_la_CFLAGS = $(VIRT_AM_CFLAGS) $(nss_CFLAGS) $(AM_CFLAGS) -Wno-cast-align
+
+libfence_virt_la_LDFLAGS = $(VIRT_AM_LDFLAGS) $(VIRT_COMMON_LDFLAGS)
+
+libfence_virt_la_LIBADD = $(nss_LIBS)
diff --git a/agents/virt/common/bcast.c b/agents/virt/common/bcast.c
new file mode 100644
index 0000000..2b498b7
--- /dev/null
+++ b/agents/virt/common/bcast.c
@@ -0,0 +1,347 @@
+/*
+ * Author: Lon Hohberger <lhh at redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+
+/* Local includes */
+#include "bcast.h"
+#include "debug.h"
+
+LOGSYS_DECLARE_SUBSYS ("XVM", SYSLOGLEVEL);
+
+/**
+ Sets up a multicast receive socket
+ */
+int
+ipv4_bcast_recv_sk(char *addr, int port)
+{
+ int sock, val;
+ struct sockaddr_in sin;
+
+ /* Store broadcast address */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = PF_INET;
+ sin.sin_port = htons(port);
+ if (inet_pton(PF_INET, addr,
+ (void *)&sin.sin_addr.s_addr) < 0) {
+ log_printf(LOG_ERR, "Invalid broadcast address: %s\n", addr);
+ return -1;
+ }
+
+ dbg_printf(4, "Setting up ipv4 broadcast receive (%s:%d)\n", addr, port);
+ sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ log_printf(LOG_ERR, "socket: %s\n", strerror(errno));
+ close(sock);
+ sock = -1;
+ return 1;
+ }
+
+ val = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, 1, sizeof(val)) < 0) {
+ log_printf(LOG_ERR, "setsockopt: %s\n", strerror(errno));
+ close(sock);
+ return 1;
+ }
+
+ /*
+ * Bind broadcast address
+ */
+ if (bind(sock, (struct sockaddr *) &sin,
+ sizeof(struct sockaddr_in)) < 0) {
+ printf("bind failed: %s\n", strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
+
+
+/**
+ Set up multicast send socket
+ */
+int
+ipv4_bcast_send_sk(char *send_addr, char *addr, int port, struct sockaddr *tgt,
+ socklen_t tgt_len, int ttl)
+{
+ int val;
+ struct ip_mreq mreq;
+ struct sockaddr_in mcast;
+ struct sockaddr_in src;
+ int sock;
+
+ if (tgt_len < sizeof(struct sockaddr_in)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Store multicast address */
+ mcast.sin_family = PF_INET;
+ mcast.sin_port = htons(port);
+ if (inet_pton(PF_INET, addr,
+ (void *)&mcast.sin_addr.s_addr) < 0) {
+ printf("Invalid multicast address: %s\n", addr);
+ return -1;
+ }
+ mreq.imr_multiaddr.s_addr = mcast.sin_addr.s_addr;
+
+ /* Store sending address */
+ src.sin_family = PF_INET;
+ src.sin_port = htons(port);
+ if (inet_pton(PF_INET, send_addr,
+ (void *)&src.sin_addr.s_addr) < 0) {
+ printf("Invalid source address: %s\n", send_addr);
+ return -1;
+ }
+ mreq.imr_interface.s_addr = src.sin_addr.s_addr;
+
+
+ /*************************
+ * SET UP MULTICAST SEND *
+ *************************/
+ dbg_printf(4, "Setting up ipv4 multicast send (%s:%d)\n", addr, port);
+ sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ /*
+ * Join Multicast group.
+ */
+ dbg_printf(4, "Joining IP Multicast group (pass 1)\n");
+ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq)) == -1) {
+ printf("Failed to add multicast membership to transmit "
+ "socket %s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join Multicast group.
+ */
+ dbg_printf(4, "Joining IP Multicast group (pass 2)\n");
+ if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &src.sin_addr,
+ sizeof(src.sin_addr)) == -1) {
+ printf("Failed to bind multicast transmit socket to "
+ "%s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * set time to live to 2 hops.
+ */
+ dbg_printf(4, "Setting TTL to %d for fd%d\n", ttl, sock);
+ val = ttl;
+ if (setsockopt(sock, SOL_IP, IP_MULTICAST_TTL, &val,
+ sizeof(val)))
+ printf("warning: setting TTL failed %s\n", strerror(errno));
+
+ memcpy((struct sockaddr_in *)tgt, &mcast, sizeof(struct sockaddr_in));
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
+
+
+
+/**
+ Sets up a multicast receive (ipv6) socket
+ */
+int
+ipv6_recv_sk(char *addr, int port)
+{
+ int sock, val;
+ struct ipv6_mreq mreq;
+ struct sockaddr_in6 sin;
+
+ memset(&mreq, 0, sizeof(mreq));
+ memset(&sin, 0, sizeof(sin));
+ sin.sin6_family = PF_INET6;
+ sin.sin6_port = htons(port);
+ if (inet_pton(PF_INET6, addr,
+ (void *)&sin.sin6_addr) < 0) {
+ printf("Invalid multicast address: %s\n", addr);
+ return -1;
+ }
+
+ memcpy(&mreq.ipv6mr_multiaddr, &sin.sin6_addr,
+ sizeof(struct in6_addr));
+
+
+ /********************************
+ * SET UP MULTICAST RECV SOCKET *
+ ********************************/
+ dbg_printf(4, "Setting up ipv6 multicast receive (%s:%d)\n", addr, port);
+ sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0) {
+ printf("socket: %s\n", strerror(errno));
+ close(sock);
+ sock = -1;
+ return 1;
+ }
+
+ /*
+ * When using Multicast, bind to the LOCAL address, not the MULTICAST
+ * address.
+ */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin6_family = PF_INET6;
+ sin.sin6_port = htons(port);
+ sin.sin6_addr = in6addr_any;
+ if (bind(sock, (struct sockaddr *) &sin,
+ sizeof(struct sockaddr_in6)) < 0) {
+ printf("bind failed: %s\n", strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ dbg_printf(4, "Disabling IP Multicast loopback\n");
+ val = 1;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val,
+ sizeof(val)) != 0) {
+ printf("Failed to disable multicast loopback\n");
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join multicast group
+ */
+ dbg_printf(4, "Joining IP Multicast group\n");
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq)) == -1) {
+ printf("Failed to add multicast to socket %s: %s\n",
+ addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
+
+
+/**
+ Set up ipv6 multicast send socket
+ */
+int
+ipv6_send_sk(char *send_addr, char *addr, int port, struct sockaddr *tgt,
+ socklen_t tgt_len, int ttl)
+{
+ int val;
+ struct ipv6_mreq mreq;
+ struct sockaddr_in6 mcast;
+ struct sockaddr_in6 src;
+ int sock;
+
+ if (tgt_len < sizeof(struct sockaddr_in6)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(&mreq, 0, sizeof(mreq));
+
+ /* Store multicast address */
+ mcast.sin6_family = PF_INET6;
+ mcast.sin6_port = htons(port);
+ if (inet_pton(PF_INET6, addr,
+ (void *)&mcast.sin6_addr) < 0) {
+ printf("Invalid multicast address: %s\n", addr);
+ return -1;
+ }
+
+ memcpy(&mreq.ipv6mr_multiaddr, &mcast.sin6_addr,
+ sizeof(struct in6_addr));
+
+ /* Store sending address */
+ src.sin6_family = PF_INET6;
+ src.sin6_port = htons(port);
+ if (inet_pton(PF_INET6, send_addr,
+ (void *)&src.sin6_addr) < 0) {
+ printf("Invalid source address: %s\n", send_addr);
+ return -1;
+ }
+
+ /*************************
+ * SET UP MULTICAST SEND *
+ *************************/
+ dbg_printf(4, "Setting up ipv6 multicast send (%s:%d)\n", addr, port);
+ sock = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ dbg_printf(4, "Disabling IP Multicast loopback\n");
+ val = 1;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val,
+ sizeof(val)) != 0) {
+ printf("Failed to disable multicast loopback\n");
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join Multicast group.
+ */
+ dbg_printf(4, "Joining IP Multicast group\n");
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq)) == -1) {
+ printf("Failed to add multicast membership to transmit "
+ "socket %s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join Multicast group (part 2)
+ */
+ /*
+ if (setsockopt(sock, IPPROTO_IPV6, IP_MULTICAST_IF, &src.sin6_addr,
+ sizeof(src.sin6_addr)) == -1) {
+ printf("Failed to bind multicast transmit socket to "
+ "%s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+ */
+
+ /*
+ * set time to live to 2 hops.
+ */
+ val = ttl;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val,
+ sizeof(val)))
+ printf("warning: setting TTL failed %s\n", strerror(errno));
+
+ memcpy((struct sockaddr_in *)tgt, &mcast, sizeof(struct sockaddr_in6));
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
diff --git a/agents/virt/common/debug.c b/agents/virt/common/debug.c
new file mode 100644
index 0000000..5cf5359
--- /dev/null
+++ b/agents/virt/common/debug.c
@@ -0,0 +1,38 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include "debug.h"
+
+static int _debug = 0;
+
+void
+dset(int threshold)
+{
+ _debug = threshold;
+ dbg_printf(3, "Debugging threshold is now %d\n", threshold);
+}
+
+int
+dget(void)
+{
+ return _debug;
+}
diff --git a/agents/virt/common/fdops.c b/agents/virt/common/fdops.c
new file mode 100644
index 0000000..329e9b7
--- /dev/null
+++ b/agents/virt/common/fdops.c
@@ -0,0 +1,202 @@
+/*
+ Copyright Red Hat, Inc. 2002-2003
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/** @file
+ * Wrapper functions around read/write/select to retry in the event
+ * of interrupts.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "fdops.h"
+
+/**
+ * This is a wrapper around select which will retry in the case we receive
+ * EINTR. This is necessary for _read_retry, since it wouldn't make sense
+ * to have _read_retry terminate if and only if two EINTRs were received
+ * in a row - one during the read() call, one during the select call...
+ *
+ * See select(2) for description of parameters.
+ */
+int
+_select_retry(int fdmax, fd_set * rfds, fd_set * wfds, fd_set * xfds,
+ struct timeval *timeout)
+{
+ int rv;
+
+ while (1) {
+ rv = select(fdmax, rfds, wfds, xfds, timeout);
+ if (rv == -1) {
+ /* return on EBADF/EINVAL/ENOMEM; continue on EINTR/EAGAIN/ENOMEM */
+ if (errno == EINTR || errno == EAGAIN || errno == ENOMEM)
+ continue;
+ }
+ return rv;
+ }
+}
+
+/**
+ * Retries a write in the event of a non-blocked interrupt signal.
+ *
+ * @param fd File descriptor to which we are writing.
+ * @param buf Data buffer to send.
+ * @param count Number of bytes in buf to send.
+ * @param timeout (struct timeval) telling us how long we should retry.
+ * @return The number of bytes written to the file descriptor,
+ * or -1 on error (with errno set appropriately).
+ */
+ssize_t
+_write_retry(int fd, void *buf, int count, struct timeval * timeout)
+{
+ int n, total = 0, remain = count, rv = 0;
+ fd_set wfds, xfds;
+ char *tmp_buf = (char *)buf;
+
+ while (total < count) {
+
+ /* Create the write FD set of 1... */
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+ FD_ZERO(&xfds);
+ FD_SET(fd, &xfds);
+
+ /* wait for the fd to be available for writing */
+ rv = _select_retry(fd + 1, NULL, &wfds, &xfds, timeout);
+ if (rv == -1)
+ return -1;
+ else if (rv == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ if (FD_ISSET(fd, &xfds)) {
+ errno = EPIPE;
+ return -1;
+ }
+
+ /*
+ * Attempt to write to fd
+ */
+ n = write(fd, tmp_buf + total, remain);
+
+ /*
+ * When we know our fd was select()ed and we receive 0 bytes
+ * when we write, the fd was closed.
+ */
+ if ((n == 0) && (rv == 1)) {
+ errno = EPIPE;
+ return -1;
+ }
+
+ if (n == -1) {
+ if ((errno == EAGAIN) || (errno == EINTR)) {
+ /*
+ * Not ready?
+ */
+ continue;
+ }
+
+ /* Other errors: EIO, EINVAL, etc */
+ return -1;
+ }
+
+ total += n;
+ remain -= n;
+ }
+
+ return total;
+}
+
+/**
+ * Retry reads until we (a) time out or (b) get our data. Of course, if
+ * timeout is NULL, it'll wait forever.
+ *
+ * @param sockfd File descriptor we want to read from.
+ * @param buf Preallocated buffer into which we will read data.
+ * @param count Number of bytes to read.
+ * @param timeout (struct timeval) describing how long we should retry.
+ * @return The number of bytes read on success, or -1 on failure.
+ Note that we will always return (count) or (-1).
+ */
+ssize_t
+_read_retry(int sockfd, void *buf, int count, struct timeval * timeout)
+{
+ int n, total = 0, remain = count, rv = 0;
+ fd_set rfds, xfds;
+ char *tmp_buf = (char *)buf;
+
+ while (total < count) {
+ FD_ZERO(&rfds);
+ FD_SET(sockfd, &rfds);
+ FD_ZERO(&xfds);
+ FD_SET(sockfd, &xfds);
+
+ /*
+ * Select on the socket, in case it closes while we're not
+ * looking...
+ */
+ rv = _select_retry(sockfd + 1, &rfds, NULL, &xfds, timeout);
+ if (rv == -1)
+ return -1;
+ else if (rv == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ if (FD_ISSET(sockfd, &xfds)) {
+ errno = EPIPE;
+ return -1;
+ }
+
+ /*
+ * Attempt to read off the socket
+ */
+ n = read(sockfd, tmp_buf + total, remain);
+
+ /*
+ * When we know our socket was select()ed and we receive 0 bytes
+ * when we read, the socket was closed.
+ */
+ if ((n == 0) && (rv == 1)) {
+ errno = EPIPE;
+ return -1;
+ }
+
+ if (n == -1) {
+ if ((errno == EAGAIN) || (errno == EINTR)) {
+ /*
+ * Not ready? Wait for data to become available
+ */
+ continue;
+ }
+
+ /* Other errors: EPIPE, EINVAL, etc */
+ return -1;
+ }
+
+ total += n;
+ remain -= n;
+ }
+
+ return total;
+}
diff --git a/agents/virt/common/ip_lookup.c b/agents/virt/common/ip_lookup.c
new file mode 100644
index 0000000..aded8ea
--- /dev/null
+++ b/agents/virt/common/ip_lookup.c
@@ -0,0 +1,326 @@
+/*
+ Copyright Red Hat, Inc. 2004, 2006
+
+ The Magma Cluster API Library is free software; you can redistribute
+ it and/or modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either version
+ 2.1 of the License, or (at your option) any later version.
+
+ The Magma Cluster API Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+ */
+/** @file
+ * Build lists of IPs on the system, excepting loopback ipv6 link-local
+ */
+
+#include "config.h"
+
+#include <asm/types.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <netdb.h>
+
+/* Local includes */
+#include "ip_lookup.h"
+#include "debug.h"
+
+static int
+send_addr_dump(int fd, int family)
+{
+ struct nlmsghdr *nh;
+ struct rtgenmsg *g;
+ char buf[256];
+ struct sockaddr_nl addr;
+
+ memset(&addr,0,sizeof(addr));
+ addr.nl_family = PF_NETLINK;
+
+ memset(buf, 0, sizeof(buf));
+ nh = (struct nlmsghdr *)buf;
+ g = (struct rtgenmsg *)(buf + sizeof(struct nlmsghdr));
+
+ nh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
+ nh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
+ nh->nlmsg_type = RTM_GETADDR;
+ g->rtgen_family = family;
+
+ return sendto(fd, buf, nh->nlmsg_len, 0, (struct sockaddr *)&addr,
+ sizeof(addr));
+}
+
+
+static int
+add_ip(ip_list_t *ipl, char *ipaddr, char family)
+{
+ ip_addr_t *ipa;
+
+ if (family == PF_INET6) {
+ /* Avoid loopback */
+ if (!strcmp(ipaddr, "::1"))
+ return -1;
+
+ /* Avoid link-local addresses */
+ if (!strncmp(ipaddr, "fe80", 4))
+ return -1;
+ if (!strncmp(ipaddr, "fe90", 4))
+ return -1;
+ if (!strncmp(ipaddr, "fea0", 4))
+ return -1;
+ if (!strncmp(ipaddr, "feb0", 4))
+ return -1;
+ }
+
+ ipa = calloc(1, sizeof(*ipa));
+ if (!ipa)
+ return -1;
+ ipa->ipa_family = family;
+ ipa->ipa_address = strdup(ipaddr);
+
+ dbg_printf(4, "Adding IP %s to list (family %d)\n", ipaddr, family);
+ TAILQ_INSERT_TAIL(ipl, ipa, ipa_entries);
+
+ return 0;
+}
+
+
+static int
+add_ip_addresses(int family, ip_list_t *ipl)
+{
+ /* List ipv4 addresses */
+ struct nlmsghdr *nh;
+ struct ifaddrmsg *ifa;
+ struct rtattr *rta, *nrta;
+ struct nlmsgerr *err;
+ char buf[10240];
+ char outbuf[256];
+ char label[256];
+ int x, fd, len;
+
+ dbg_printf(5, "Connecting to Netlink...\n");
+ fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+ if (fd < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ dbg_printf(5, "Sending address dump request\n");
+ if (send_addr_dump(fd, family) < 0) {
+ perror("sendto");
+ close(fd);
+ return -1;
+ }
+ memset(buf, 0, sizeof(buf));
+
+ dbg_printf(5, "Waiting for response\n");
+ x = recvfrom(fd, buf, sizeof(buf), 0, NULL, 0);
+ if (x < 0) {
+ perror("recvfrom");
+ close(fd);
+ return -1;
+ }
+
+ dbg_printf(5, "Received %d bytes\n", x);
+
+ nh = (struct nlmsghdr *)buf;
+ while (NLMSG_OK(nh, x)) {
+
+ switch(nh->nlmsg_type) {
+ case NLMSG_DONE:
+ close(fd);
+ return 0;
+
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr*)NLMSG_DATA(nh);
+ if (nh->nlmsg_len <
+ NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
+ fprintf(stderr, "ERROR truncated");
+ } else {
+ errno = -err->error;
+ perror("RTNETLINK answers");
+ }
+ close(fd);
+ return -1;
+
+ case RTM_NEWADDR:
+ break;
+
+ default:
+ nh = NLMSG_NEXT(nh, x);
+ continue;
+ }
+
+ /* RTM_NEWADDR */
+ len = NLMSG_PAYLOAD(nh,0);
+ ifa = NLMSG_DATA(nh);
+
+ /* Make sure we got the type we expect back */
+ if (ifa->ifa_family != family) {
+ nh = NLMSG_NEXT(nh, x);
+ continue;
+ }
+
+ rta = IFA_RTA(ifa);
+ len -= sizeof(struct ifaddrmsg);
+ do {
+ /* Make sure we've got a valid rtaddr field */
+ if (!RTA_OK(rta, len)) {
+ dbg_printf(5, "!RTA_OK(rta, len)\n");
+ break;
+ }
+
+ if (rta->rta_type == IFA_ADDRESS) {
+ inet_ntop(family, RTA_DATA(rta), outbuf,
+ sizeof(outbuf) );
+ add_ip(ipl, outbuf, family);
+ }
+
+ if (rta->rta_type == IFA_LABEL) {
+ memset(label, 0, sizeof(label));
+ strncpy(label, (char *)RTA_DATA(rta), sizeof(label) - 1);
+ dbg_printf(5, "Skipping label: %s\n",
+ label);
+ }
+
+ nrta = RTA_NEXT(rta, len);
+ len -= (nrta - rta);
+ rta = nrta;
+ } while (RTA_OK(rta, len));
+
+ nh = NLMSG_NEXT(nh, x);
+ }
+
+ dbg_printf(5, "Closing Netlink connection\n");
+ close(fd);
+ return 0;
+}
+
+
+int
+ip_search(ip_list_t *ipl, char *ip_name)
+{
+ ip_addr_t *ipa;
+
+ dbg_printf(5, "Looking for IP address %s in IP list %p...", ip_name, ipl);
+ ipa = ipl->tqh_first;
+ for (ipa = ipl->tqh_first; ipa; ipa = ipa->ipa_entries.tqe_next) {
+ if (!strcmp(ip_name, ipa->ipa_address)) {
+ dbg_printf(4,"Found\n");
+ return 0;
+ }
+ }
+ dbg_printf(5, "Not found\n");
+ return 1;
+}
+
+
+int
+ip_free_list(ip_list_t *ipl)
+{
+ ip_addr_t *ipa;
+
+ dbg_printf(5, "Tearing down IP list @ %p\n", ipl);
+ while ((ipa = ipl->tqh_first)) {
+ TAILQ_REMOVE(ipl, ipa, ipa_entries);
+ free(ipa->ipa_address);
+ free(ipa);
+ }
+ return 0;
+}
+
+
+int
+ip_build_list(ip_list_t *ipl)
+{
+ dbg_printf(5, "Build IP address list\n");
+ TAILQ_INIT(ipl);
+ if (add_ip_addresses(PF_INET6, ipl) < 0) {
+ ip_free_list(ipl);
+ return -1;
+ }
+ if (add_ip_addresses(PF_INET, ipl) < 0) {
+ ip_free_list(ipl);
+ return -1;
+ }
+ return 0;
+}
+
+
+/**
+ Look up the interface name which corresponds to the given hostname and
+ return the list of matching attrinfo structures. We do this by looking
+ up all the possible physical and virtual network interfaces on the machine
+ and checking the hostname/IP mappings for each active IP address incurred.
+
+ @param nodename Interface name
+ @param ret_ai Structure pointer to allocate & return.
+ @return -1 on failure or 0 on success.
+ */
+int
+ip_lookup(char *nodename, struct addrinfo **ret_ai)
+{
+ char ip_name[256];
+ struct addrinfo *ai = NULL;
+ struct addrinfo *n;
+ void *p;
+ ip_list_t ipl;
+ int ret = -1;
+
+ dbg_printf(5, "Looking for IP matching %s\n", nodename);
+ /* Build list of IP addresses configured locally */
+ if (ip_build_list(&ipl) < 0)
+ return -1;
+
+ /* Get list of addresses for the host-name/ip */
+ if (getaddrinfo(nodename, NULL, NULL, &ai) != 0)
+ return -1;
+
+
+ /* Traverse list of addresses for given host-name/ip */
+ for (n = ai; n; n = n->ai_next) {
+ if (n->ai_family != PF_INET && n->ai_family != PF_INET6)
+ continue;
+
+ if (n->ai_family == PF_INET)
+ p = &(((struct sockaddr_in *)n->ai_addr)->sin_addr);
+ else
+ p = &(((struct sockaddr_in6 *)n->ai_addr)->sin6_addr);
+
+ if (!inet_ntop(n->ai_family, p, ip_name,
+ sizeof(ip_name)))
+ continue;
+
+ /* Search local interfaces for this IP address */
+ if (ip_search(&ipl, ip_name) != 0)
+ continue;
+
+ /* Found it */
+ ret = 0;
+ break;
+ }
+
+ /* Clean up */
+ if (!ret_ai)
+ freeaddrinfo(ai);
+ else
+ *ret_ai = ai;
+
+ ip_free_list(&ipl);
+
+ return ret;
+}
+
diff --git a/agents/virt/common/log.c b/agents/virt/common/log.c
new file mode 100644
index 0000000..61018ed
--- /dev/null
+++ b/agents/virt/common/log.c
@@ -0,0 +1,204 @@
+/**
+ * Syslog wrapper that does not block
+ *
+ * Lon Hohberger, 2009
+ */
+
+#include "config.h"
+
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/syslog.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include "list.h"
+
+struct log_entry {
+ list_head();
+ char *message;
+ int sev;
+ int bufsz;
+};
+
+#define MAX_QUEUE_LENGTH 10
+#define LOGLEN 256
+
+static struct log_entry *_log_entries = NULL;
+static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t log_cond = PTHREAD_COND_INITIALIZER;
+static int log_size = 0;
+static int dropped = 0;
+static pthread_t thread_id = 0;
+
+void __real_syslog(int severity, const char *fmt, ...);
+void __wrap_syslog(int severity, const char *fmt, ...);
+void __wrap_closelog(void);
+
+static void *
+_log_thread(void *arg)
+{
+ struct timeval tv;
+ struct timespec ts;
+ struct log_entry *entry;
+
+ do {
+ gettimeofday(&tv, NULL);
+ ts.tv_sec = tv.tv_sec + 10;
+ ts.tv_nsec = tv.tv_usec;
+
+ pthread_mutex_lock(&log_mutex);
+
+ while (!(entry = _log_entries)) {
+ if (pthread_cond_timedwait(&log_cond,
+ &log_mutex,
+ &ts) == ETIMEDOUT)
+ goto out;
+ }
+
+ list_remove(&_log_entries, entry);
+ --log_size;
+ if (log_size < 0)
+ raise(SIGSEGV);
+ pthread_mutex_unlock(&log_mutex);
+
+ __real_syslog(entry->sev, entry->message);
+ free(entry->message);
+ free(entry);
+ } while (1);
+
+out:
+ thread_id = (pthread_t)0;
+ pthread_mutex_unlock(&log_mutex);
+ return NULL;
+}
+
+
+static int
+insert_entry(int sev, char *buf, int bufsz)
+{
+ struct log_entry *lent;
+ pthread_attr_t attrs;
+
+ lent = malloc(sizeof(*lent));
+ if (!lent)
+ return -1;
+ lent->sev = sev;
+ lent->message = buf;
+ lent->bufsz = bufsz;
+
+ pthread_mutex_lock(&log_mutex);
+ if (log_size >= MAX_QUEUE_LENGTH) {
+ free(lent->message);
+ free(lent);
+
+ ++dropped;
+ lent = (struct log_entry *)(le(_log_entries)->le_prev);
+
+ lent->sev = LOG_WARNING;
+ snprintf(lent->message, lent->bufsz,
+ "%d message(s) lost due to syslog load\n",
+ dropped + 1);
+ /* Dropped +1 because we overwrote a message to
+ * give the 'dropped' message */
+ } else {
+ ++log_size;
+ dropped = 0;
+ list_insert(&_log_entries, lent);
+ }
+
+ if (!thread_id) {
+ pthread_attr_init(&attrs);
+ pthread_attr_setinheritsched(&attrs, PTHREAD_INHERIT_SCHED);
+
+ if (pthread_create(&thread_id, &attrs, _log_thread, NULL) < 0)
+ thread_id = 0;
+ pthread_mutex_unlock(&log_mutex);
+ } else {
+ pthread_mutex_unlock(&log_mutex);
+ pthread_cond_signal(&log_cond);
+ }
+
+ return 0;
+}
+
+
+__attribute__((__format__ (__printf__, 2, 0)))
+void
+__wrap_syslog(int severity, const char *fmt, ...)
+{
+ va_list args;
+ char *logmsg;
+
+ logmsg = malloc(LOGLEN);
+ if (!logmsg)
+ return;
+ memset(logmsg, 0, LOGLEN);
+
+ va_start(args, fmt);
+ vsnprintf(logmsg + strlen(logmsg), LOGLEN - strlen(logmsg),
+ fmt, args);
+ va_end(args);
+
+ insert_entry(severity, logmsg, LOGLEN);
+
+ return;
+}
+
+
+void __real_closelog(void);
+
+void
+__wrap_closelog(void)
+{
+ struct log_entry *lent;
+#ifdef DEBUG
+ int lost = 0;
+#endif
+
+ if (thread_id != 0) {
+ pthread_cancel(thread_id);
+ pthread_join(thread_id, NULL);
+ thread_id = 0;
+ }
+ __real_closelog();
+ while (_log_entries) {
+#ifdef DEBUG
+ ++lost;
+#endif
+ lent = _log_entries;
+ list_remove(&_log_entries, lent);
+ free(lent->message);
+ free(lent);
+ }
+
+#ifdef DEBUG
+ printf("%d lost\n", lost);
+#endif
+}
+
+
+#ifdef STANDALONE
+int
+main(int argc, char**argv)
+{
+ int x;
+
+ for (x = 0; x < 100; x++) {
+ syslog(1, "Yo %d\n", x);
+ }
+ sleep(1);
+
+ closelog();
+
+ return 0;
+}
+
+#endif
diff --git a/agents/virt/common/mcast.c b/agents/virt/common/mcast.c
new file mode 100644
index 0000000..cc79c64
--- /dev/null
+++ b/agents/virt/common/mcast.c
@@ -0,0 +1,388 @@
+/*
+ Copyright Red Hat, Inc. 2003, 2004, 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/*
+ * Author: Lon Hohberger <lhh at redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+
+/* Local includes */
+#include "mcast.h"
+#include "debug.h"
+
+/**
+ Sets up a multicast receive socket
+ */
+int
+ipv4_recv_sk(char *addr, int port, unsigned int ifindex)
+{
+ int sock;
+ struct ip_mreqn mreq;
+ struct sockaddr_in sin;
+
+ memset(&mreq, 0, sizeof(mreq));
+ memset(&sin, 0, sizeof(sin));
+
+ /* Store multicast address */
+ if (inet_pton(PF_INET, addr,
+ (void *)&mreq.imr_multiaddr.s_addr) < 0) {
+ printf("Invalid multicast address: %s\n", addr);
+ return -1;
+ }
+
+ /********************************
+ * SET UP MULTICAST RECV SOCKET *
+ ********************************/
+ dbg_printf(4, "Setting up ipv4 multicast receive (%s:%d)\n", addr, port);
+ sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ printf("socket: %s\n", strerror(errno));
+ sock = -1;
+ return 1;
+ }
+
+ /*
+ * When using Multicast, bind to the LOCAL address, not the MULTICAST
+ * address.
+ */
+ sin.sin_family = PF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (bind(sock, (struct sockaddr *) &sin,
+ sizeof(struct sockaddr_in)) < 0) {
+ printf("bind failed: %s\n", strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join multicast group
+ */
+ /* mreq.imr_multiaddr.s_addr is set above */
+ if (ifindex == 0) {
+ dbg_printf(4, "Setting mcast addr to INADDR_ANY due to ifindex of 0\n");
+ mreq.imr_address.s_addr = htonl(INADDR_ANY);
+ } else {
+ mreq.imr_ifindex = ifindex;
+ }
+ dbg_printf(4, "Joining multicast group\n");
+ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ &mreq, sizeof(mreq)) == -1) {
+ printf("Failed to bind multicast receive socket to "
+ "%s: %s\n", addr, strerror(errno));
+ printf("Check network configuration.\n");
+ close(sock);
+ return -1;
+ }
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
+
+
+/**
+ Set up multicast send socket
+ */
+int
+ipv4_send_sk(char *send_addr, char *addr, int port, struct sockaddr *tgt,
+ socklen_t tgt_len)
+{
+ int val;
+ struct ip_mreq mreq;
+ struct sockaddr_in mcast;
+ struct sockaddr_in src;
+ int sock;
+
+ if (tgt_len < sizeof(struct sockaddr_in)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(&mcast, 0, sizeof(mcast));
+ memset(&src, 0, sizeof(src));
+
+ /* Store multicast address */
+ mcast.sin_family = PF_INET;
+ mcast.sin_port = htons(port);
+ if (inet_pton(PF_INET, addr,
+ (void *)&mcast.sin_addr.s_addr) < 0) {
+ printf("Invalid multicast address: %s\n", addr);
+ return -1;
+ }
+ mreq.imr_multiaddr.s_addr = mcast.sin_addr.s_addr;
+
+ /* Store sending address */
+ src.sin_family = PF_INET;
+ src.sin_port = htons(port);
+ if (inet_pton(PF_INET, send_addr,
+ (void *)&src.sin_addr.s_addr) < 0) {
+ printf("Invalid source address: %s\n", send_addr);
+ return -1;
+ }
+ mreq.imr_interface.s_addr = src.sin_addr.s_addr;
+
+
+ /*************************
+ * SET UP MULTICAST SEND *
+ *************************/
+ dbg_printf(4, "Setting up ipv4 multicast send (%s:%d)\n", addr, port);
+ sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ /*
+ * Join Multicast group.
+ */
+ dbg_printf(4, "Joining IP Multicast group (pass 1)\n");
+ if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq)) == -1) {
+ printf("Failed to add multicast membership to transmit "
+ "socket %s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join Multicast group.
+ */
+ dbg_printf(4, "Joining IP Multicast group (pass 2)\n");
+ if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &src.sin_addr,
+ sizeof(src.sin_addr)) == -1) {
+ printf("Failed to bind multicast transmit socket to "
+ "%s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * set time to live to 2 hops.
+ */
+ dbg_printf(4, "Setting TTL to 2 for fd%d\n", sock);
+ val = 2;
+ if (setsockopt(sock, SOL_IP, IP_MULTICAST_TTL, &val,
+ sizeof(val)))
+ printf("warning: setting TTL failed %s\n", strerror(errno));
+
+ memcpy((struct sockaddr_in *)tgt, &mcast, sizeof(struct sockaddr_in));
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
+
+
+
+/**
+ Sets up a multicast receive (ipv6) socket
+ */
+int
+ipv6_recv_sk(char *addr, int port, unsigned int ifindex)
+{
+ int sock, val;
+ struct ipv6_mreq mreq;
+ struct sockaddr_in6 sin;
+
+ memset(&mreq, 0, sizeof(mreq));
+ memset(&sin, 0, sizeof(sin));
+ sin.sin6_family = PF_INET6;
+ sin.sin6_port = htons(port);
+ if (inet_pton(PF_INET6, addr,
+ (void *)&sin.sin6_addr) < 0) {
+ printf("Invalid multicast address: %s\n", addr);
+ return -1;
+ }
+
+ memcpy(&mreq.ipv6mr_multiaddr, &sin.sin6_addr,
+ sizeof(struct in6_addr));
+
+ mreq.ipv6mr_interface = ifindex;
+
+ /********************************
+ * SET UP MULTICAST RECV SOCKET *
+ ********************************/
+ dbg_printf(4, "Setting up ipv6 multicast receive (%s:%d)\n", addr, port);
+ sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0) {
+ printf("socket: %s\n", strerror(errno));
+ sock = -1;
+ return 1;
+ }
+
+ /*
+ * When using Multicast, bind to the LOCAL address, not the MULTICAST
+ * address.
+ */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin6_family = PF_INET6;
+ sin.sin6_port = htons(port);
+ sin.sin6_addr = in6addr_any;
+ if (bind(sock, (struct sockaddr *) &sin,
+ sizeof(struct sockaddr_in6)) < 0) {
+ printf("bind failed: %s\n", strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ dbg_printf(4, "Disabling IP Multicast loopback\n");
+ val = 1;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val,
+ sizeof(val)) != 0) {
+ printf("Failed to disable multicast loopback\n");
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join multicast group
+ */
+ dbg_printf(4, "Joining IP Multicast group\n");
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq)) == -1) {
+ printf("Failed to add multicast to socket %s: %s\n",
+ addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
+
+
+/**
+ Set up ipv6 multicast send socket
+ */
+int
+ipv6_send_sk(char *send_addr, char *addr, int port, struct sockaddr *tgt,
+ socklen_t tgt_len)
+{
+ int val;
+ struct ipv6_mreq mreq;
+ struct sockaddr_in6 mcast;
+ struct sockaddr_in6 src;
+ int sock;
+
+ if (tgt_len < sizeof(struct sockaddr_in6)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(&mcast, 0, sizeof(mcast));
+ memset(&src, 0, sizeof(src));
+ memset(&mreq, 0, sizeof(mreq));
+
+ /* Store multicast address */
+ mcast.sin6_family = PF_INET6;
+ mcast.sin6_port = htons(port);
+ if (inet_pton(PF_INET6, addr,
+ (void *)&mcast.sin6_addr) < 0) {
+ printf("Invalid multicast address: %s\n", addr);
+ return -1;
+ }
+
+ memcpy(&mreq.ipv6mr_multiaddr, &mcast.sin6_addr,
+ sizeof(struct in6_addr));
+
+ /* Store sending address */
+ src.sin6_family = PF_INET6;
+ src.sin6_port = htons(port);
+ if (inet_pton(PF_INET6, send_addr,
+ (void *)&src.sin6_addr) < 0) {
+ printf("Invalid source address: %s\n", send_addr);
+ return -1;
+ }
+
+ /*************************
+ * SET UP MULTICAST SEND *
+ *************************/
+ dbg_printf(4, "Setting up ipv6 multicast send (%s:%d)\n", addr, port);
+ sock = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ dbg_printf(4, "Disabling IP Multicast loopback\n");
+ val = 1;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &val,
+ sizeof(val)) != 0) {
+ printf("Failed to disable multicast loopback\n");
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join Multicast group.
+ */
+ dbg_printf(4, "Joining IP Multicast group\n");
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq)) == -1) {
+ printf("Failed to add multicast membership to transmit "
+ "socket %s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ /*
+ * Join Multicast group (part 2)
+ */
+ /*
+ if (setsockopt(sock, IPPROTO_IPV6, IP_MULTICAST_IF, &src.sin6_addr,
+ sizeof(src.sin6_addr)) == -1) {
+ printf("Failed to bind multicast transmit socket to "
+ "%s: %s\n", addr, strerror(errno));
+ close(sock);
+ return -1;
+ }
+ */
+
+ /*
+ * set time to live to 2 hops.
+ */
+ val = 2;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val,
+ sizeof(val)))
+ printf("warning: setting TTL failed %s\n", strerror(errno));
+
+ memcpy((struct sockaddr_in *)tgt, &mcast, sizeof(struct sockaddr_in6));
+
+ dbg_printf(4, "%s: success, fd = %d\n", __FUNCTION__, sock);
+ return sock;
+}
diff --git a/agents/virt/common/simple_auth.c b/agents/virt/common/simple_auth.c
new file mode 100644
index 0000000..9f694c4
--- /dev/null
+++ b/agents/virt/common/simple_auth.c
@@ -0,0 +1,466 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sechash.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "fdops.h"
+#include "simple_auth.h"
+#include "debug.h"
+
+
+static void
+print_hash(unsigned char *hash, size_t hashlen)
+{
+ int x;
+
+ for (x = 0; x < hashlen; x++)
+ printf("%02x", (hash[x]&0xff));
+}
+
+
+static int
+sha_sign(fence_req_t *req, void *key, size_t key_len)
+{
+ unsigned char hash[SHA512_LENGTH];
+ HASHContext *h;
+ HASH_HashType ht;
+ unsigned int rlen;
+ int devrand;
+ int ret;
+
+ switch(req->hashtype) {
+ case HASH_SHA1:
+ ht = HASH_AlgSHA1;
+ break;
+ case HASH_SHA256:
+ ht = HASH_AlgSHA256;
+ break;
+ case HASH_SHA512:
+ ht = HASH_AlgSHA512;
+ break;
+ default:
+ dbg_printf(1, "Unknown hash type: %d\n", req->hashtype);
+ return -1;
+ }
+
+ dbg_printf(4, "Opening /dev/urandom\n");
+ devrand = open("/dev/urandom", O_RDONLY);
+ if (devrand < 0) {
+ dbg_printf(1, "Error: open: /dev/urandom: %s", strerror(errno));
+ return -1;
+ }
+
+ ret = _read_retry(devrand, req->random, sizeof(req->random), NULL);
+ if (ret <= 0) {
+ dbg_printf(1, "Error: read: /dev/urandom: %s", strerror(errno));
+ close(devrand);
+ return -1;
+ }
+ close(devrand);
+
+ memset(hash, 0, sizeof(hash));
+ h = HASH_Create(ht);
+ if (!h)
+ return -1;
+
+ HASH_Begin(h);
+ HASH_Update(h, key, key_len);
+ HASH_Update(h, (void *)req, sizeof(*req));
+ HASH_End(h, hash, &rlen, sizeof(hash));
+ HASH_Destroy(h);
+
+ memcpy(req->hash, hash, sizeof(req->hash));
+ return 0;
+}
+
+
+static int
+sha_verify(fence_req_t *req, void *key, size_t key_len)
+{
+ unsigned char hash[SHA512_LENGTH];
+ unsigned char pkt_hash[SHA512_LENGTH];
+ HASHContext *h = NULL;
+ HASH_HashType ht;
+ unsigned int rlen;
+ int ret;
+
+ switch(req->hashtype) {
+ case HASH_SHA1:
+ ht = HASH_AlgSHA1;
+ break;
+ case HASH_SHA256:
+ ht = HASH_AlgSHA256;
+ break;
+ case HASH_SHA512:
+ ht = HASH_AlgSHA512;
+ break;
+ default:
+ dbg_printf(3, "%s: no-op (HASH_NONE)\n", __FUNCTION__);
+ return 0;
+ }
+
+ if (!key || !key_len) {
+ dbg_printf(3, "%s: Hashing requested when we have no key data\n",
+ __FUNCTION__);
+ return 0;
+ }
+
+ memset(hash, 0, sizeof(hash));
+ h = HASH_Create(ht);
+ if (!h)
+ return 0;
+
+ memcpy(pkt_hash, req->hash, sizeof(pkt_hash));
+ memset(req->hash, 0, sizeof(req->hash));
+
+ HASH_Begin(h);
+ HASH_Update(h, key, key_len);
+ HASH_Update(h, (void *)req, sizeof(*req));
+ HASH_End(h, hash, &rlen, sizeof(hash));
+ HASH_Destroy(h);
+
+ memcpy(req->hash, pkt_hash, sizeof(req->hash));
+
+ ret = !memcmp(hash, pkt_hash, sizeof(hash));
+ if (!ret) {
+ printf("Hash mismatch:\nPKT = ");
+ print_hash(pkt_hash, sizeof(pkt_hash));
+ printf("\nEXP = ");
+ print_hash(hash, sizeof(hash));
+ printf("\n");
+ }
+
+ return ret;
+}
+
+
+int
+sign_request(fence_req_t *req, void *key, size_t key_len)
+{
+ memset(req->hash, 0, sizeof(req->hash));
+ switch(req->hashtype) {
+ case HASH_NONE:
+ dbg_printf(3, "%s: no-op (HASH_NONE)\n", __FUNCTION__);
+ return 0;
+ case HASH_SHA1:
+ case HASH_SHA256:
+ case HASH_SHA512:
+ return sha_sign(req, key, key_len);
+ default:
+ break;
+ }
+ return -1;
+}
+
+
+int
+verify_request(fence_req_t *req, fence_hash_t min,
+ void *key, size_t key_len)
+{
+ if (req->hashtype < min) {
+ printf("Hash type not strong enough (%d < %d)\n",
+ req->hashtype, min);
+ return 0;
+ }
+ switch(req->hashtype) {
+ case HASH_NONE:
+ return 1;
+ case HASH_SHA1:
+ case HASH_SHA256:
+ case HASH_SHA512:
+ return sha_verify(req, key, key_len);
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static int
+sha_challenge(int fd, fence_auth_type_t auth, void *key,
+ size_t key_len, int timeout)
+{
+ fd_set rfds;
+ struct timeval tv;
+ unsigned char hash[MAX_HASH_LENGTH];
+ unsigned char challenge[MAX_HASH_LENGTH];
+ unsigned char response[MAX_HASH_LENGTH];
+ int devrand;
+ int ret;
+ HASHContext *h;
+ HASH_HashType ht;
+ unsigned int rlen;
+
+ devrand = open("/dev/urandom", O_RDONLY);
+ if (devrand < 0) {
+ dbg_printf(1, "Error: open /dev/urandom: %s", strerror(errno));
+ return 0;
+ }
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ ret = _read_retry(devrand, challenge, sizeof(challenge), &tv);
+ if (ret < 0) {
+ dbg_printf(1, "Error: read: /dev/urandom: %s", strerror(errno));
+ close(devrand);
+ return 0;
+ }
+ close(devrand);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ ret = _write_retry(fd, challenge, sizeof(challenge), &tv);
+ if (ret < 0) {
+ dbg_printf(2, "Error: write: %s", strerror(errno));
+ return 0;
+ }
+
+ switch(auth) {
+ case HASH_SHA1:
+ ht = HASH_AlgSHA1;
+ break;
+ case HASH_SHA256:
+ ht = HASH_AlgSHA256;
+ break;
+ case HASH_SHA512:
+ ht = HASH_AlgSHA512;
+ break;
+ default:
+ return 0;
+ }
+
+ memset(hash, 0, sizeof(hash));
+ h = HASH_Create(ht);
+ if (!h)
+ return 0;
+
+ HASH_Begin(h);
+ HASH_Update(h, key, key_len);
+ HASH_Update(h, challenge, sizeof(challenge));
+ HASH_End(h, hash, &rlen, sizeof(hash));
+ HASH_Destroy(h);
+
+ memset(response, 0, sizeof(response));
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0) {
+ dbg_printf(0, "Error: select: %s\n", strerror(errno));
+ return 0;
+ }
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ ret = _read_retry(fd, response, sizeof(response), &tv);
+ if (ret < 0) {
+ dbg_printf(0, "Error reading challenge response: %s", strerror(errno));
+ return 0;
+ } else if (ret < sizeof(response)) {
+ dbg_printf(0,
+ "read data from socket is too short(actual: %d, expected: %zu)\n",
+ ret, sizeof(response));
+ return 0;
+ }
+
+ ret = !memcmp(response, hash, sizeof(response));
+ if (!ret) {
+ printf("Hash mismatch:\nC = ");
+ print_hash(challenge, sizeof(challenge));
+ printf("\nH = ");
+ print_hash(hash, sizeof(hash));
+ printf("\nR = ");
+ print_hash(response, sizeof(response));
+ printf("\n");
+ }
+
+ return ret;
+}
+
+
+static int
+sha_response(int fd, fence_auth_type_t auth, void *key,
+ size_t key_len, int timeout)
+{
+ fd_set rfds;
+ struct timeval tv;
+ unsigned char challenge[MAX_HASH_LENGTH];
+ unsigned char hash[MAX_HASH_LENGTH];
+ HASHContext *h;
+ HASH_HashType ht;
+ unsigned int rlen;
+ int ret;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ if (_select_retry(fd + 1, &rfds, NULL, NULL, &tv) <= 0) {
+ dbg_printf(2, "Error: select: %s\n", strerror(errno));
+ return 0;
+ }
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ if (_read_retry(fd, challenge, sizeof(challenge), &tv) < 0) {
+ dbg_printf(2, "Error reading challenge hash: %s\n", strerror(errno));
+ return 0;
+ }
+
+ switch(auth) {
+ case AUTH_SHA1:
+ ht = HASH_AlgSHA1;
+ break;
+ case AUTH_SHA256:
+ ht = HASH_AlgSHA256;
+ break;
+ case AUTH_SHA512:
+ ht = HASH_AlgSHA512;
+ break;
+ default:
+ dbg_printf(3, "%s: no-op (AUTH_NONE)\n", __FUNCTION__);
+ return 0;
+ }
+
+ memset(hash, 0, sizeof(hash));
+ h = HASH_Create(ht); /* */
+ if (!h)
+ return 0;
+
+ HASH_Begin(h);
+ HASH_Update(h, key, key_len);
+ HASH_Update(h, challenge, sizeof(challenge));
+ HASH_End(h, hash, &rlen, sizeof(hash));
+ HASH_Destroy(h);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+ ret = _write_retry(fd, hash, sizeof(hash), &tv);
+ if (ret < 0) {
+ perror("write");
+ return 0;
+ } else if (ret < sizeof(hash)) {
+ dbg_printf(2,
+ "Only part of hash is written(actual: %d, expected: %zu)\n",
+ ret,
+ sizeof(hash));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int
+sock_challenge(int fd, fence_auth_type_t auth, void *key, size_t key_len,
+ int timeout)
+{
+ switch(auth) {
+ case AUTH_NONE:
+ dbg_printf(3, "%s: no-op (AUTH_NONE)\n", __FUNCTION__);
+ return 1;
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ return sha_challenge(fd, auth, key, key_len, timeout);
+ default:
+ break;
+ }
+ return -1;
+}
+
+
+int
+sock_response(int fd, fence_auth_type_t auth, void *key, size_t key_len,
+ int timeout)
+{
+ switch(auth) {
+ case AUTH_NONE:
+ dbg_printf(3, "%s: no-op (AUTH_NONE)\n", __FUNCTION__);
+ return 1;
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ return sha_response(fd, auth, key, key_len, timeout);
+ default:
+ break;
+ }
+ return -1;
+}
+
+
+int
+read_key_file(char *file, char *key, size_t max_len)
+{
+ int fd;
+ int nread, remain = max_len;
+ char *p;
+
+ dbg_printf(3, "Reading in key file %s into %p (%d max size)\n",
+ file, key, (int)max_len);
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ dbg_printf(2, "Error opening key file: %s\n", strerror(errno));
+ return -1;
+ }
+
+ memset(key, 0, max_len);
+ p = key;
+ remain = max_len;
+
+ while (remain) {
+ nread = read(fd, p, remain);
+ if (nread < 0) {
+ if (errno == EINTR)
+ continue;
+ dbg_printf(2, "Error from read: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ if (nread == 0) {
+ dbg_printf(3, "Stopped reading @ %d bytes\n",
+ (int)max_len-remain);
+ break;
+ }
+
+ p += nread;
+ remain -= nread;
+ }
+
+ close(fd);
+ dbg_printf(3, "Actual key length = %d bytes\n", (int)max_len-remain);
+
+ return (int)(max_len - remain);
+}
diff --git a/agents/virt/common/tcp.c b/agents/virt/common/tcp.c
new file mode 100644
index 0000000..5796770
--- /dev/null
+++ b/agents/virt/common/tcp.c
@@ -0,0 +1,386 @@
+/*
+ Copyright Red Hat, Inc. 2002-2004, 2006
+ Copyright Mission Critical Linux, 2000
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/** @file
+ *
+ * @author Lon H. Hohberger <lhh at redhat.com>
+ * @author Jeff Moyer <jmoyer at redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "tcp.h"
+#include "debug.h"
+
+static int connect_nb(int fd, struct sockaddr *dest, socklen_t len, int timeout);
+static int get_addr(const char *hostname, int family, struct sockaddr_storage *addr);
+
+/**
+ Set close-on-exec bit option for a socket.
+
+ @param fd Socket to set CLOEXEC flag
+ @return 0 on success, -1 on failure
+ @see fcntl
+ */
+static int
+set_cloexec(int fd)
+{
+ int flags = fcntl(fd, F_GETFD, 0);
+ flags |= FD_CLOEXEC;
+ return fcntl(fd, F_SETFD, flags);
+}
+
+
+/**
+ Bind to a port on the local IPv6 stack
+
+ @param addr_str Address to listen on, NULL for inaddr6_any
+ @param port Port to bind to
+ @param backlog same as backlog for listen(2)
+ @return 0 on success, -1 on failure
+ @see ipv4_bind
+ */
+int
+ipv6_listen(const char *addr_str, uint16_t port, int backlog)
+{
+ struct sockaddr_in6 _sin6;
+ int fd, opt=1;
+
+ dbg_printf(4, "%s: Setting up ipv6 listen socket for %s:%d\n",
+ __FUNCTION__, addr_str, port);
+
+ memset(&_sin6, 0, sizeof(_sin6));
+ _sin6.sin6_family = PF_INET6;
+ _sin6.sin6_port = htons(port);
+ _sin6.sin6_flowinfo = 0;
+
+ if (addr_str == NULL) {
+ _sin6.sin6_addr = in6addr_any;
+ } else {
+ struct sockaddr_storage ss;
+
+ if (get_addr(addr_str, AF_INET6, &ss) == -1) {
+ dbg_printf(4, "%s: Can't get addr for %s\n",
+ __FUNCTION__, addr_str);
+ return -1;
+ }
+
+ memcpy(&_sin6.sin6_addr,
+ &((struct sockaddr_in6 *)&ss)->sin6_addr, sizeof(_sin6.sin6_addr));
+ }
+
+ fd = socket(PF_INET6, SOCK_STREAM, 0);
+ if (fd < 0)
+ return -1;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof (opt)) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ if (set_cloexec(fd) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ if (bind(fd, (struct sockaddr *)&_sin6, sizeof(_sin6)) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ if (listen(fd, backlog) < 0){
+ close(fd);
+ return -1;
+ }
+
+ dbg_printf(4, "%s: Success; fd = %d\n", __FUNCTION__, fd);
+ return fd;
+}
+
+
+/**
+ Bind to a port on the local IPv4 stack
+
+ @param addr_str Address to listen on, NULL for inaddr_any
+ @param port Port to bind to
+ @param backlog same as backlog for listen(2)
+ @return 0 on success, -1 on failure
+ @see ipv6_bind
+ */
+int
+ipv4_listen(const char *addr_str, uint16_t port, int backlog)
+{
+ struct sockaddr_in _sin;
+ int fd, opt=1;
+
+ dbg_printf(4, "%s: Setting up ipv4 listen socket for %s:%d\n",
+ __FUNCTION__, addr_str, port);
+
+ _sin.sin_family = PF_INET;
+ _sin.sin_port = htons(port);
+
+ if (addr_str == NULL) {
+ _sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ struct sockaddr_storage ss;
+
+ if (get_addr(addr_str, AF_INET, &ss) == -1) {
+ dbg_printf(4, "%s: Can't get addr for %s\n",
+ __FUNCTION__, addr_str);
+ return -1;
+ }
+
+ memcpy(&_sin.sin_addr,
+ &((struct sockaddr_in *)&ss)->sin_addr, sizeof(_sin.sin_addr));
+ }
+
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0)
+ return -1;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof (opt)) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ if (set_cloexec(fd) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ if (bind(fd, (struct sockaddr *)&_sin, sizeof(_sin)) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ if (listen(fd, backlog) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ dbg_printf(4, "%s: Success; fd = %d\n", __FUNCTION__, fd);
+ return fd;
+}
+
+
+
+/**
+ Connect via ipv6 socket to a given IP address and port.
+
+ @param in6_addr IPv6 address to connect to
+ @param port Port to connect to
+ @param timeout Timeout, in seconds, to wait for a completed
+ connection
+ @return 0 on success, -1 on failure
+ @see connect_nb, ipv4_connect
+ */
+int
+ipv6_connect(struct in6_addr *in6_addr, uint16_t port, int timeout)
+{
+ struct sockaddr_in6 _sin6;
+ int fd, ret;
+
+ dbg_printf(4, "%s: Connecting to client\n", __FUNCTION__);
+ fd = socket(PF_INET6, SOCK_STREAM, 0);
+ if (fd < 0)
+ return -1;
+
+ memset(&_sin6, 0, sizeof(_sin6));
+ _sin6.sin6_family = PF_INET6;
+ _sin6.sin6_port = htons(port);
+ _sin6.sin6_flowinfo = 0;
+ memcpy(&_sin6.sin6_addr, in6_addr, sizeof(_sin6.sin6_addr));
+
+ ret = connect_nb(fd, (struct sockaddr *)&_sin6, sizeof(_sin6), timeout);
+ if (ret < 0) {
+ close(fd);
+ return -1;
+ }
+ dbg_printf(4, "%s: Success; fd = %d\n", __FUNCTION__, fd);
+ return fd;
+}
+
+
+/**
+ Connect via ipv4 socket to a given IP address and port.
+
+ @param in_addr IPv4 address to connect to
+ @param port Port to connect to
+ @param timeout Timeout, in seconds, to wait for a completed
+ connection
+ @return 0 on success, -1 on failure
+ @see connect_nb, ipv6_connect
+ */
+int
+ipv4_connect(struct in_addr *in_addr, uint16_t port, int timeout)
+{
+ struct sockaddr_in _sin;
+ int fd, ret;
+
+ dbg_printf(4, "%s: Connecting to client\n", __FUNCTION__);
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0)
+ return -1;
+
+ _sin.sin_family = PF_INET;
+ _sin.sin_port = htons(port);
+ memcpy(&_sin.sin_addr, in_addr, sizeof(_sin.sin_addr));
+
+ ret = connect_nb(fd, (struct sockaddr *)&_sin, sizeof(_sin), timeout);
+ if (ret < 0) {
+ close(fd);
+ return -1;
+ }
+
+ dbg_printf(4, "%s: Success; fd = %d\n", __FUNCTION__, fd);
+ return fd;
+}
+
+
+/**
+ Connect in a non-blocking fashion to the designated address.
+
+ @param fd File descriptor to connect
+ @param dest sockaddr (ipv4 or ipv6) to connect to.
+ @param len Length of dest
+ @param timeout Timeout, in seconds, to wait for a completed
+ connection.
+ @return 0 on success, -1 on failure.
+ */
+static int
+connect_nb(int fd, struct sockaddr *dest, socklen_t len, int timeout)
+{
+ int ret, flags = 1, err;
+ unsigned l;
+ fd_set rfds, wfds;
+ struct timeval tv;
+
+ /*
+ * Use TCP Keepalive
+ */
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags,
+ sizeof(flags))<0) {
+ return -1;
+ }
+
+ /*
+ Set up non-blocking connect
+ */
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0) {
+ return -1;
+ }
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ return -1;
+ }
+
+ ret = connect(fd, dest, len);
+
+ if ((ret < 0) && (errno != EINPROGRESS))
+ return -1;
+
+ if (ret != 0) {
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ if (select(fd + 1, &rfds, &wfds, NULL, &tv) == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ /* XXX check for -1 from select */
+
+ if (FD_ISSET(fd, &rfds) || FD_ISSET(fd, &wfds)) {
+ l = sizeof(err);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR,
+ (void *)&err, &l) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ if (err != 0) {
+ close(fd);
+ errno = err;
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, flags) < 0) {
+ close(fd);
+ return -1;
+ }
+ return 0;
+ }
+ }
+
+ errno = EIO;
+ return -1;
+}
+
+static int
+get_addr(const char *hostname, int family, struct sockaddr_storage *addr)
+{
+ struct addrinfo *res;
+ size_t len;
+ struct addrinfo ai;
+
+ memset(&ai, 0, sizeof(ai));
+ ai.ai_family = family;
+
+ if (getaddrinfo(hostname, NULL, &ai, &res) != 0)
+ return -1;
+
+ switch (res->ai_addr->sa_family) {
+ case AF_INET:
+ len = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ len = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ goto out_fail;
+ }
+
+ if (len < (size_t) res->ai_addrlen)
+ goto out_fail;
+
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+
+ return 0;
+
+out_fail:
+ freeaddrinfo(res);
+ return -1;
+}
diff --git a/agents/virt/config/Makefile.am b/agents/virt/config/Makefile.am
new file mode 100644
index 0000000..19d9742
--- /dev/null
+++ b/agents/virt/config/Makefile.am
@@ -0,0 +1,44 @@
+###############################################################################
+###############################################################################
+##
+## Copyright (C) 2009-2019 Red Hat, Inc.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2.
+##
+###############################################################################
+###############################################################################
+
+MAINTAINERCLEANFILES = Makefile.in
+
+EXTRA_DIST = config.l config.y fence_virt.conf
+
+noinst_LIBRARIES = libsimpleconfig.a
+
+libsimpleconfig_a_SOURCES = \
+ simpleconfig.c
+
+nodist_libsimpleconfig_a_SOURCES = \
+ y.tab.c \
+ config.c
+
+libsimpleconfig_a_CFLAGS = $(VIRT_AM_CFLAGS) $(AM_CFLAGS) -Wno-unused
+
+noinst_HEADERS = config-stack.h
+
+
+sysconf_DATA = fence_virt.conf
+
+# local rules
+y.tab.c: config.y
+ $(YACC) -d $^
+
+config.c: y.tab.c config.l
+ $(LEX) -oconfig.c $(srcdir)/config.l
+
+install-exec-hook:
+ chmod 600 $(DESTDIR)$(sysconfdir)/fence_virt.conf
+
+clean-local:
+ rm -f config.tab.c config.tab.h config.c y.tab.c y.tab.h
diff --git a/agents/virt/config/config-stack.h b/agents/virt/config/config-stack.h
new file mode 100644
index 0000000..1eb3cfa
--- /dev/null
+++ b/agents/virt/config/config-stack.h
@@ -0,0 +1,38 @@
+#ifndef _CONFIG_STACK_H
+#define _CONFIG_STACK_H
+
+int yyparse (void);
+extern FILE *yyin;
+
+struct value {
+ char *id;
+ char *val;
+ struct value *next;
+};
+
+
+struct node {
+ char *id;
+ char *val;
+ struct node *nodes;
+ struct value *values;
+ struct node *next;
+};
+
+
+struct parser_context {
+ struct value *val_list;
+ struct node *node_list;
+ struct parser_context *next;
+};
+
+extern struct value *val_list;
+extern struct node *node_list;
+extern struct parser_context *context_stack;
+
+int _sc_value_add(char *id, char *val, struct value **list);
+int _sc_node_add(char *id, char *val, struct value *vallist,
+ struct node *nodelist, struct node **list);
+
+
+#endif
diff --git a/agents/virt/config/config.l b/agents/virt/config/config.l
new file mode 100644
index 0000000..78462f3
--- /dev/null
+++ b/agents/virt/config/config.l
@@ -0,0 +1,106 @@
+%{
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include "config-stack.h"
+#include "y.tab.h"
+#include "simpleconfig.h"
+
+/* Some distributions can't use the output from flex without help */
+#define ECHO if(fwrite( yytext, yyleng, 1, yyout ))
+
+struct value *val_list = NULL;
+struct node *node_list = NULL;
+struct parser_context *context_stack = NULL;
+
+int _line_count = 1;
+
+%}
+%%
+[\n] {
+ ++_line_count;
+}
+
+[ \t]* {}
+
+\#[^\n]* {}
+
+"{" {
+ struct parser_context *c = NULL;
+ //printf("obrace\n");
+
+ c = malloc(sizeof(*c));
+ assert(c);
+
+ c->next = context_stack;
+ c->val_list = val_list;
+ c->node_list = node_list;
+
+ context_stack = c;
+ val_list = NULL;
+ node_list = NULL;
+
+ return T_OBRACE;
+}
+
+"}" {
+ return T_CBRACE;
+}
+
+";" {
+ return T_SEMI;
+}
+
+"=" {
+ return T_EQ;
+}
+
+[^ \t{};=\"\n]+ {
+ yylval.sval = strdup(yytext);
+ return T_ID;
+}
+
+\"[^\"]+\" {
+ yylval.sval = strdup(yytext+1);
+ yylval.sval[strlen(yytext)-2] = 0;
+ return T_VAL;
+}
+
+%%
+int
+yywrap(void)
+{
+ return 1;
+}
+
+
+#ifdef STANDALONE
+int
+main(int argc, char *argv[])
+{
+ char value[80];
+ config_object_t *c = NULL;
+
+ yyout = fopen("/dev/null","w");
+
+ c = sc_init();
+ sc_parse(c, NULL);
+ sc_dump(c, stdout);
+ if (argc == 2) {
+ if (sc_get(c, argv[1], value, sizeof(value)) == 0)
+ printf("%s = %s\n", argv[1], value);
+ else
+ printf("Not found\n");
+ } else if (argc == 3) {
+ printf("---------\n");
+ if (sc_set(c, argv[1], argv[2]) == 0)
+ sc_dump(c, stdout);
+ }
+
+ sc_release(c);
+
+ return 0;
+}
+#endif
diff --git a/agents/virt/config/config.y b/agents/virt/config/config.y
new file mode 100644
index 0000000..2ae0380
--- /dev/null
+++ b/agents/virt/config/config.y
@@ -0,0 +1,140 @@
+%{
+#include "config.h"
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+#include <assert.h>
+#include "config-stack.h"
+
+extern int yylex (void);
+int yyerror(const char *foo);
+
+int
+_sc_value_add(char *id, char *val, struct value **list)
+{
+ struct value *v;
+
+ v = malloc(sizeof(*v));
+ assert(v);
+
+ memset(v, 0, sizeof(*v));
+ v->id = id;
+ v->val = val;
+ //snprintf(v->id, sizeof(v->id), "%s", id);
+ //snprintf(v->val, sizeof(v->val), "%s", val);
+ //printf("add %s %s on to %p\n", id, val, *list);
+
+ v->next = *list;
+ *list = v;
+
+ //printf("new list %p\n", *list);
+ return 0;
+}
+
+
+int
+_sc_node_add(char *id, char *val, struct value *vallist,
+ struct node *nodelist, struct node **list)
+{
+ struct node *n;
+
+ n = malloc(sizeof(*n));
+ assert(n);
+
+ //printf("nodes %p values %p\n", nodelist, vallist);
+
+ memset(n, 0, sizeof(*n));
+ //snprintf(n->id, sizeof(n->id), "%s", id);
+ n->id = id; /* malloc'd during parsing */
+ n->val = val; /* malloc'd during parsing */
+ n->values = vallist;
+ n->nodes = nodelist;
+ n->next = *list;
+ *list = n;
+
+ return 0;
+}
+
+%}
+
+%token <sval> T_ID
+%token <sval> T_VAL
+%token T_OBRACE T_CBRACE T_EQ T_SEMI
+
+%start stuff
+
+%union {
+ char *sval;
+ int ival;
+}
+
+%%
+node:
+ T_ID T_OBRACE stuff T_CBRACE {
+ struct parser_context *c = NULL;
+
+ c = context_stack;
+ _sc_node_add($1, NULL, val_list, node_list, &c->node_list);
+ val_list = c->val_list;
+ node_list = c->node_list;
+ context_stack = c->next;
+
+ free(c);
+ }
+ |
+ T_ID T_EQ T_VAL T_OBRACE stuff T_CBRACE {
+ struct parser_context *c = NULL;
+
+ c = context_stack;
+ _sc_node_add($1, $3, val_list, node_list, &c->node_list);
+ val_list = c->val_list;
+ node_list = c->node_list;
+ context_stack = c->next;
+
+ free(c);
+ }
+ |
+ T_ID T_OBRACE T_CBRACE {
+ struct parser_context *c = NULL;
+
+ c = context_stack;
+ _sc_node_add($1, NULL, val_list, node_list, &c->node_list);
+ val_list = c->val_list;
+ node_list = c->node_list;
+ context_stack = c->next;
+
+ free(c);
+ }
+ |
+ T_ID T_EQ T_VAL T_OBRACE T_CBRACE {
+ struct parser_context *c = NULL;
+
+ c = context_stack;
+ _sc_node_add($1, $3, val_list, node_list, &c->node_list);
+ val_list = c->val_list;
+ node_list = c->node_list;
+ context_stack = c->next;
+
+ free(c);
+ }
+ ;
+
+stuff:
+ node stuff | assign stuff | node | assign
+ ;
+
+assign:
+ T_ID T_EQ T_VAL T_SEMI {
+ _sc_value_add($1, $3, &val_list);
+ }
+ ;
+%%
+
+extern int _line_count;
+
+int
+yyerror(const char *foo)
+{
+ printf("%s on line %d\n", foo, _line_count);
+ return 0;
+}
diff --git a/agents/virt/config/fence_virt.conf b/agents/virt/config/fence_virt.conf
new file mode 100644
index 0000000..03e2c58
--- /dev/null
+++ b/agents/virt/config/fence_virt.conf
@@ -0,0 +1,20 @@
+fence_virtd {
+ listener = "multicast";
+ backend = "libvirt";
+}
+
+listeners {
+ multicast {
+ key_file = "/etc/cluster/fence_xvm.key";
+ address = "225.0.0.12";
+ # Needed on Fedora systems
+ interface = "virbr0";
+ }
+}
+
+backends {
+ libvirt {
+ uri = "qemu:///system";
+ }
+}
+
diff --git a/agents/virt/config/simpleconfig.c b/agents/virt/config/simpleconfig.c
new file mode 100644
index 0000000..3315b32
--- /dev/null
+++ b/agents/virt/config/simpleconfig.c
@@ -0,0 +1,494 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <pthread.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "simpleconfig.h"
+#include "config-stack.h"
+#include "static_map.h"
+
+
+static pthread_mutex_t parser_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int
+print_value(struct value *v, int depth, FILE *fp)
+{
+ int x;
+
+ if (v->val == NULL)
+ return 0;
+
+ for (x = 0; x < depth; x++)
+ fprintf(fp, "\t");
+ fprintf(fp, "%s = \"%s\";\n", v->id, v->val);
+
+ return 0;
+}
+
+
+static void
+_sc_dump_d(struct node *node, int depth, FILE *fp)
+{
+ struct node *n;
+ struct value *v;
+ int x;
+
+ if (!node) {
+ //printf("Empty node\n");
+ return;
+ }
+
+ for (x = 0; x < depth; x++)
+ fprintf(fp, "\t");
+
+ if (node->val) {
+ fprintf(fp, "%s = \"%s\" {\n", node->id, node->val);
+ } else {
+ fprintf(fp, "%s {\n", node->id);
+ }
+
+ for (n = node->nodes; n; n = n->next) {
+ _sc_dump_d(n, depth+1, fp);
+ }
+
+ for (v = node->values; v; v = v->next) {
+ print_value(v, depth+1, fp);
+ }
+
+ for (x = 0; x < depth; x++)
+ fprintf(fp, "\t");
+ fprintf(fp, "}\n\n");
+}
+
+
+static void
+_sc_dump(void *config, FILE *fp)
+{
+ struct node *n, *node;
+ struct value *v, *values;
+
+ if (!config)
+ return;
+
+ values = ((struct parser_context *)config)->val_list;
+ node = ((struct parser_context *)config)->node_list;
+
+ for (n = node; n; n = n->next) {
+ _sc_dump_d(n, 0, fp);
+ }
+
+ for (v = values; v; v = v->next) {
+ print_value(v, 0, fp);
+ }
+}
+
+
+static int
+free_value(struct value *v)
+{
+ if (v) {
+ free(v->id);
+ free(v->val);
+ free(v);
+ }
+
+ return 0;
+}
+
+
+static void
+_sc_free_node(struct node *node)
+{
+ struct node *n;
+ struct value *v;
+
+ if (!node)
+ return;
+
+ while (node->nodes) {
+ n = node->nodes;
+ if (n) {
+ node->nodes = node->nodes->next;
+ _sc_free_node(n);
+ }
+ }
+
+ while (node->values) {
+ v = node->values;
+ node->values = node->values->next;
+ free_value(v);
+ }
+
+ free(node->id);
+ free(node);
+}
+
+
+static int
+_sc_free(void *config)
+{
+ struct node *n, *nlist;
+ struct value *v, *vlist;
+
+ if (!config)
+ return -1;
+
+ vlist = ((struct parser_context *)config)->val_list;
+ nlist = ((struct parser_context *)config)->node_list;
+
+ while (nlist) {
+ n = nlist;
+ nlist = nlist->next;
+ _sc_free_node(n);
+ }
+
+ ((struct parser_context *)config)->node_list = NULL;
+
+ while (vlist) {
+ v = vlist;
+ vlist = vlist->next;
+ free_value(v);
+ }
+
+ ((struct parser_context *)config)->val_list = NULL;
+
+ free(config);
+
+ return 0;
+}
+
+
+static int
+_sc_get(void *config, const char *key, char *value, size_t valuesz)
+{
+ char buf[1024];
+ struct node *n, *node;
+ struct value *v, *values;
+ char *ptr;
+ char *slash;
+ char *bracket;
+ char *id;
+ int req_index = 0;
+ int curr_index = 0;
+ int found;
+
+ if (!config)
+ return -1;
+
+ node = ((struct parser_context *)config)->node_list;
+ values = ((struct parser_context *)config)->val_list;
+
+ assert(strlen(key) < sizeof(buf));
+
+ ptr = (char *)key;
+
+ while ((slash = strchr(ptr, '/'))) {
+ memset(buf, 0, sizeof(buf));
+ strncpy(buf, ptr, (slash - ptr));
+ ptr = ++slash;
+
+ id = NULL;
+ bracket = strchr(buf, '[');
+ if (bracket) {
+ *bracket = 0;
+ ++bracket;
+
+ id = bracket;
+
+ bracket = strchr(bracket, ']');
+ if (!bracket)
+ return 1;
+ *bracket = 0;
+
+ if (id[0] == '@') {
+ ++id;
+ if (!strlen(id)) {
+ return 1;
+ }
+ } else {
+ req_index = atoi(id);
+ if (req_index <= 0)
+ return 1;
+ id = NULL;
+ }
+ }
+
+ found = 0;
+ curr_index = 0;
+
+ for (n = node; n; n = n->next) {
+
+ if (strcasecmp(n->id, buf))
+ continue;
+
+ ++curr_index;
+
+ if (req_index && (curr_index != req_index)) {
+ continue;
+ } else if (id && strcasecmp(n->val, id)) {
+ continue;
+ }
+
+ node = n->nodes;
+ values = n->values;
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ return 1;
+ }
+
+ if (ptr[0] != '@') {
+
+ strncpy(buf, ptr, sizeof(buf) - 1);
+ id = NULL;
+ bracket = strchr(buf, '[');
+ if (bracket) {
+ *bracket = 0;
+ ++bracket;
+
+ id = bracket;
+
+ bracket = strchr(bracket, ']');
+ if (!bracket)
+ return 1;
+ *bracket = 0;
+
+ if (id[0] == '@') {
+ ++id;
+ if (!strlen(id)) {
+ return 1;
+ }
+ } else {
+ req_index = atoi(id);
+ if (req_index <= 0)
+ return 1;
+ id = NULL;
+ }
+ }
+
+ found = 0;
+ curr_index = 0;
+
+ for (n = node; n; n = n->next) {
+
+ if (strcasecmp(n->id, buf))
+ continue;
+
+ ++curr_index;
+
+ if (req_index && (curr_index != req_index)) {
+ continue;
+ } else if (id && strcasecmp(n->val, id)) {
+ continue;
+ }
+ if (node->val) {
+ strncpy(value, node->val, valuesz);
+ return 0;
+ }
+ return 1;
+ }
+ }
+
+ ++ptr;
+ found = 0;
+ id = NULL;
+
+ strncpy(buf, ptr, sizeof(buf) - 1);
+ bracket = strchr(buf, '[');
+
+ req_index = 0;
+ curr_index = 0;
+
+ if (bracket) {
+ *bracket = 0;
+ ++bracket;
+
+ id = bracket;
+
+ bracket = strchr(bracket, ']');
+ if (!bracket)
+ return 1;
+ *bracket = 0;
+
+ req_index = atoi(id);
+ if (req_index <= 0)
+ return 1;
+ id = NULL;
+ }
+
+ for (v = values; v; v = v->next) {
+
+ if (strcasecmp(v->id, buf))
+ continue;
+
+ ++curr_index;
+ if (req_index && (curr_index != req_index))
+ continue;
+ snprintf(value, valuesz, "%s", v->val);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int
+_sc_set(void *config, const char *key, const char *value)
+{
+ char buf[1024];
+ struct node *n, **nodes = &((struct parser_context *)config)->node_list;
+ struct value *v, **values = &((struct parser_context *)config)->val_list;
+ char *ptr;
+ char *slash;
+ char *id_dup, *val_dup;
+ int found = 0;
+
+ ptr = (char *)key;
+ while ((slash = strchr(ptr, '/'))) {
+ memset(buf, 0, sizeof(buf));
+ strncpy(buf, ptr, (slash - ptr));
+ ptr = ++slash;
+ found = 0;
+
+ for (n = *nodes; n; n = n->next) {
+ if (strcasecmp(n->id, buf))
+ continue;
+
+ nodes = &n->nodes;
+ values = &n->values;
+ found = 1;
+ break;
+ }
+
+ if (!found) {
+ id_dup = strdup(buf);
+ if (!id_dup)
+ return -1;
+ _sc_node_add(id_dup, NULL, NULL, NULL, nodes);
+ n = *nodes;
+ nodes = &n->nodes;
+ values = &n->values;
+ }
+ }
+
+ if (ptr[0] != '@')
+ return 1;
+ ++ptr;
+
+ for (v = *values; v; v = v->next) {
+ if (strcasecmp(v->id, ptr))
+ continue;
+
+ ptr = v->val;
+ if (value) {
+ v->val = strdup(value);
+ if (!v->val) {
+ v->val = ptr;
+ return -1;
+ }
+ } else {
+ v->val = NULL;
+ }
+ free(ptr);
+
+ return 0;
+ }
+
+ if (!value)
+ return 0;
+
+ id_dup = strdup(ptr);
+ if (!id_dup)
+ return -1;
+
+ val_dup = strdup(value);
+ if (!val_dup) {
+ free(id_dup);
+ return -1;
+ }
+ _sc_value_add(id_dup, val_dup, values);
+
+ return 0;
+}
+
+
+static int
+_sc_parse(const char *filename, void **config)
+{
+ struct parser_context *c;
+ FILE *fp = NULL;
+ int ret = 0;
+
+ if (!config)
+ return -1;
+
+ pthread_mutex_lock(&parser_mutex);
+ if (filename) {
+ fp = fopen(filename, "r");
+ yyin = fp;
+ if (fp)
+ ret = yyparse();
+ else
+ ret = 1;
+ } else {
+ ret = 1;
+ }
+
+ c = malloc(sizeof(*c));
+ if (!c) {
+ ret = -1;
+ goto out_unlock;
+ }
+ c->node_list = node_list;
+ c->val_list = val_list;
+ c->next = NULL;
+ val_list = NULL;
+ node_list = NULL;
+ *config = (void *)c;
+
+ if (fp)
+ fclose(fp);
+
+out_unlock:
+ pthread_mutex_unlock(&parser_mutex);
+ return ret;
+}
+
+
+static const config_object_t sc_object = {
+ .get = _sc_get,
+ .set = _sc_set,
+ .parse = _sc_parse,
+ .free = _sc_free,
+ .dump = _sc_dump,
+ .info = NULL
+};
+
+
+config_object_t *
+sc_init(void)
+{
+ config_object_t *o;
+
+ o = malloc(sizeof(*o));
+ if (!o)
+ return NULL;
+ memset(o, 0, sizeof(*o));
+ memcpy(o, &sc_object, sizeof(*o));
+
+ return o;
+}
+
+
+void
+sc_release(config_object_t *c)
+{
+ sc_free(c);
+ free(c);
+}
diff --git a/agents/virt/docs/README b/agents/virt/docs/README
new file mode 100644
index 0000000..e2b19bc
--- /dev/null
+++ b/agents/virt/docs/README
@@ -0,0 +1,125 @@
+TODO: update
+
+I. Fence_xvm - Virtual machine fencing agent
+
+Fence_xvm is an agent which establishes a communications link between
+a cluster of virtual machines (VC) and a cluster of domain0/physical
+nodes which are hosting the virtual cluster. Its operations are
+fairly simple.
+
+ (a) Start a listener service.
+ (b) Send a multicast packet requesting that a VM be fenced.
+ (c) Authenticate client.
+ (e) Read response.
+ (f) Exit with success/failure, depending on the response received.
+
+If any of the above steps fail, the fencing agent exits with a failure
+code and fencing is retried by the virtual cluster at a later time.
+Because of the simplicty of fence_xvm, it is not necessary that
+fence_xvm be run from within a virtualized guest - all it needs is
+libnspr and libnss and a shared private key (for authentication; we
+would hate to receive a false positive response from a node not in the
+cluster!).
+
+
+II. Fence_virtd - Virtual machine fencing host
+
+Fence_virtd is a daemon which runs on physical hosts (e.g. in domain0)
+of the cluster hosting the virtual cluster. It listens on a port
+for multicast traffic from virtual cluster(s), and takes actions.
+Multiple disjoint virtual clusters can coexist on a single physical
+host cluster, but this requires multiple instances of fence_virtd.
+
+NOTE: fence_virtd *MUST* be run on ALL nodes in a given cluster which
+will be hosting virtual machines if fence_xvm is to be used for
+fencing!
+
+There are a couple of ways the multicast packet is handled,
+depending on the state of the host OS. It might be hosting the VM,
+or it might not. Furthermore, the VM might "reside" on a host which
+has failed.
+
+In order to be able to guarantee safe fencing of a VM even if the
+last- known host is down, we must store the last-known locations of
+each virtual machine in some sort of cluster-wide way. For this, we
+use the corosync CPG API. Every few seconds, fence_virtd queries the
+hypervisor via libvirt and stores any local VM states and sends those
+states over CPG to all other members. In the event of a physical node
+failure (which consequently causes the failure of one or more guests),
+we can then read the stored VM state corresponding to the guest we need
+to fence to find out the previous owner. With that information, we can
+infer if the known host node has been fenced. If so, then the VM is clean
+as well. The physical cluster must, therefore, have fencing in order for
+fence_virtd to work.
+
+Operation of a node hosting a VM which needs to be fenced:
+
+ (a) Receive multicast packet
+ (b) Authenticate multicast packet
+ (c) Open connection to host contained within multicast
+ packet.
+ (d) Authenticate server.
+ (e) Carry out fencing operation (e.g. call libvirt to destroy or
+ reboot the VM; there is no "on" method at this point).
+ (f) If operation succeeds, send success response.
+
+Operation of high-node-ID:
+
+ (a) Receive multicast packet
+ (b) Authenticate multicast packet
+ (c) Read VM state from stored CPG messages
+ (d) Check liveliness of nodeID hosting VM (if alive, do nothing)
+ (e) Open connection to host contained within multicast
+ packet.
+ (f) Check with CMAN to see if last-known host has been fenced.
+ (g) If last-known host has been fenced, send success response.
+ (h) Authenticate server & send response.
+
+NOTE: There is always a possibility that a VM is started again
+before the fencing operation and CPG update for that VM
+occurs. If the VM has booted and rejoined the cluster, fencing will
+not be necessary. If it is in the process of booting, but has not
+yet joined the cluster, fencing will also not be necessary - because
+it will not be using cluster resources yet.
+
+
+III. Security considerations
+
+While fencing is generally expected to run on a more or less trusted
+network, there are cases where it may not be.
+
+* The multicast packet is subject to replay attacks, but because no
+fencing action is taken based solely on the information contained
+within the packet, this should not allow an attacker to maliciously
+fence a VM from outside the cluster, though it may be possible to
+cause a DoS of fence_virtd if enough multicast packets are sent.
+
+* The only currently supported authentication mechanisms are simple
+challenge-response based on a shared private key and pseudorandom
+number generation.
+
+* An attacker with access to the shared key(s) can easily fence any
+known VM, even if they are not on a cluster node.
+
+* Different shared keys should be used for different virtual
+clusters on the same subnet (whether in the same physical cluster
+or not). Additionally, multiple fence_virtd instances must be run
+(each listening on a different multicast IP + port combination).
+
+IV. Configuration
+
+Generate a random key file. An example of how to generate it is:
+
+ dd if=/dev/urandom of=/etc/cluster/fence_xvm.key bs=4096 count=1
+
+Distribute the generated key file to all domUs in a cluster as well
+as all dom0s which will be hosting that particular cluster of domUs.
+The key should not be placed on shared file systems (because shared
+file systems require the cluster, which requires fencing...).
+
+Start fence_virtd on all hosts
+
+Configure fence_xvm on the domU cluster...
+
+rest...tbd
+
diff --git a/agents/virt/docs/TODO b/agents/virt/docs/TODO
new file mode 100644
index 0000000..17456cf
--- /dev/null
+++ b/agents/virt/docs/TODO
@@ -0,0 +1,7 @@
+High Priority / Blockers for v1.0;
+
+* endian-clean / 64-bit clean data structure analysis
+
+Future Stuff:
+
+* clean up development bits so third parties can develop plugins
diff --git a/agents/virt/docs/architecture.txt b/agents/virt/docs/architecture.txt
new file mode 100644
index 0000000..54fda11
--- /dev/null
+++ b/agents/virt/docs/architecture.txt
@@ -0,0 +1,16 @@
+The actual architecture of fence_virtd is very simple. We have a set
+of listener plugins which listens for fencing requests for virtual
+machines.
+
+These plugins are assigned callbacks which are entry functions in to
+the backend plugins. The backend plugins perform the actual fencing
+request.
+
+In the middle, we have only enough code to provide basic integration
+functions between the listener and backend plugins. This includes a
+very simple confiugration plugin which we pass to each of the plugins.
+
+Because we are passing function pointers in to the plugins themselves
+for configuration (rather than having the plugins call an API directly,
+for example), we are able to swap out the configuration subsystem for
+other, more full-featured configuration systems, such as libccs.
diff --git a/agents/virt/docs/fence_virt.txt b/agents/virt/docs/fence_virt.txt
new file mode 100644
index 0000000..e554ce4
--- /dev/null
+++ b/agents/virt/docs/fence_virt.txt
@@ -0,0 +1,127 @@
+We need a fencing agent which can work in a variety of guest cluster
+configurations and host configurations.
+
+Requirements
+
+1. Nonrequirement of guest to host networking. Virtual machines
+ may be configured to run using a nework unknown to the host
+ operating system. Therefore, the ability to run without network
+ communication between the guest and the hsot is required.
+
+2. Ease of configuration. The absolute minimum possible configuration
+ must be available.
+
+3. Nonrequirement of host clustering software. Multiple layers of
+ configuration sucks. While I fundamentally disagree with the general
+ idea that running CMAN on the host constitutes a "heavyweight
+ cluster", perception is important.
+
+4. Ability to support RHEV-M, oVirt server, and other virtual machine
+ management technologies. This is beneficial from a security standpoint
+ since it is assumed the management server will be aware of what VMs
+ are allowed to fence what other VMs.
+
+5. Upgrade compatibility with fence_xvm from a configuration standpoint.
+ This may be provided by a symlink over fence_xvm. If this feature
+ can not be provided as a matter of design, a method to convert an
+ existing fence_xvm/fence_xvmd configuration to fence_virt must be
+ present.
+
+
+Guest to Host Interaction
+-------------------------
+
+The proposal is to use various communications media plugins in order
+to facilitate flexibility with respect to how virtual machine
+environments are configured.
+
+There are at least 3 simple plugins for guest/client to host/server
+communications:
+
+ * Direct serial. The guest sends fencing requests out via /dev/ttySX
+ in the guest. The host is listening on a Unix domain socket[1],
+ and forwards fencing requests accordingly.
+
+ This satisifies most of the requirements, but adds a conundrum
+ when configuring guest clusters, as /dev/ttySX may be /dev/ttySY
+ on another guest. So, either we must account for this per-guest
+ configuration discrepancy or we must make it an administrative
+ requirement to provide the same serial device on each host
+
+ * Multicast. This violates the networking requirement, but this is
+ okay since this method of operation is optional. This operational
+ mode provides for one of the simpler configurations: all that is
+ needed is the guest's name or UUID. The guest to host
+ communications operates in the same manner as fence_xvm/fence_xvmd,
+ except that there is an implied requirement on restricting the
+ multicast packets accepted to be from the local guests.
+
+ * VM Channel over Serial. This works like direct serial, but
+ instead of owning the whole device, the device may be shared between
+ multiple applications. The server subscribes to a channel and
+ listens for fencing requests on the channel; the client in the
+ guest OS connects to the channel and issues fencing requests across
+ it. One interesting thing is that it may be possible to provide
+ unprivileged users the ability to fence using this method (I
+ do not claim to know if this is useful or not).
+
+
+Host to Hypervisor interaction
+------------------------------
+
+Similar to the way we have plugins for guest to host interaction,
+we also have plugins which actually do the real work. These plugins
+are responsible for all of the actual real work performed, including
+tracking VMs if required, forwarding requests to the appropriate hosts
+or management services, and handling the responses.
+
+We propose at 5 plugins in this case:
+
+ * Libvirt (local-only). There is no intracommunication and no
+ migration support is provided
+
+ * Cluster CPG (+ libvirt). This the way fence_xvmd
+ operates today. This setup has the most requirements on the
+ infrastructure, as it requires guest to host networking _and_
+ host-to-host clustering in order to keep track of virtual
+ machines. The benefit is that it is self-contained and requires
+ no external management nodes. VM states are stored so that other
+ CPG group members know the locations of other VMs and can make
+ some decisions about whether a VM is dead based on whether a host
+ is dead (i.e. if fencing is in use or can be performed on the
+ host).
+
+ * Libvirt-QMF ... ??? Subscription to the appropriate cluster
+ specific AMQP channel is required on the host side, but this
+ handles routing the message very easily. The fencing request
+ is forwarded to the other listeners on the channel, the VM owner
+ takes the action requested and returns a value. When new VMs
+ are created, the event is broadcast out via the AMQP channel so
+ other hosts know the locations of other VMs and can make some
+ decisions about whether a VM is dead based on whether a host
+ is dead (i.e. if fencing is in use or can be performed on the
+ host).
+
+ * oVirt Manager. The request is forwarded to the oVirt Manager
+ and the oVirt manager is responsible for taking the appropriate
+ action and responding to the request.
+
+ * RHEV-M. The request is forwarded to the RHEV-M node, which is
+ responsible for taking the appropriate action and responding to
+ the request.
+
+
+These plugins have no requirements on which guest to host communication
+plugin is used (you could, if you wanted, use 'direct serial' with
+'cluster cpg', or 'multicast' with 'RHEV-H' for example).
+
+These plugins must also be able to discover where appropriate. For
+example, the cpg plugin can only be used if corosync/openais
+is running. A defined plugin preference order should be specified/documented
+so that the host daemon behaves in a predictable manner in absence of
+host-side configuration data (about which plugin to use).
+
+
+[1] TCP was also explored, however, the security is much better
+ using a Unix domain socket, despite the additional complexity
+ of listening for VM creation events.
diff --git a/agents/virt/fence_virtd.service.in b/agents/virt/fence_virtd.service.in
new file mode 100644
index 0000000..9d2836f
--- /dev/null
+++ b/agents/virt/fence_virtd.service.in
@@ -0,0 +1,23 @@
+[Unit]
+Description=Fence-Virt system host daemon
+Documentation=man:fence_virtd(8)
+Documentation=man:fence_virt.conf(5)
+
+After=basic.target
+After=network.target
+After=syslog.target
+After=libvirtd.service
+After=corosync.service
+
+Requires=basic.target
+Requires=network.target
+
+[Install]
+WantedBy=multi-user.target
+
+[Service]
+Type=forking
+Restart=on-failure
+Environment="FENCE_VIRTD_ARGS=-w"
+
+# Autogenerated below here
diff --git a/agents/virt/include/bcast.h b/agents/virt/include/bcast.h
new file mode 100644
index 0000000..5113f04
--- /dev/null
+++ b/agents/virt/include/bcast.h
@@ -0,0 +1,16 @@
+#ifndef _XVM_MCAST_H
+#define _XVM_MCAST_H
+
+#define IPV4_MCAST_DEFAULT "225.0.0.12"
+#define IPV6_MCAST_DEFAULT "ff05::3:1"
+
+int ipv4_recv_sk(char *addr, int port);
+int ipv4_send_sk(char *src_addr, char *addr, int port,
+ struct sockaddr *src, socklen_t slen,
+ int ttl);
+int ipv6_recv_sk(char *addr, int port);
+int ipv6_send_sk(char *src_addr, char *addr, int port,
+ struct sockaddr *src, socklen_t slen,
+ int ttl);
+
+#endif
diff --git a/agents/virt/include/client.h b/agents/virt/include/client.h
new file mode 100644
index 0000000..48b92c3
--- /dev/null
+++ b/agents/virt/include/client.h
@@ -0,0 +1,9 @@
+#ifndef _CLIENT_H
+#define _CLIENT_H
+
+int tcp_fence_virt(fence_virt_args_t *args);
+int serial_fence_virt(fence_virt_args_t *args);
+int mcast_fence_virt(fence_virt_args_t *args);
+int vsock_fence_virt(fence_virt_args_t *args);
+void do_read_hostlist(int fd, int timeout);
+#endif
diff --git a/agents/virt/include/debug.h b/agents/virt/include/debug.h
new file mode 100644
index 0000000..d6a5416
--- /dev/null
+++ b/agents/virt/include/debug.h
@@ -0,0 +1,31 @@
+/*
+ Copyright Red Hat, Inc. 2007
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+#ifndef _DBG_H
+#define _DBG_H
+
+void dset(int);
+int dget(void);
+
+#define dbg_printf(level, fmt, args...) \
+do { \
+ if (dget()>=level) \
+ printf(fmt, ##args); \
+} while(0)
+
+#endif
diff --git a/agents/virt/include/fdops.h b/agents/virt/include/fdops.h
new file mode 100644
index 0000000..f3194de
--- /dev/null
+++ b/agents/virt/include/fdops.h
@@ -0,0 +1,14 @@
+#ifndef _FDOPS_H
+#define _FDOPS_H
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int _select_retry(int fdmax, fd_set * rfds, fd_set * wfds, fd_set * xfds,
+ struct timeval *timeout);
+ssize_t _write_retry(int fd, void *buf, int count, struct timeval * timeout);
+ssize_t _read_retry(int sockfd, void *buf, int count,
+ struct timeval * timeout);
+
+#endif
diff --git a/agents/virt/include/history.h b/agents/virt/include/history.h
new file mode 100644
index 0000000..3d28518
--- /dev/null
+++ b/agents/virt/include/history.h
@@ -0,0 +1,25 @@
+#ifndef _HISTORY_H
+#define _HISTORY_H
+
+typedef struct _history_node {
+ list_head();
+ void *data;
+ time_t when;
+} history_node;
+
+typedef int (*history_compare_fn)(void *, void *);
+
+typedef struct _history_info {
+ history_node *hist;
+ history_compare_fn compare_func;
+ time_t timeout;
+ size_t element_size;
+} history_info_t;
+
+history_info_t *history_init(history_compare_fn func,
+ time_t expiration, size_t element_size);
+int history_check(history_info_t *hinfo, void *stuff);
+int history_record(history_info_t *hinfo, void *data);
+int history_wipe(history_info_t *hinfo);
+
+#endif
diff --git a/agents/virt/include/ip_lookup.h b/agents/virt/include/ip_lookup.h
new file mode 100644
index 0000000..3386c71
--- /dev/null
+++ b/agents/virt/include/ip_lookup.h
@@ -0,0 +1,40 @@
+/*
+ Copyright Red Hat, Inc. 2004,2006
+
+ The Magma Cluster API Library is free software; you can redistribute
+ it and/or modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either version
+ 2.1 of the License, or (at your option) any later version.
+
+ The Magma Cluster API Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+*/
+/** @file
+ * Header for ip_lookup.c
+ */
+#ifndef _IP_LOOKUP_H
+#define _IP_LOOKUP_H
+
+#include <sys/queue.h>
+
+typedef struct _ip_address {
+ TAILQ_ENTRY(_ip_address) ipa_entries;
+ char ipa_family;
+ char *ipa_address;
+} ip_addr_t;
+
+typedef TAILQ_HEAD(_ip_list, _ip_address) ip_list_t;
+
+int ip_search(ip_list_t *ipl, char *ip_name);
+int ip_free_list(ip_list_t *ipl);
+int ip_build_list(ip_list_t *ipl);
+int ip_lookup(char *, struct addrinfo **);
+
+#endif
diff --git a/agents/virt/include/list.h b/agents/virt/include/list.h
new file mode 100644
index 0000000..01340d6
--- /dev/null
+++ b/agents/virt/include/list.h
@@ -0,0 +1,84 @@
+#ifndef _LIST_H
+#define _LIST_H
+
+/**
+ Simple list handlig macros.
+ Needs rewrite or inclusion of /usr/include/linux/list.h as a replacement.
+ */
+
+/* Must be first if structure is going to use it. */
+struct list_entry {
+ struct list_entry *le_next, *le_prev;
+};
+
+#define list_head() struct list_entry _list_head
+
+#define le(p) (&((*p)._list_head))
+
+#define list_insert(list, newnode) \
+do { \
+ if (!(*list)) { \
+ le(newnode)->le_next = \
+ le(newnode)->le_prev = le(newnode); \
+ *list = (void *)le(newnode); \
+ } else { \
+ le(*list)->le_prev->le_next = le(newnode); \
+ le(newnode)->le_next = le(*list); \
+ le(newnode)->le_prev = le(*list)->le_prev; \
+ le(*list)->le_prev = le(newnode); \
+ } \
+} while (0)
+
+
+#define list_prepend(list, newnode) \
+do { \
+ list_insert(list, newnode); \
+ *list = newnode; \
+} while (0)
+
+
+#define list_remove(list, oldnode) \
+do { \
+ if (le(oldnode) == le(*list)) { \
+ *list = (void *)le(*list)->le_next; \
+ } \
+ if (le(oldnode) == le(*list)) { \
+ le(oldnode)->le_next = NULL; \
+ le(oldnode)->le_prev = NULL; \
+ *list = NULL; \
+ } else { \
+ le(oldnode)->le_next->le_prev = le(oldnode)->le_prev; \
+ le(oldnode)->le_prev->le_next = le(oldnode)->le_next; \
+ le(oldnode)->le_prev = NULL; \
+ le(oldnode)->le_next = NULL; \
+ } \
+} while (0)
+
+
+/*
+ * list_for(list, tmp, counter) {
+ * stuff;
+ * }
+ *
+ * counter = # of items in list when done.
+ * * sets cnt to 0 before even checking list;
+ * * checks for valid list
+ * * traverses list, incrementing counter. If we get to the for loop,
+ * there must be at least one item in the list
+ * * cnt ends up being the number of items in the list.
+ */
+#define list_for(list, curr, cnt) \
+ if ((!(cnt=0)) && (*list != NULL)) \
+ for (curr = *list; \
+ (cnt == 0) || (curr != *list); \
+ curr = (void*)le(curr)->le_next, \
+ cnt++)
+
+#define list_for_rev(list, curr, cnt) \
+ if ((!(cnt=0)) && (*list != NULL)) \
+ for (curr = (void *)(le(*list)->le_prev); \
+ (cnt == 0) || ((void *)curr != le(*list)->le_prev); \
+ curr = (void*)(le(curr)->le_prev), \
+ cnt++)
+
+#endif
diff --git a/agents/virt/include/mcast.h b/agents/virt/include/mcast.h
new file mode 100644
index 0000000..f86ad96
--- /dev/null
+++ b/agents/virt/include/mcast.h
@@ -0,0 +1,32 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+#ifndef _XVM_MCAST_H
+#define _XVM_MCAST_H
+
+#define IPV4_MCAST_DEFAULT "225.0.0.12"
+#define IPV6_MCAST_DEFAULT "ff05::3:1"
+
+int ipv4_recv_sk(char *addr, int port, unsigned int ifindex);
+int ipv4_send_sk(char *src_addr, char *addr, int port,
+ struct sockaddr *src, socklen_t slen);
+int ipv6_recv_sk(char *addr, int port, unsigned int ifindex);
+int ipv6_send_sk(char *src_addr, char *addr, int port,
+ struct sockaddr *src, socklen_t slen);
+
+#endif
diff --git a/agents/virt/include/options.h b/agents/virt/include/options.h
new file mode 100644
index 0000000..6e2c1c1
--- /dev/null
+++ b/agents/virt/include/options.h
@@ -0,0 +1,99 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+#ifndef _XVM_OPTIONS_H
+#define _XVM_OPTIONS_H
+
+typedef enum {
+ F_FOREGROUND = 0x1,
+ F_NOCCS = 0x2,
+ F_ERR = 0x4,
+ F_HELP = 0x8,
+ F_USE_UUID = 0x10,
+ F_VERSION = 0x20,
+ F_CCSERR = 0x40,
+ F_CCSFAIL = 0x80,
+ F_NOCLUSTER = 0x100
+} arg_flags_t;
+
+typedef enum {
+ MODE_MULTICAST = 0,
+ /*MODE_BROADCAST = 1,*/
+ MODE_SERIAL = 2,
+ MODE_VMCHANNEL = 3,
+ MODE_TCP = 4,
+ MODE_VSOCK = 5
+} client_mode_t;
+
+typedef struct {
+ char *domain;
+ fence_cmd_t op;
+ client_mode_t mode;
+ int debug;
+ int timeout;
+ int delay;
+ int retr_time;
+ arg_flags_t flags;
+
+ struct network_args {
+ char *addr;
+ char *ipaddr;
+ char *key_file;
+ uint32_t cid;
+ int port;
+ fence_hash_t hash;
+ fence_auth_type_t auth;
+ int family;
+ unsigned int ifindex;
+ } net;
+
+ struct serial_args {
+ char *device; /* Serial device */
+ char *speed;
+ char *address; /* vmchannel IP */
+ } serial;
+} fence_virt_args_t;
+
+/* Private structure for commandline / stdin fencing args */
+struct arg_info {
+ const char opt;
+ const char *opt_desc;
+ const char *stdin_opt;
+ const char *obsoletes;
+ int deprecated;
+ int eh;
+ const char *content_type;
+ const char *default_value;
+ const char *desc;
+ void (*assign)(fence_virt_args_t *, struct arg_info *, char *);
+};
+
+
+/* Get options */
+void args_init(fence_virt_args_t *args);
+void args_finalize(fence_virt_args_t *args);
+
+void args_get_getopt(int argc, char **argv, const char *optstr,
+ fence_virt_args_t *args);
+void args_get_stdin(const char *optstr, fence_virt_args_t *args);
+void args_get_ccs(const char *optstr, fence_virt_args_t *args);
+void args_usage(char *progname, const char *optstr, int print_stdin);
+void args_print(fence_virt_args_t *args);
+void args_metadata(char *progname, const char *optstr);
+
+#endif
diff --git a/agents/virt/include/server_plugin.h b/agents/virt/include/server_plugin.h
new file mode 100644
index 0000000..04ceae0
--- /dev/null
+++ b/agents/virt/include/server_plugin.h
@@ -0,0 +1,130 @@
+/* */
+
+#ifndef _SERVER_PLUGIN_H
+#define _SERVER_PLUGIN_H
+
+#include "config.h"
+
+#define PLUGIN_VERSION_LISTENER ((double)0.3)
+#define PLUGIN_VERSION_BACKEND ((double)0.2)
+
+typedef void * listener_context_t;
+typedef void * backend_context_t;
+
+/* These callbacks hand requests off to the
+ appropriate backend. */
+
+/* Do nothing. Returns 1 (failure) to caller */
+typedef int (*fence_null_callback)(const char *vm_name,
+ void *priv);
+
+/* Turn the VM 'off'. Returns 0 to caller if successful or
+ nonzero if unsuccessful. */
+typedef int (*fence_off_callback)(const char *vm_name, const char *src,
+ uint32_t seqno, void *priv);
+
+/* Turn the VM 'on'. Returns 0 to caller if successful or
+ nonzero if unsuccessful. */
+typedef int (*fence_on_callback)(const char *vm_name, const char *src,
+ uint32_t seqno, void *priv);
+
+/* Reboot a VM. Returns 0 to caller if successful or
+ nonzero if unsuccessful. */
+typedef int (*fence_reboot_callback)(const char *vm_name, const char *src,
+ uint32_t seqno, void *priv);
+
+/* Get status of a VM. Returns 0 to caller if VM is alive or
+ nonzero if VM is not alive. */
+typedef int (*fence_status_callback)(const char *vm_name,
+ void *priv);
+
+/* Get status of backend. Returns 0 to caller if backend
+ is responding to requests. */
+typedef int (*fence_devstatus_callback)(void *priv);
+
+
+/* VMs available to fence. Returns 0 to caller if backend
+ is responding to requests and a host list can be produced */
+typedef int (*hostlist_callback)(const char *vm_name, const char *uuid,
+ int state, void *arg);
+typedef int (*fence_hostlist_callback)(hostlist_callback cb,
+ void *arg, void *priv);
+
+typedef int (*backend_init_fn)(backend_context_t *c,
+ config_object_t *config);
+typedef int (*backend_cleanup_fn)(backend_context_t c);
+
+typedef struct _fence_callbacks {
+ fence_null_callback null;
+ fence_off_callback off;
+ fence_on_callback on;
+ fence_reboot_callback reboot;
+ fence_status_callback status;
+ fence_devstatus_callback devstatus;
+ fence_hostlist_callback hostlist;
+} fence_callbacks_t;
+
+typedef struct backend_plugin {
+ const char *name;
+ const char *version;
+ const fence_callbacks_t *callbacks;
+ backend_init_fn init;
+ backend_cleanup_fn cleanup;
+} backend_plugin_t;
+
+double backend_plugin_version(void);
+const backend_plugin_t * backend_plugin_info(void);
+
+#define BACKEND_VER_SYM backend_plugin_version
+#define BACKEND_INFO_SYM backend_plugin_info
+#define BACKEND_VER_STR "backend_plugin_version"
+#define BACKEND_INFO_STR "backend_plugin_info"
+
+typedef int (*listener_init_fn)(listener_context_t *c,
+ const fence_callbacks_t *cb,
+ config_object_t *config,
+ map_object_t *map,
+ void *priv);
+typedef int (*listener_dispatch_fn)(listener_context_t c,
+ struct timeval *timeout);
+typedef int (*listener_cleanup_fn)(listener_context_t c);
+
+
+typedef struct listener_plugin {
+ const char *name;
+ const char *version;
+ listener_init_fn init;
+ listener_dispatch_fn dispatch;
+ listener_cleanup_fn cleanup;
+} listener_plugin_t;
+
+double listener_plugin_version(void);
+const listener_plugin_t * listener_plugin_info(void);
+
+#define LISTENER_VER_SYM listener_plugin_version
+#define LISTENER_INFO_SYM listener_plugin_info
+#define LISTENER_VER_STR "listener_plugin_version"
+#define LISTENER_INFO_STR "listener_plugin_info"
+
+typedef enum {
+ PLUGIN_NONE = 0,
+ PLUGIN_LISTENER = 1,
+ PLUGIN_BACKEND = 2
+} plugin_type_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const backend_plugin_t *plugin_find_backend(const char *name);
+const listener_plugin_t *plugin_find_listener(const char *name);
+
+void plugin_dump(void);
+int plugin_load(const char *filename);
+void plugin_unload(void);
+int plugin_search(const char *pathname);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/agents/virt/include/simple_auth.h b/agents/virt/include/simple_auth.h
new file mode 100644
index 0000000..4cd57ed
--- /dev/null
+++ b/agents/virt/include/simple_auth.h
@@ -0,0 +1,35 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+#ifndef _XVM_SIMPLE_AUTH_H
+#define _XVM_SIMPLE_AUTH_H
+
+#include <sys/types.h>
+
+/* 2-way challenge/response simple auth */
+#define DEFAULT_KEY_FILE "/etc/cluster/fence_xvm.key"
+
+int read_key_file(char *, char *, size_t);
+int sock_challenge(int, fence_auth_type_t, void *, size_t, int);
+int sock_response(int, fence_auth_type_t, void *, size_t, int);
+int sign_request(fence_req_t *, void *, size_t);
+int verify_request(fence_req_t *, fence_hash_t, void *, size_t);
+
+/* SSL certificate-based authentication TBD */
+
+#endif
diff --git a/agents/virt/include/simpleconfig.h b/agents/virt/include/simpleconfig.h
new file mode 100644
index 0000000..6aba85f
--- /dev/null
+++ b/agents/virt/include/simpleconfig.h
@@ -0,0 +1,56 @@
+#ifndef _SIMPLECONFIG_H
+#define _SIMPLECONFIG_H
+
+typedef int (*config_get_t)(void *config, const char *key,
+ char *value, size_t valuesz);
+typedef int (*config_set_t)(void *config, const char *key,
+ const char *value);
+typedef int (*config_parse_t)(const char *filename, void **config);
+typedef int (*config_free_t)(void *config);
+typedef void (*config_dump_t)(void *config, FILE *fp);
+
+/*
+ * We use an abstract object here so we do not have to link loadable
+ * modules against the configuration library.
+ */
+
+typedef struct {
+ config_get_t get;
+ config_set_t set;
+ config_parse_t parse;
+ config_free_t free;
+ config_dump_t dump;
+ void *info;
+} config_object_t;
+
+/*
+ * These macros may be called from within a loadable module
+ */
+#define sc_get(obj, key, value, valuesz) \
+ obj->get(obj->info, key, value, valuesz)
+#define sc_set(obj, key, value) \
+ obj->set(obj->info, key, value)
+#define sc_parse(obj, filename) \
+ obj->parse(filename, &obj->info)
+#define sc_free(obj) \
+ obj->free(obj->info)
+#define sc_dump(obj, fp) \
+ obj->dump(obj->info, fp)
+
+/*
+ * Do not call the below functions from loadable modules. Doing so
+ * requires linking the configuration library in to the modules, which
+ * is what we want to avoid.
+ */
+
+/* Returns a copy of our simple config object */
+config_object_t *sc_init(void);
+
+/* Frees a previously-allocated copy of our simple config object */
+void sc_release(config_object_t *c);
+
+int check_file_permissions(const char *fname);
+
+int do_configure(config_object_t *config, const char *filename);
+
+#endif
diff --git a/agents/virt/include/static_map.h b/agents/virt/include/static_map.h
new file mode 100644
index 0000000..736e823
--- /dev/null
+++ b/agents/virt/include/static_map.h
@@ -0,0 +1,34 @@
+#ifndef _STATIC_MAP_H
+#define _STATIC_MAP_H
+
+typedef int (*map_load_t)(void *config, void **perm_info);
+typedef int (*map_check_t)(void *info, const char *src, const char *tgt_uuid, const char *tgt_name);
+typedef void (*map_cleanup_t)(void **info);
+
+typedef struct {
+ map_load_t load;
+ map_check_t check;
+ map_cleanup_t cleanup;
+ void *info;
+} map_object_t;
+
+/*
+ * These macros may be called from within a loadable module
+ */
+#define map_load(obj, config) \
+ obj->load(config, &obj->info)
+#define map_check(obj, src, tgt_uuid) \
+ obj->check(obj->info, src, tgt_uuid, NULL)
+#define map_check2(obj, src, tgt_uuid, tgt_name) \
+ obj->check(obj->info, src, tgt_uuid, tgt_name)
+#define map_free(obj) \
+ obj->cleanup(obj->info)
+
+/* Returns a copy of our simple config object */
+void *map_init(void);
+
+/* Frees a previously-allocated copy of our simple config object */
+void map_release(void *c);
+
+
+#endif
diff --git a/agents/virt/include/tcp.h b/agents/virt/include/tcp.h
new file mode 100644
index 0000000..609f3e9
--- /dev/null
+++ b/agents/virt/include/tcp.h
@@ -0,0 +1,27 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+#ifndef _XVM_TCP_H
+#define _XVM_TCP_H
+
+int ipv4_connect(struct in_addr *in_addr, uint16_t port, int timeout);
+int ipv6_connect(struct in6_addr *in6_addr, uint16_t port, int timeout);
+int ipv4_listen(const char *addr_str, uint16_t port, int backlog);
+int ipv6_listen(const char *addr_str, uint16_t port, int backlog);
+
+#endif
diff --git a/agents/virt/include/tcp_listener.h b/agents/virt/include/tcp_listener.h
new file mode 100644
index 0000000..75dec93
--- /dev/null
+++ b/agents/virt/include/tcp_listener.h
@@ -0,0 +1,7 @@
+#ifndef __TCP_LISTENER_H
+#define __TCP_LISTENER_H
+
+#define IPV4_TCP_ADDR_DEFAULT "127.0.0.1"
+#define IPV6_TCP_ADDR_DEFAULT "::1"
+
+#endif
diff --git a/agents/virt/include/xvm.h b/agents/virt/include/xvm.h
new file mode 100644
index 0000000..bcd7db2
--- /dev/null
+++ b/agents/virt/include/xvm.h
@@ -0,0 +1,158 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+#ifndef _XVM_H
+#define _XVM_H
+
+#include <stdint.h>
+#include <sechash.h>
+#include <netinet/in.h>
+#include <byteswap.h>
+#include <endian.h>
+
+#define XVM_VERSION "1.9.0"
+
+#define MAX_DOMAINNAME_LENGTH 64 /* XXX MAXHOSTNAMELEN */
+#define MAX_ADDR_LEN sizeof(struct sockaddr_in6)
+#define DOMAIN0NAME "Domain-0"
+#define DOMAIN0UUID "00000000-0000-0000-0000-000000000000"
+
+typedef enum {
+ HASH_NONE = 0x0, /* No packet signing */
+ HASH_SHA1 = 0x1, /* SHA1 signing */
+ HASH_SHA256 = 0x2, /* SHA256 signing */
+ HASH_SHA512 = 0x3 /* SHA512 signing */
+} fence_hash_t;
+
+#define DEFAULT_HASH HASH_SHA256
+
+typedef enum {
+ AUTH_NONE = 0x0, /* Plain TCP */
+ AUTH_SHA1 = 0x1, /* Challenge-response (SHA1) */
+ AUTH_SHA256 = 0x2, /* Challenge-response (SHA256) */
+ AUTH_SHA512 = 0x3 /* Challenge-response (SHA512) */
+ /* AUTH_SSL_X509 = 0x10 SSL X509 certificates */
+} fence_auth_type_t;
+
+#define DEFAULT_AUTH AUTH_SHA256
+
+typedef enum {
+ FENCE_NULL = 0x0,
+ FENCE_OFF = 0x1, /* Turn the VM off */
+ FENCE_REBOOT = 0x2, /* Hit the reset button */
+ FENCE_ON = 0x3, /* Turn the VM on */
+ FENCE_STATUS = 0x4, /* virtual machine status (off/on) */
+ FENCE_DEVSTATUS = 0x5, /* Status of the fencing device */
+ FENCE_HOSTLIST = 0x6, /* List VMs controllable */
+ FENCE_METADATA = 0x7, /* Print fence agent metadata */
+ FENCE_VALIDATEALL = 0x8 /* Validate command-line or stdin arguments and exit */
+} fence_cmd_t;
+
+#define DEFAULT_TTL 4
+
+#ifndef DEFAULT_HYPERVISOR_URI
+#define DEFAULT_HYPERVISOR_URI "qemu:///system"
+#endif
+
+#define MAX_HASH_LENGTH SHA512_LENGTH
+#define MAX_KEY_LEN 4096
+
+typedef struct __attribute__ ((packed)) _fence_req {
+ uint8_t request; /* Fence request */
+ uint8_t hashtype; /* Hash type used */
+ uint8_t addrlen; /* Length of address */
+ uint8_t flags; /* Special flags */
+#define RF_UUID 0x1 /* Flag specifying UUID */
+ uint8_t domain[MAX_DOMAINNAME_LENGTH]; /* Domain to fence*/
+ uint8_t address[MAX_ADDR_LEN]; /* We're this IP */
+#define DEFAULT_MCAST_PORT 1229
+ uint16_t port; /* Port we bound to */
+ uint8_t random[6]; /* Random Data */
+ uint32_t seqno; /* Request identifier; can be random */
+ uint32_t family; /* Address family */
+ uint8_t hash[MAX_HASH_LENGTH]; /* Binary hash */
+} fence_req_t;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define swab_fence_req_t(req) \
+do { \
+ (req)->seqno = bswap_32((req)->seqno); \
+ (req)->family = bswap_32((req)->family); \
+ (req)->port = bswap_32((req)->port); \
+} while(0)
+#else
+#define swab_fence_req_t(req)
+#endif
+
+
+/* for host list */
+typedef struct __attribute__ ((packed)) _host_info {
+ uint8_t domain[MAX_DOMAINNAME_LENGTH];
+ uint8_t uuid[MAX_DOMAINNAME_LENGTH];
+ uint8_t state;
+ uint8_t pad;
+} host_state_t;
+
+
+#define DEFAULT_SERIAL_DEVICE "/dev/ttyS1"
+#define DEFAULT_SERIAL_SPEED "115200,8N1"
+#define DEFAULT_CHANNEL_IP "10.0.2.179"
+#define SERIAL_MAGIC 0x61626261 /* endian doesn't matter */
+
+typedef struct __attribute__((packed)) _serial_fence_req {
+ uint32_t magic;
+ uint8_t request;
+ uint8_t flags;
+ uint8_t domain[MAX_DOMAINNAME_LENGTH];
+ uint32_t seqno;
+} serial_req_t;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define swab_serial_req_t(req) \
+do { \
+ (req)->magic = bswap_32((req)->magic); \
+ (req)->seqno = bswap_32((req)->seqno); \
+} while(0)
+#else
+#define swab_serial_req_t(req)
+#endif
+
+
+typedef struct __attribute__((packed)) _serial_fense_resp {
+ uint32_t magic;
+ uint8_t response;
+} serial_resp_t;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define swab_serial_resp_t(req) \
+do { \
+ (req)->magic = bswap_32((req)->magic); \
+} while(0)
+#else
+#define swab_serial_resp_t(req)
+#endif
+
+
+#define RESP_SUCCESS 0
+#define RESP_FAIL 1
+#define RESP_OFF 2
+#define RESP_PERM 3
+#define RESP_HOSTLIST 253
+
+
+#endif
diff --git a/agents/virt/man/.gitignore b/agents/virt/man/.gitignore
new file mode 100644
index 0000000..4a80f6e
--- /dev/null
+++ b/agents/virt/man/.gitignore
@@ -0,0 +1,2 @@
+fence_virt.8
+fence_virt.wiki
diff --git a/agents/virt/man/Makefile.am b/agents/virt/man/Makefile.am
new file mode 100644
index 0000000..5b8ae36
--- /dev/null
+++ b/agents/virt/man/Makefile.am
@@ -0,0 +1,28 @@
+###############################################################################
+###############################################################################
+##
+## Copyright (C) 2009-2021 Red Hat, Inc.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2.
+##
+###############################################################################
+###############################################################################
+
+MAINTAINERCLEANFILES = Makefile.in
+
+dist_man8_MANS = fence_xvm.8 fence_virtd.8
+dist_man5_MANS = fence_virt.conf.5
+man8_MANS = fence_virt.8
+
+fence_virt.8: $(top_builddir)/agents/virt/client/fence_virt $(top_srcdir)/lib/fence2man.xsl
+ set -e && \
+ ../client/$(@:%.8=%) -o metadata > .$(@F).tmp && \
+ xmllint --noout --relaxng $(top_srcdir)/lib/metadata.rng .$(@F).tmp && \
+ xsltproc $(top_srcdir)/lib/fence2man.xsl .$(@F).tmp > $@
+ xsltproc $(top_srcdir)/lib/fence2wiki.xsl .$(@F).tmp | grep -v '<?xml' > $(@F:%.8=%.wiki)
+
+
+clean-local:
+ rm -f fence_virt.8* .*.8.tmp *.wiki
diff --git a/agents/virt/man/fence_virt.conf.5 b/agents/virt/man/fence_virt.conf.5
new file mode 100644
index 0000000..f920a66
--- /dev/null
+++ b/agents/virt/man/fence_virt.conf.5
@@ -0,0 +1,335 @@
+.TH fence_virt.conf 5
+
+.SH NAME
+fence_virt.conf - configuration file for fence_virtd
+
+.SH DESCRIPTION
+
+The fence_virt.conf file contains configuration information for fence_virtd,
+a fencing request routing daemon for clusters of virtual machines.
+
+The file is tree-structured. There are parent/child relationships and sibling
+relationships between the nodes.
+
+ foo {
+ bar {
+ baz = "1";
+ }
+ }
+
+There are three primary sections of fence_virt.conf.
+
+.SH SECTIONS
+.SS fence_virtd
+
+This section contains global information about how fence_virtd is to operate.
+The most important pieces of information are as follows:
+
+.TP
+.B listener
+.
+the listener plugin for receiving fencing requests from clients
+
+.TP
+.B backend
+.
+the plugin to be used to carry out fencing requests
+
+.TP
+.B foreground
+.
+do not fork into the background.
+
+.TP
+.B wait_for_init
+.
+wait for the frontend and backends to become available rather than giving up immediately.
+This replaces wait_for_backend in 0.2.x.
+
+.TP
+.B module_path
+.
+the module path to search for plugins
+
+.SS listeners
+
+This section contains listener-specific configuration information; see the
+section about listeners below.
+
+.SS backends
+
+This section contains listener-specific configuration information; see the
+section about listeners below.
+
+.SS groups
+
+This section contains static maps of which virtual machines
+may fence which other virtual machines; see the section
+about groups below.
+
+
+.SH LISTENERS
+
+There are various listeners available for fence_virtd, each one handles
+decoding and authentication of a given fencing request. The following
+configuration blocks belong in the \fBlisteners\fP section of fence_virt.conf
+
+.SS multicast
+.TP
+.B key_file
+.
+the shared key file to use (default: /etc/cluster/fence_xvm.key).
+
+.TP
+.B hash
+.
+the weakest hashing algorithm allowed for client requests. Clients may send packets with stronger hashes than the one specified, but not weaker ones. (default: sha256, but could
+be sha1, sha512, or none)
+
+.TP
+.B auth
+.
+the hashing algorithm to use for the simplistic challenge-response authentication
+(default: sha256, but could be sha1, sha512, or none)
+
+.TP
+.B family
+.
+the IP family to use (default: ipv4, but may be ipv6)
+
+.TP
+.B address
+.
+the multicast address to listen on (default: 225.0.0.12)
+
+.TP
+.B port
+.
+the multicast port to listen on (default: 1229)
+
+.TP
+.B interface
+.
+interface to listen on. By default, fence_virtd listens on all interfaces.
+However, this causes problems in some environments where the host computer
+is used as a gateway.
+
+.SS serial
+
+The serial listener plugin utilizes libvirt's serial (or VMChannel)
+mapping to listen for requests. When using the serial listener, it is
+necessary to add a serial port (preferably pointing to /dev/ttyS1) or
+a channel (preferably pointing to 10.0.2.179:1229) to the
+libvirt domain description. Note that only type
+.B unix
+, mode
+.B bind
+serial ports and channels are supported and each VM should have a
+separate unique socket. Example libvirt XML:
+
+.in 8
+ <\fBserial\fP type='unix'>
+ <source mode='bind' path='/sandbox/guests/fence_socket_molly'/>
+ <target port='1'/>
+ </serial>
+ <\fBchannel\fP type='unix'>
+ <source mode='bind' path='/sandbox/guests/fence_molly_vmchannel'/>
+ <target type='guestfwd' address='10.0.2.179' port='1229'/>
+ </channel>
+.in 0
+
+.TP
+.B uri
+.
+the URI to use when connecting to libvirt by the serial plugin (optional).
+
+.TP
+.B path
+.
+The same directory that is defined for the domain serial port path (From example above: /sandbox/guests). Sockets must reside in this directory in order to be considered valid. This can be used to prevent fence_virtd from using the wrong sockets.
+
+.TP
+.B mode
+.
+This selects the type of sockets to register. Valid values are "serial"
+(default) and "vmchannel".
+
+.SS tcp
+The tcp listener operates similarly to the multicast listener but uses TCP sockets for communication instead of using multicast packets.
+
+.TP
+.B key_file
+.
+the shared key file to use (default: /etc/cluster/fence_xvm.key).
+
+.TP
+.B hash
+.
+the hashing algorithm to use for packet signing (default: sha256, but could
+be sha1, sha512, or none)
+
+.TP
+.B auth
+.
+the hashing algorithm to use for the simplistic challenge-response authentication
+(default: sha256, but could be sha1, sha512, or none)
+
+.TP
+.B family
+.
+the IP family to use (default: ipv4, but may be ipv6)
+
+.TP
+.B address
+.
+the IP address to listen on (default: 127.0.0.1 for IPv4, ::1 for IPv6)
+
+.TP
+.B port
+.
+the TCP port to listen on (default: 1229)
+
+.SS vsock
+The vsock listener operates similarly to the multicast listener but uses virtual machine sockets (AF_VSOCK) for communication instead of using multicast packets.
+
+.TP
+.B key_file
+.
+the shared key file to use (default: /etc/cluster/fence_xvm.key).
+
+.TP
+.B hash
+.
+the hashing algorithm to use for packet signing (default: sha256, but could
+be sha1, sha512, or none)
+
+.TP
+.B auth
+.
+the hashing algorithm to use for the simplistic challenge-response authentication
+(default: sha256, but could be sha1, sha512, or none)
+
+.TP
+.B port
+.
+the vsock port to listen on (default: 1229)
+
+.SH BACKENDS
+
+There are various backends available for fence_virtd, each one handles
+routing a fencing request to a hypervisor or management tool. The following
+configuration blocks belong in the \fBbackends\fP section of fence_virt.conf
+
+.SS libvirt
+
+The libvirt plugin is the simplest plugin. It is used in environments where
+routing fencing requests between multiple hosts is not required, for example
+by a user running a cluster of virtual machines on a single desktop computer.
+
+.TP
+.B uri
+.
+the URI to use when connecting to libvirt.
+
+All libvirt URIs are accepted and passed as-is.
+
+See https://libvirt.org/uri.html#remote-uris for examples.
+
+NOTE: When VMs are run as non-root user the socket path must be set as part
+of the URI.
+
+Example: qemu:///session?socket=/run/user/<UID>/libvirt/virtqemud-sock
+
+.SS cpg
+
+The cpg plugin uses corosync CPG and libvirt to track virtual
+machines and route fencing requests to the appropriate computer.
+
+.TP
+.B uri
+.
+the URI to use when connecting to libvirt by the cpg plugin.
+
+.TP
+.B name_mode
+.
+The cpg plugin, in order to retain compatibility with fence_xvm,
+stores virtual machines in a certain way. The
+default was to use 'name' when using fence_xvm and fence_xvmd, and so this
+is still the default. However, it is strongly recommended to use 'uuid'
+instead of 'name' in all cluster environments involving more than one
+physical host in order to avoid the potential for name collisions.
+
+.SH GROUPS
+
+Fence_virtd supports static maps which allow grouping of VMs. The
+groups are arbitrary and are checked at fence time. Any member of
+a group may fence any other member. Hosts may be assigned to multiple
+groups if desired.
+
+.SS group
+
+This defines a group.
+
+.TP
+.B name
+.
+Optionally define the name of the group. Useful only for configuration
+readability and debugging of configuration parsing.
+
+.TP
+.B uuid
+.
+Defines UUID as a member of a group. It can be used multiple times
+to specify both node name and UUID values that can be fenced.
+When using the serial listener, the vm uuid is required and it is
+recommended to add also the vm name.
+
+.TP
+.B ip
+.
+Defines an IP which is allowed to send fencing requests
+for members of this group (e.g. for multicast). It can be used
+multiple times to allow more than 1 IP to send fencing requests to
+the group. It is highly recommended that this be used in conjunction
+with a key file.
+When using the vsock listener, ip should contain the CID value assigned
+by libvirt to the vm.
+When using the serial listener, ip value is not used and can be omitted.
+
+
+.SH EXAMPLE
+
+ fence_virtd {
+ listener = "multicast";
+ backend = "cpg";
+ }
+
+ # this is the listeners section
+
+ listeners {
+ multicast {
+ key_file = "/etc/cluster/fence_xvm.key";
+ }
+ }
+
+ backends {
+ libvirt {
+ uri = "qemu:///system";
+ }
+ }
+
+ groups {
+ group {
+ name = "cluster1";
+ ip = "192.168.1.1";
+ ip = "192.168.1.2";
+ uuid = "44179d3f-6c63-474f-a212-20c8b4b25b16";
+ uuid = "1ce02c4b-dfa1-42cb-b5b1-f0b1091ece60";
+ uuid = "node1";
+ uuid = "node2";
+ }
+ }
+
+.SH SEE ALSO
+fence_virtd(8), fence_virt(8), fence_xvm(8), fence(8)
diff --git a/agents/virt/man/fence_virtd.8 b/agents/virt/man/fence_virtd.8
new file mode 100644
index 0000000..56f6938
--- /dev/null
+++ b/agents/virt/man/fence_virtd.8
@@ -0,0 +1,53 @@
+.TH FENCE_AGENT 8 2010-01-05 "fence_virtd (Fence Agent)"
+.SH NAME
+fence_virtd - Fencing host for virtual machines
+
+.SH DESCRIPTION
+.P
+fence_virtd is a host daemon designed to route fencing requests for
+virtual machines.
+
+Fence_virt and fence_xvm talk to fence_virtd, which supports multiple backend plugins, including:
+ - libvirt for single-node operation
+ - Corosync CPG and libvirt when using Linux-cluster release 3.0.0 or later
+ - libvirt-qpid for multi-node, non-cluster operation
+
+For compatibility, fence_xvm from linux-cluster release 2 may talk to fence_virtd.
+
+.P
+fence_virtd accepts a few options on the command line, but most options
+are read from fence_virt.conf.
+
+.SH PARAMETERS
+.TP
+.B -d
+.
+Specify debug level, e.g. "-d99"
+
+.TP
+.B -c
+.
+Interactively prompt user for configuration information
+
+.TP
+.B -f
+.
+Specify an alternate configuration file instead of /etc/fence_virt.conf
+
+.TP
+.B -F
+.
+Do not fork into background after starting (overrides any setting in fence_virt.conf)
+
+.TP
+.B -w
+.
+Wait for backend to be available (overrides any setting in fence_virt.conf)
+
+.TP
+.B -p
+.
+Specify the full path to the pid file used to record the active process pid.
+
+.SH SEE ALSO
+fence_virt(8), fence_xvm(8), fence(8), fence_virt.conf(5)
diff --git a/agents/virt/man/fence_xvm.8 b/agents/virt/man/fence_xvm.8
new file mode 100644
index 0000000..5d0cfdd
--- /dev/null
+++ b/agents/virt/man/fence_xvm.8
@@ -0,0 +1 @@
+.so man8/fence_virt.8
diff --git a/agents/virt/server/Makefile.am b/agents/virt/server/Makefile.am
new file mode 100644
index 0000000..fbca617
--- /dev/null
+++ b/agents/virt/server/Makefile.am
@@ -0,0 +1,79 @@
+###############################################################################
+###############################################################################
+##
+## Copyright (C) 2009-2021 Red Hat, Inc.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2.
+##
+###############################################################################
+###############################################################################
+
+MAINTAINERCLEANFILES = Makefile.in
+
+noinst_HEADERS = cpg.h serial.h uuid-test.h virt.h
+
+sbin_PROGRAMS = fence_virtd
+
+#
+# daemon
+#
+fence_virtd_SOURCES = main.c plugin.c config.c static_map.c uuid-test.c \
+ daemon_init.c
+
+fence_virtd_CFLAGS = $(VIRT_AM_CFLAGS) \
+ $(nss_CFLAGS) $(xml2_CFLAGS) $(uuid_CFLAGS) $(PTHREAD_CFLAGS) \
+ $(AM_CFLAGS)
+
+fence_virtd_LDADD = $(VIRT_CONFIG_LIBS) $(VIRT_COMMON_LIBS) \
+ $(nss_LIBS) $(xml2_LIBS) $(uuid_LIBS) $(PTHREAD_LIBS) $(dl_LIBS)
+
+fence_virtd_LDFLAGS = $(VIRT_AM_LDFLAGS) $(VIRT_COMMON_LDFLAGS)
+
+virt_la_SOURCES = libvirt.c virt.c uuid-test.c
+cpg_la_SOURCES = cpg-virt.c cpg.c virt.c uuid-test.c
+multicast_la_SOURCES = mcast.c history.c
+tcp_la_SOURCES = tcp.c history.c
+vsock_la_SOURCES = vsock.c history.c
+serial_la_SOURCES = virt-serial.c virt-sockets.c serial.c history.c
+
+fence_virtd_CFLAGS += -DMODULE_PATH=\"$(libdir)/fence-virt/\"
+
+fvlibdir = $(libdir)/fence-virt
+
+fvlib_LTLIBRARIES =
+
+MODULESCFLAGS = $(VIRT_AM_CFLAGS) $(AM_CFLAGS)
+MODULESLDFLAGS = $(VIRT_AM_LDFLAGS) $(VIRT_COMMON_LIBS) $(VIRT_COMMON_LDFLAGS) -module -avoid-version -export-dynamic
+
+if modlibvirt
+fvlib_LTLIBRARIES += virt.la
+virt_la_CFLAGS = $(MODULESCFLAGS) $(nss_CFLAGS) $(virt_CFLAGS)
+virt_la_LDFLAGS = $(MODULESLDFLAGS) $(nss_LIBS) $(virt_LIBS)
+endif
+if modcpg
+fvlib_LTLIBRARIES += cpg.la
+cpg_la_CFLAGS = $(MODULESCFLAGS) $(nss_CFLAGS) $(cpg_CFLAGS) $(virt_CFLAGS)
+cpg_la_LDFLAGS = $(MODULESLDFLAGS) $(nss_LIBS) $(cpg_LIBS) $(virt_LIBS)
+endif
+if modmulticast
+fvlib_LTLIBRARIES += multicast.la
+multicast_la_CFLAGS = $(MODULESCFLAGS) $(nss_CFLAGS)
+multicast_la_LDFLAGS = $(MODULESLDFLAGS) $(nss_LIBS)
+endif
+if modserial
+fvlib_LTLIBRARIES += serial.la
+serial_la_CFLAGS = $(MODULESCFLAGS) $(nss_CFLAGS) $(xml2_CFLAGS) $(virt_CFLAGS)
+serial_la_LDFLAGS = $(MODULESLDFLAGS) $(nss_LIBS) $(xml2_LIBS) $(virt_LIBS)
+endif
+if modtcp
+fvlib_LTLIBRARIES += tcp.la
+tcp_la_CFLAGS = $(MODULESCFLAGS) $(nss_CFLAGS)
+tcp_la_LDFLAGS = $(MODULESLDFLAGS) $(nss_LIBS)
+endif
+if modvsock
+fvlib_LTLIBRARIES += vsock.la
+vsock_la_CFLAGS = $(MODULESCFLAGS) $(nss_CFLAGS)
+vsock_la_LDFLAGS = $(MODULESLDFLAGS) $(nss_LIBS)
+endif
diff --git a/agents/virt/server/config.c b/agents/virt/server/config.c
new file mode 100644
index 0000000..fa9af97
--- /dev/null
+++ b/agents/virt/server/config.c
@@ -0,0 +1,698 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "mcast.h"
+#include "xvm.h"
+#include "server_plugin.h"
+#include "simple_auth.h"
+
+
+static int
+yesno(const char *prompt, int dfl)
+{
+ char result[10];
+
+ printf("%s [%c/%c]? ", prompt, dfl?'Y':'y', dfl?'n':'N');
+ fflush(stdout);
+
+ memset(result, 0, sizeof(result));
+ if (fgets(result, 9, stdin) == NULL)
+ return dfl;
+
+ if (result[0] == 'y' || result[0] == 'Y')
+ return 1;
+ if (result[0] == 'n' || result[0] == 'N')
+ return 0;
+
+ return dfl;
+}
+
+
+static int
+text_input(const char *prompt, const char *dfl, char *input, size_t len)
+{
+ const char *tmpdfl = dfl;
+ const char *nulldfl = "";
+
+ if (dfl == NULL) {
+ tmpdfl = nulldfl;
+ }
+
+ printf("%s [%s]: ", prompt, tmpdfl);
+ fflush(stdout);
+
+ memset(input, 0, len);
+ if (fgets(input, len, stdin) == NULL) {
+ strncpy(input, tmpdfl, len);
+ return 0;
+ }
+ if (input[strlen(input)-1] == '\n')
+ input[strlen(input)-1] = 0;
+
+ if (strlen(input) == 0) {
+ strncpy(input, tmpdfl, len);
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static int
+plugin_path_configure(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+ int done = 0;
+
+ if (sc_get(config, "fence_virtd/@module_path", val,
+ sizeof(val))) {
+#ifdef MODULE_PATH
+ snprintf(val, sizeof(val), MODULE_PATH);
+#else
+ printf("Failed to determine module search path.\n");
+#endif
+ }
+
+ do {
+ text_input("Module search path", val, inp, sizeof(inp));
+
+ printf("\n");
+ done = plugin_search(inp);
+ if (done > 0) {
+ plugin_dump();
+ done = 1;
+ } else {
+ done = 0;
+ printf("No modules found in %s!\n", inp);
+ if (yesno("Use this value anyway", 0) == 1)
+ done = 1;
+ }
+ } while (!done);
+
+ sc_set(config, "fence_virtd/@module_path", inp);
+
+ return 0;
+}
+
+
+static int
+backend_config_libvirt(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+
+ printf("\n");
+ printf("The libvirt backend module is designed for single desktops or\n"
+ "servers. Do not use in environments where virtual machines\n"
+ "may be migrated between hosts.\n\n");
+
+ /* Default backend plugin */
+ if (sc_get(config, "backends/libvirt/@uri", val,
+ sizeof(val))) {
+ strncpy(val, DEFAULT_HYPERVISOR_URI, sizeof(val));
+ }
+
+ text_input("Libvirt URI", val, inp, sizeof(inp));
+
+ sc_set(config, "backends/libvirt/@uri", inp);
+
+ return 0;
+}
+
+
+static int
+backend_config_cpg(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+ int done = 0;
+
+ printf("\n");
+ printf("The CPG backend module is designed for use in clusters\n"
+ "running corosync and libvirt. It utilizes the CPG API to \n"
+ "route fencing requests, finally utilizing libvirt to perform\n"
+ "fencing actions.\n\n");
+
+ if (sc_get(config, "backends/cpg/@uri", val,
+ sizeof(val))) {
+ strncpy(val, DEFAULT_HYPERVISOR_URI, sizeof(val));
+ }
+
+ text_input("Libvirt URI", val, inp, sizeof(inp));
+
+ sc_set(config, "backends/cpg/@uri", inp);
+
+ printf("\n");
+ printf("The name mode is how the cpg plugin stores and \n"
+ "references virtual machines. Since virtual machine names\n"
+ "are not guaranteed to be unique cluster-wide, use of UUIDs\n"
+ "is strongly recommended. However, for compatibility with \n"
+ "fence_xvmd, the use of 'name' mode is also supported.\n\n");
+
+ if (sc_get(config, "backends/cpg/@name_mode", val,
+ sizeof(val))) {
+ strncpy(val, "uuid", sizeof(val));
+ }
+
+ do {
+ text_input("VM naming/tracking mode (name or uuid)",
+ val, inp, sizeof(inp));
+ if (!strcasecmp(inp, "uuid")) {
+ done = 1;
+ } else if (!strcasecmp(inp, "name")) {
+ done = 0;
+ printf("This can be dangerous if you do not take care to"
+ "ensure that\n"
+ "virtual machine names are unique "
+ "cluster-wide.\n");
+ if (yesno("Use name mode anyway", 1) == 1)
+ done = 1;
+ }
+ } while (!done);
+
+ sc_set(config, "backends/cpg/@name_mode", inp);
+
+ return 0;
+}
+
+
+static int
+listener_config_multicast(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+ const char *family = "ipv4";
+ struct in_addr sin;
+ struct in6_addr sin6;
+ int done = 0;
+
+ printf("\n");
+ printf("The multicast listener module is designed for use environments\n"
+ "where the guests and hosts may communicate over a network using\n"
+ "multicast.\n\n");
+
+
+ /* MULTICAST IP ADDRESS/FAMILY */
+ printf("The multicast address is the address that a client will use to\n"
+ "send fencing requests to fence_virtd.\n\n");
+
+ if (sc_get(config, "listeners/multicast/@address",
+ val, sizeof(val)-1)) {
+ strncpy(val, IPV4_MCAST_DEFAULT, sizeof(val));
+ }
+
+ done = 0;
+ do {
+ text_input("Multicast IP Address", val, inp, sizeof(inp));
+
+ if (inet_pton(AF_INET, inp, &sin) == 1) {
+ printf("\nUsing ipv4 as family.\n\n");
+ family = "ipv4";
+ done = 1;
+ } else if (inet_pton(AF_INET6, inp, &sin6) == 1) {
+ printf("\nUsing ipv6 as family.\n\n");
+ family = "ipv6";
+ done = 1;
+ } else
+ printf("'%s' is not a valid IP address!\n", inp);
+ } while (!done);
+
+ sc_set(config, "listeners/multicast/@family", family);
+ sc_set(config, "listeners/multicast/@address", inp);
+
+ /* MULTICAST IP PORT */
+ if (sc_get(config, "listeners/multicast/@port",
+ val, sizeof(val)-1)) {
+ snprintf(val, sizeof(val), "%d", DEFAULT_MCAST_PORT);
+ }
+
+ done = 0;
+ do {
+ char *p;
+ int ret;
+
+ text_input("Multicast IP Port", val, inp, sizeof(inp));
+ ret = strtol(inp, &p, 0);
+ if (*p != '\0' || ret <= 0 || ret >= 65536) {
+ printf("Port value '%s' is out of range\n", val);
+ continue;
+ } else
+ done = 1;
+ } while (!done);
+
+ sc_set(config, "listeners/multicast/@port", inp);
+
+ /* MULTICAST INTERFACE */
+ printf("\nSetting a preferred interface causes fence_virtd to listen only\n"
+ "on that interface. Normally, it listens on all interfaces.\n"
+ "In environments where the virtual machines are using the host\n"
+ "machine as a gateway, this *must* be set (typically to virbr0).\n"
+ "Set to 'none' for no interface.\n\n"
+ );
+
+ if (sc_get(config, "listeners/multicast/@interface",
+ val, sizeof(val)-1)) {
+ strncpy(val, "none", sizeof(val));
+ }
+
+ done = 0;
+ do {
+ text_input("Interface", val, inp, sizeof(inp));
+
+ if (!strcasecmp(inp, "none")) {
+ break;
+ }
+
+ if (strlen(inp) > 0) {
+ int ret;
+
+ ret = if_nametoindex(inp);
+ if (ret < 0) {
+ printf("Invalid interface: %s\n", inp);
+ if (yesno("Use anyway", 1) == 1)
+ done = 1;
+ } else
+ done = 1;
+ } else
+ printf("No interface given\n");
+ } while (!done);
+
+ if (!strcasecmp(inp, "none")) {
+ sc_set(config, "listeners/multicast/@interface", NULL);
+ } else {
+ sc_set(config, "listeners/multicast/@interface", inp);
+ }
+
+
+ /* KEY FILE */
+ printf("\nThe key file is the shared key information which is used to\n"
+ "authenticate fencing requests. The contents of this file must\n"
+ "be distributed to each physical host and virtual machine within\n"
+ "a cluster.\n\n");
+
+ if (sc_get(config, "listeners/multicast/@key_file",
+ val, sizeof(val)-1)) {
+ strncpy(val, DEFAULT_KEY_FILE, sizeof(val));
+ }
+
+ done = 0;
+ do {
+ text_input("Key File", val, inp, sizeof(inp));
+
+ if (!strcasecmp(inp, "none")) {
+ break;
+ }
+
+ if (strlen(inp) > 0) {
+ if (inp[0] != '/') {
+ printf("Invalid key file: %s\n", inp);
+ if (yesno("Use anyway", 1) == 1)
+ done = 1;
+ } else
+ done = 1;
+ } else
+ printf("No key file given\n");
+ } while (!done);
+
+ if (!strcasecmp(inp, "none")) {
+ sc_set(config, "listeners/multicast/@key_file", NULL);
+ } else {
+ sc_set(config, "listeners/multicast/@key_file", inp);
+ }
+
+ return 0;
+}
+
+static int
+listener_config_tcp(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+ const char *family = "ipv4";
+ struct in_addr sin;
+ struct in6_addr sin6;
+ int done = 0;
+
+ printf("\n");
+ printf("The TCP listener module is designed for use in environments\n"
+ "where the guests and hosts communicate over viosproxy.\n\n");
+
+ /* IP ADDRESS/FAMILY */
+ printf("The IP address is the address that a client will use to\n"
+ "send fencing requests to fence_virtd.\n\n");
+
+ if (sc_get(config, "listeners/tcp/@address",
+ val, sizeof(val)-1)) {
+ strncpy(val, IPV4_MCAST_DEFAULT, sizeof(val));
+ }
+
+ done = 0;
+ do {
+ text_input("TCP Listen IP Address", val, inp, sizeof(inp));
+
+ if (inet_pton(AF_INET, inp, &sin) == 1) {
+ printf("\nUsing ipv4 as family.\n\n");
+ family = "ipv4";
+ done = 1;
+ } else if (inet_pton(AF_INET6, inp, &sin6) == 1) {
+ printf("\nUsing ipv6 as family.\n\n");
+ family = "ipv6";
+ done = 1;
+ } else {
+ printf("'%s' is not a valid IP address!\n", inp);
+ continue;
+ }
+ } while (!done);
+
+ sc_set(config, "listeners/tcp/@family", family);
+ sc_set(config, "listeners/tcp/@address", inp);
+
+ /* MULTICAST IP PORT */
+ if (sc_get(config, "listeners/tcp/@port",
+ val, sizeof(val)-1)) {
+ snprintf(val, sizeof(val), "%d", DEFAULT_MCAST_PORT);
+ }
+
+ done = 0;
+ do {
+ char *p;
+ int ret;
+
+ text_input("TCP Listen Port", val, inp, sizeof(inp));
+
+ ret = strtol(inp, &p, 0);
+ if (*p != '\0' || ret <= 0 || ret >= 65536) {
+ printf("Port value '%s' is out of range\n", val);
+ continue;
+ }
+ done = 1;
+ } while (!done);
+ sc_set(config, "listeners/tcp/@port", inp);
+
+ /* KEY FILE */
+ printf("\nThe key file is the shared key information which is used to\n"
+ "authenticate fencing requests. The contents of this file must\n"
+ "be distributed to each physical host and virtual machine within\n"
+ "a cluster.\n\n");
+
+ if (sc_get(config, "listeners/tcp/@key_file",
+ val, sizeof(val)-1)) {
+ strncpy(val, DEFAULT_KEY_FILE, sizeof(val));
+ }
+
+ done = 0;
+ do {
+ text_input("Key File", val, inp, sizeof(inp));
+
+ if (!strcasecmp(inp, "none")) {
+ break;
+ }
+
+ if (strlen(inp) > 0) {
+ if (inp[0] != '/') {
+ printf("Invalid key file: %s\n", inp);
+ if (yesno("Use anyway", 1) == 1)
+ done = 1;
+ } else
+ done = 1;
+ } else
+ printf("No key file given\n");
+ } while (!done);
+
+ if (!strcasecmp(inp, "none")) {
+ sc_set(config, "listeners/tcp/@key_file", NULL);
+ } else {
+ sc_set(config, "listeners/tcp/@key_file", inp);
+ }
+
+ return 0;
+}
+
+static int
+listener_config_serial(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+ int done;
+
+ printf("\n");
+ printf("The serial plugin allows fence_virtd to communicate with\n"
+ "guests using serial or guest-forwarding VMChannel instead\n"
+ "of using TCP/IP networking.\n\n");
+ printf("Special configuration of virtual machines is required. See\n"
+ "fence_virt.conf(5) for more details.\n\n");
+
+ if (sc_get(config, "listeners/serial/@uri",
+ val, sizeof(val)-1)) {
+ strncpy(val, DEFAULT_HYPERVISOR_URI, sizeof(val));
+ }
+
+ text_input("Libvirt URI", val, inp, sizeof(inp));
+
+ printf("\nSetting a socket path prevents fence_virtd from taking\n"
+ "hold of all Unix domain sockets created when the guest\n"
+ "is started. A value like /var/run/cluster/fence might\n"
+ "be a good value. Don't forget to create the directory!\n\n");
+
+ if (sc_get(config, "listeners/serial/@path",
+ val, sizeof(val)-1)) {
+ strncpy(val, "none", sizeof(val));
+ }
+
+ text_input("Socket directory", val, inp, sizeof(inp));
+ if (!strcasecmp(inp, "none")) {
+ sc_set(config, "listeners/serial/@path", NULL);
+ } else {
+ sc_set(config, "listeners/serial/@path", inp);
+ }
+
+ printf("\nThe serial plugin allows two types of guest to host\n"
+ "configurations. One is via a serial port; the other is\n"
+ "utilizing the newer VMChannel.\n\n");
+
+ if (sc_get(config, "listeners/serial/@mode",
+ val, sizeof(val)-1)) {
+ strncpy(val, "serial", sizeof(val));
+ }
+
+ if (!strcasecmp(inp, "none")) {
+ sc_set(config, "listeners/serial/@path", NULL);
+ } else {
+ sc_set(config, "listeners/serial/@path", inp);
+ }
+
+ done = 0;
+ do {
+ text_input("Mode (serial or vmchannel)", val, inp,
+ sizeof(inp));
+
+ if (strcasecmp(inp, "serial") && strcasecmp(inp, "vmchannel")) {
+ printf("Invalid mode: %s\n", inp);
+ if (yesno("Use anyway", 1) == 1)
+ done = 1;
+ } else
+ done = 1;
+ } while (!done);
+
+ sc_set(config, "listeners/serial/@mode", inp);
+ return 0;
+}
+
+
+static int
+backend_configure(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+ int done;
+
+ printf("\n");
+ printf("Backend modules are responsible for routing requests to\n"
+ "the appropriate hypervisor or management layer.\n\n");
+
+ /* Default backend plugin */
+ if (sc_get(config, "fence_virtd/@backend", val,
+ sizeof(val))) {
+ strncpy(val, "libvirt", sizeof(val));
+ }
+
+ done = 0;
+ do {
+ text_input("Backend module", val, inp, sizeof(inp));
+ if (plugin_find_backend(inp) == NULL) {
+ printf("No backend module named %s found!\n", inp);
+ if (yesno("Use this value anyway", 0) == 1)
+ done = 1;
+ } else
+ done = 1;
+ } while (!done);
+
+ sc_set(config, "fence_virtd/@backend", inp);
+
+ if (!strcmp(inp, "libvirt")) {
+ backend_config_libvirt(config);
+ } else if (!strcmp(inp, "cpg")) {
+ backend_config_cpg(config);
+ }
+
+ return 0;
+}
+
+
+static int
+listener_configure(config_object_t *config)
+{
+ char val[4096];
+ char inp[4096];
+ int done;
+
+ printf("\n");
+ printf("Listener modules are responsible for accepting requests\n"
+ "from fencing clients.\n\n");
+
+ /* Default backend plugin */
+ if (sc_get(config, "fence_virtd/@listener", val,
+ sizeof(val))) {
+ strncpy(val, "multicast", sizeof(val));
+ }
+
+ done = 0;
+ do {
+ text_input("Listener module", val, inp, sizeof(inp));
+ if (plugin_find_listener(inp) == NULL) {
+ printf("No listener module named %s found!\n", inp);
+ if (yesno("Use this value anyway", 0) == 1)
+ done = 1;
+ } else
+ done = 1;
+ } while (!done);
+
+ sc_set(config, "fence_virtd/@listener", inp);
+ if (!strcmp(inp, "multicast"))
+ listener_config_multicast(config);
+ else if (!strcmp(inp, "tcp"))
+ listener_config_tcp(config);
+ else if (!strcmp(inp, "serial"))
+ listener_config_serial(config);
+ else
+ printf("Unable to configure unknown listner module '%s'\n", inp);
+
+ return 0;
+}
+
+
+int
+check_file_permissions(const char *fname)
+{
+ struct stat st;
+ mode_t file_perms = 0600;
+ int ret;
+
+ ret = stat(fname, &st);
+ if (ret != 0) {
+ printf("stat failed on file '%s': %s\n",
+ fname, strerror(errno));
+ return 1;
+ }
+
+ if ((st.st_mode & 0777) != file_perms) {
+ printf("Insecure permissions on file "
+ "'%s': changing from 0%o to 0%o.\n", fname,
+ (unsigned int)(st.st_mode & 0777),
+ (unsigned int)file_perms);
+ if (chmod(fname, file_perms) != 0) {
+ printf("Unable to change permissions for file '%s'",
+ fname);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int
+do_configure(config_object_t *config, const char *config_file)
+{
+ FILE *fp = NULL;
+ char message[80];
+ char tmp_filename[4096];
+ int tmp_fd = -1;
+ mode_t old_umask;
+
+ if (sc_parse(config, config_file) != 0) {
+ printf("Parsing of %s failed.\n", config_file);
+ if (yesno("Start from scratch", 0) == 0) {
+ return 1;
+ }
+ }
+
+ plugin_path_configure(config);
+ listener_configure(config);
+ backend_configure(config);
+
+ printf("\nConfiguration complete.\n\n");
+
+ printf("=== Begin Configuration ===\n");
+ sc_dump(config, stdout);
+ printf("=== End Configuration ===\n");
+
+ snprintf(message, sizeof(message), "Replace %s with the above",
+ config_file);
+ if (yesno(message, 0) == 0) {
+ return 1;
+ }
+
+ snprintf(tmp_filename, sizeof(tmp_filename),
+ "%s.XXXXXX", config_file);
+
+ old_umask = umask(077);
+ tmp_fd = mkstemp(tmp_filename);
+ umask(old_umask);
+
+ if (tmp_fd < 0) {
+ perror("fopen");
+ printf("Failed to write configuration file!\n");
+ return 1;
+ }
+
+ fp = fdopen(tmp_fd, "w+");
+ if (fp == NULL)
+ goto out_fail;
+
+ sc_dump(config, fp);
+
+ if (rename(tmp_filename, config_file) < 0) {
+ perror("rename");
+ goto out_fail;
+ }
+
+ fclose(fp);
+ close(tmp_fd);
+
+ return 0;
+
+out_fail:
+ if (fp)
+ fclose(fp);
+ if (tmp_fd >= 0)
+ close(tmp_fd);
+ if (strlen(tmp_filename))
+ unlink(tmp_filename);
+ printf("Failed to write configuration file!\n");
+ return 1;
+}
diff --git a/agents/virt/server/cpg-virt.c b/agents/virt/server/cpg-virt.c
new file mode 100644
index 0000000..304519c
--- /dev/null
+++ b/agents/virt/server/cpg-virt.c
@@ -0,0 +1,643 @@
+/*
+ Copyright Red Hat, Inc. 2017
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/*
+ * Author: Ryan McCabe <rmccabe@redhat.com>
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <time.h>
+#include <string.h>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <corosync/cpg.h>
+
+#include "debug.h"
+#include "virt.h"
+#include "xvm.h"
+#include "cpg.h"
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "server_plugin.h"
+
+#define NAME "cpg"
+#define CPG_VERSION "0.1"
+
+#define MAGIC 0x38e93fc2
+
+struct cpg_info {
+ int magic;
+ config_object_t *config;
+ int vp_count;
+ virConnectPtr *vp;
+};
+
+#define VALIDATE(arg) \
+do {\
+ if (!arg || ((struct cpg_info *) arg)->magic != MAGIC) { \
+ errno = EINVAL;\
+ return -1; \
+ } \
+} while(0)
+
+static struct cpg_info *cpg_virt_handle = NULL;
+static int use_uuid = 0;
+pthread_mutex_t local_vm_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static virt_list_t *local_vm_list = NULL;
+
+pthread_mutex_t remote_vm_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static virt_list_t *remote_vm_list = NULL;
+
+static void cpg_virt_init_libvirt(struct cpg_info *info);
+
+static int
+virt_list_update(struct cpg_info *info, virt_list_t **vl, int my_id)
+{
+ virt_list_t *list = NULL;
+
+ if (*vl)
+ vl_free(*vl);
+
+ list = vl_get(info->vp, info->vp_count, my_id);
+ if (!list && (errno == EPIPE || errno == EINVAL)) {
+ do {
+ cpg_virt_init_libvirt(info);
+ } while (info->vp_count == 0);
+ list = vl_get(info->vp, info->vp_count, my_id);
+ }
+
+ *vl = list;
+ if (!list)
+ return -1;
+
+ return 0;
+}
+
+
+static void
+store_domains(virt_list_t *vl)
+{
+ int i;
+
+ if (!vl)
+ return;
+
+ for (i = 0 ; i < vl->vm_count ; i++) {
+ int ret;
+
+ if (!strcmp(DOMAIN0NAME, vl->vm_states[i].v_name))
+ continue;
+
+ ret = cpg_send_vm_state(&vl->vm_states[i]);
+ if (ret < 0) {
+ printf("Error storing VM state for %s|%s\n",
+ vl->vm_states[i].v_name, vl->vm_states[i].v_uuid);
+ }
+ }
+}
+
+
+static void
+update_local_vms(struct cpg_info *info)
+{
+ uint32_t my_id = 0;
+
+ if (!info)
+ return;
+
+ cpg_get_ids(&my_id, NULL);
+ virt_list_update(info, &local_vm_list, my_id);
+ store_domains(local_vm_list);
+}
+
+
+static int
+do_off(struct cpg_info *info, const char *vm_name)
+{
+ dbg_printf(5, "%s %s\n", __FUNCTION__, vm_name);
+ return vm_off(info->vp, info->vp_count, vm_name);
+
+}
+
+static int
+do_on(struct cpg_info *info, const char *vm_name)
+{
+ dbg_printf(5, "%s %s\n", __FUNCTION__, vm_name);
+ return vm_on(info->vp, info->vp_count, vm_name);
+
+}
+
+static int
+do_reboot(struct cpg_info *info, const char *vm_name)
+{
+ dbg_printf(5, "%s %s\n", __FUNCTION__, vm_name);
+ return vm_reboot(info->vp, info->vp_count, vm_name);
+}
+
+static void
+cpg_join_cb(const struct cpg_address *join, size_t joinlen) {
+ struct cpg_info *info = cpg_virt_handle;
+
+ pthread_mutex_lock(&local_vm_list_lock);
+ update_local_vms(info);
+ pthread_mutex_unlock(&local_vm_list_lock);
+}
+
+static void
+cpg_leave_cb(const struct cpg_address *left, size_t leftlen) {
+ struct cpg_info *info = cpg_virt_handle;
+ int i;
+
+ pthread_mutex_lock(&remote_vm_list_lock);
+ for (i = 0 ; i < leftlen ; i++) {
+ dbg_printf(2, "Removing VMs owned by nodeid %u\n", left[i].nodeid);
+ vl_remove_by_owner(&remote_vm_list, left[i].nodeid);
+ }
+ pthread_mutex_unlock(&remote_vm_list_lock);
+
+ pthread_mutex_lock(&local_vm_list_lock);
+ update_local_vms(info);
+ pthread_mutex_unlock(&local_vm_list_lock);
+}
+
+static void
+store_cb(void *data, size_t len, uint32_t nodeid, uint32_t seqno)
+{
+ uint32_t my_id;
+ virt_state_t *vs = (virt_state_t *) data;
+ struct cpg_info *info = cpg_virt_handle;
+
+ cpg_get_ids(&my_id, NULL);
+
+ if (nodeid == my_id)
+ return;
+
+ pthread_mutex_lock(&local_vm_list_lock);
+ if (!local_vm_list)
+ update_local_vms(info);
+ pthread_mutex_unlock(&local_vm_list_lock);
+
+ pthread_mutex_lock(&remote_vm_list_lock);
+ vl_update(&remote_vm_list, vs);
+ pthread_mutex_unlock(&remote_vm_list_lock);
+}
+
+/*
+** This function must a send reply from at least one node, otherwise
+** the requesting fence_virtd will block forever in wait_cpt_reply.
+*/
+static void
+do_real_work(void *data, size_t len, uint32_t nodeid, uint32_t seqno)
+{
+ struct cpg_info *info = cpg_virt_handle;
+ struct cpg_fence_req *req = data;
+ struct cpg_fence_req reply;
+ int reply_code = -1;
+ virt_state_t *vs = NULL;
+ int cur_state;
+ uint32_t cur_owner = 0;
+ int local = 0;
+ uint32_t my_id, high_id;
+
+ dbg_printf(2, "Request %d for VM %s\n", req->request, req->vm_name);
+
+ if (cpg_get_ids(&my_id, &high_id) == -1) {
+ syslog(LOG_WARNING, "Unable to get CPG IDs");
+ printf("Should never happen: Can't get CPG node ids - can't proceed\n");
+ return;
+ }
+
+ memcpy(&reply, req, sizeof(reply));
+
+ pthread_mutex_lock(&local_vm_list_lock);
+ update_local_vms(info);
+ if (strlen(req->vm_name)) {
+ if (use_uuid)
+ vs = vl_find_uuid(local_vm_list, req->vm_name);
+ else
+ vs = vl_find_name(local_vm_list, req->vm_name);
+
+ if (vs) {
+ local = 1;
+ cur_owner = vs->v_state.s_owner;
+ cur_state = vs->v_state.s_state;
+ dbg_printf(2, "Found VM %s locally state %d\n",
+ req->vm_name, cur_state);
+ }
+ }
+ pthread_mutex_unlock(&local_vm_list_lock);
+
+ if (vs == NULL) {
+ pthread_mutex_lock(&remote_vm_list_lock);
+ if (strlen(req->vm_name)) {
+ if (use_uuid)
+ vs = vl_find_uuid(remote_vm_list, req->vm_name);
+ else
+ vs = vl_find_name(remote_vm_list, req->vm_name);
+
+ if (vs) {
+ cur_owner = vs->v_state.s_owner;
+ cur_state = vs->v_state.s_state;
+ dbg_printf(2, "Found VM %s remotely on %u state %d\n",
+ req->vm_name, cur_owner, cur_state);
+ }
+ }
+ pthread_mutex_unlock(&remote_vm_list_lock);
+ }
+
+ if (!vs) {
+ /*
+ ** We know about all domains on all nodes in the CPG group.
+ ** If we didn't find it, and we're high ID, act on the request.
+ ** We can safely assume the VM is OFF because it wasn't found
+ ** on any current members of the CPG group.
+ */
+ if (my_id == high_id) {
+ if (req->request == FENCE_STATUS)
+ reply_code = RESP_OFF;
+ else if (req->request == FENCE_OFF || req->request == FENCE_REBOOT)
+ reply_code = RESP_SUCCESS;
+ else
+ reply_code = 1;
+
+ dbg_printf(2, "Acting on request %d for unknown domain %s -> %d\n",
+ req->request, req->vm_name, reply_code);
+ goto out;
+ }
+
+ dbg_printf(2, "Not acting on request %d for unknown domain %s\n",
+ req->request, req->vm_name);
+ return;
+ }
+
+ if (local) {
+ if (req->request == FENCE_STATUS) {
+ /* We already have the status */
+ if (cur_state == VIR_DOMAIN_SHUTOFF)
+ reply_code = RESP_OFF;
+ else
+ reply_code = RESP_SUCCESS;
+ } else if (req->request == FENCE_OFF) {
+ reply_code = do_off(info, req->vm_name);
+ } else if (req->request == FENCE_ON) {
+ reply_code = do_on(info, req->vm_name);
+ } else if (req->request == FENCE_REBOOT) {
+ reply_code = do_reboot(info, req->vm_name);
+ } else {
+ dbg_printf(2, "Not explicitly handling request type %d for %s\n",
+ req->request, req->vm_name);
+ reply_code = 0;
+ }
+ goto out;
+ }
+
+ /*
+ ** This is a request for a non-local domain that exists on a
+ ** current CPG group member, so that member will see the request
+ ** and act on it. We don't need to do anything.
+ */
+ dbg_printf(2, "Nothing to do for non-local domain %s seq %d owner %u\n",
+ req->vm_name, seqno, cur_owner);
+ return;
+
+out:
+ dbg_printf(2, "[%s] sending reply code seq %d -> %d\n",
+ req->vm_name, seqno, reply_code);
+
+ reply.response = reply_code;
+ if (cpg_send_reply(&reply, sizeof(reply), nodeid, seqno) < 0) {
+ dbg_printf(2, "cpg_send_reply failed for %s [%d %d]: %s\n",
+ req->vm_name, nodeid, seqno, strerror(errno));
+ }
+}
+
+
+static int
+do_request(const char *vm_name, int request, uint32_t seqno)
+{
+ struct cpg_fence_req freq, *frp;
+ size_t retlen;
+ uint32_t seq;
+ int ret;
+
+ memset(&freq, 0, sizeof(freq));
+ if (!vm_name) {
+ dbg_printf(1, "No VM name\n");
+ return 1;
+ }
+
+ if (strlen(vm_name) >= sizeof(freq.vm_name)) {
+ dbg_printf(1, "VM name %s too long\n", vm_name);
+ return 1;
+ }
+
+ strcpy(freq.vm_name, vm_name);
+
+ freq.request = request;
+ freq.seqno = seqno;
+
+ if (cpg_send_req(&freq, sizeof(freq), &seq) != 0) {
+ dbg_printf(1, "Failed to send request %d for VM %s\n",
+ freq.request, vm_name);
+ return 1;
+ }
+
+ dbg_printf(2, "Sent request %d for VM %s got seqno %d\n",
+ request, vm_name, seq);
+
+ if (cpg_wait_reply((void *) &frp, &retlen, seq) != 0) {
+ dbg_printf(1, "Failed to receive reply seq %d for %s\n", seq, vm_name);
+ return 1;
+ }
+
+ dbg_printf(2, "Received reply [%d] seq %d for %s\n",
+ frp->response, seq, vm_name);
+
+ ret = frp->response;
+ free(frp);
+
+ return ret;
+}
+
+
+static int
+cpg_virt_null(const char *vm_name, void *priv)
+{
+ VALIDATE(priv);
+ printf("[cpg-virt] Null operation on %s\n", vm_name);
+
+ return 1;
+}
+
+
+static int
+cpg_virt_off(const char *vm_name, const char *src, uint32_t seqno, void *priv)
+{
+ VALIDATE(priv);
+ printf("[cpg-virt] OFF operation on %s seq %d\n", vm_name, seqno);
+
+ return do_request(vm_name, FENCE_OFF, seqno);
+}
+
+
+static int
+cpg_virt_on(const char *vm_name, const char *src, uint32_t seqno, void *priv)
+{
+ VALIDATE(priv);
+ printf("[cpg-virt] ON operation on %s seq %d\n", vm_name, seqno);
+
+ return do_request(vm_name, FENCE_ON, seqno);
+}
+
+
+static int
+cpg_virt_devstatus(void *priv)
+{
+ printf("[cpg-virt] Device status\n");
+ VALIDATE(priv);
+
+ return 0;
+}
+
+
+static int
+cpg_virt_status(const char *vm_name, void *priv)
+{
+ VALIDATE(priv);
+ printf("[cpg-virt] STATUS operation on %s\n", vm_name);
+
+ return do_request(vm_name, FENCE_STATUS, 0);
+}
+
+
+static int
+cpg_virt_reboot(const char *vm_name, const char *src,
+ uint32_t seqno, void *priv)
+{
+ VALIDATE(priv);
+ printf("[cpg-virt] REBOOT operation on %s seq %d\n", vm_name, seqno);
+
+ return do_request(vm_name, FENCE_REBOOT, 0);
+}
+
+
+static int
+cpg_virt_hostlist(hostlist_callback callback, void *arg, void *priv)
+{
+ struct cpg_info *info = (struct cpg_info *) priv;
+ int i;
+
+ VALIDATE(priv);
+ printf("[cpg-virt] HOSTLIST operation\n");
+
+ pthread_mutex_lock(&local_vm_list_lock);
+ update_local_vms(info);
+ for (i = 0 ; i < local_vm_list->vm_count ; i++) {
+ callback(local_vm_list->vm_states[i].v_name,
+ local_vm_list->vm_states[i].v_uuid,
+ local_vm_list->vm_states[i].v_state.s_state, arg);
+ }
+ pthread_mutex_unlock(&local_vm_list_lock);
+
+ return 1;
+}
+
+static void
+cpg_virt_init_libvirt(struct cpg_info *info) {
+ config_object_t *config = info->config;
+ int i = 0;
+
+ if (info->vp) {
+ dbg_printf(2, "Lost libvirtd connection. Reinitializing.\n");
+ for (i = 0 ; i < info->vp_count ; i++)
+ virConnectClose(info->vp[i]);
+ free(info->vp);
+ info->vp = NULL;
+ }
+ info->vp_count = 0;
+
+ do {
+ virConnectPtr vp;
+ virConnectPtr *vpl = NULL;
+ char conf_attr[256];
+ char value[1024];
+ char *uri;
+
+ if (i != 0) {
+ snprintf(conf_attr, sizeof(conf_attr),
+ "backends/cpg/@uri%d", i);
+ } else
+ snprintf(conf_attr, sizeof(conf_attr), "backends/cpg/@uri");
+ ++i;
+
+ if (sc_get(config, conf_attr, value, sizeof(value)) != 0)
+ break;
+
+ uri = value;
+ vp = virConnectOpen(uri);
+ if (!vp) {
+ dbg_printf(1, "[cpg-virt:INIT] Failed to connect to URI: %s\n", uri);
+ continue;
+ }
+
+ vpl = realloc(info->vp, sizeof(*info->vp) * (info->vp_count + 1));
+ if (!vpl) {
+ dbg_printf(1, "[cpg-virt:INIT] Out of memory allocating URI: %s\n",
+ uri);
+ virConnectClose(vp);
+ continue;
+ }
+
+ info->vp = vpl;
+ info->vp[info->vp_count++] = vp;
+
+ if (i > 1)
+ dbg_printf(1, "[cpg-virt:INIT] Added URI%d %s\n", i - 1, uri);
+ else
+ dbg_printf(1, "[cpg_virt:INIT] Added URI %s\n", uri);
+ } while (1);
+}
+
+static int
+cpg_virt_init(backend_context_t *c, config_object_t *config)
+{
+ char value[1024];
+ struct cpg_info *info = NULL;
+ int ret;
+
+ ret = cpg_start(PACKAGE_NAME,
+ do_real_work, store_cb, cpg_join_cb, cpg_leave_cb);
+ if (ret < 0)
+ return -1;
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return -1;
+ info->magic = MAGIC;
+ info->config = config;
+
+ if (sc_get(config, "fence_virtd/@debug", value, sizeof(value)) == 0)
+ dset(atoi(value));
+
+ cpg_virt_init_libvirt(info);
+
+ /* Naming scheme is no longer a top-level config option.
+ * However, we retain it here for configuration compatibility with
+ * versions 0.1.3 and previous.
+ */
+ if (sc_get(config, "fence_virtd/@name_mode",
+ value, sizeof(value)-1) == 0) {
+
+ dbg_printf(1, "Got %s for name_mode\n", value);
+ if (!strcasecmp(value, "uuid")) {
+ use_uuid = 1;
+ } else if (!strcasecmp(value, "name")) {
+ use_uuid = 0;
+ } else {
+ dbg_printf(1, "Unsupported name_mode: %s\n", value);
+ }
+ }
+
+ if (sc_get(config, "backends/cpg/@name_mode",
+ value, sizeof(value)-1) == 0)
+ {
+ dbg_printf(1, "Got %s for name_mode\n", value);
+ if (!strcasecmp(value, "uuid")) {
+ use_uuid = 1;
+ } else if (!strcasecmp(value, "name")) {
+ use_uuid = 0;
+ } else {
+ dbg_printf(1, "Unsupported name_mode: %s\n", value);
+ }
+ }
+
+ if (info->vp_count < 1) {
+ dbg_printf(1, "[cpg_virt:INIT] Could not connect to any hypervisors\n");
+ cpg_stop();
+ free(info);
+ return -1;
+ }
+
+ pthread_mutex_lock(&local_vm_list_lock);
+ update_local_vms(info);
+ pthread_mutex_unlock(&local_vm_list_lock);
+
+ *c = (void *) info;
+ cpg_virt_handle = info;
+ return 0;
+}
+
+
+static int
+cpg_virt_shutdown(backend_context_t c)
+{
+ struct cpg_info *info = (struct cpg_info *)c;
+ int i = 0;
+ int ret = 0;
+
+ VALIDATE(info);
+ info->magic = 0;
+
+ cpg_stop();
+
+ for (i = 0 ; i < info->vp_count ; i++) {
+ if (virConnectClose(info->vp[i]) < 0)
+ ret = -errno;
+ }
+
+ free(info->vp);
+ free(info);
+
+ return ret;
+}
+
+
+static fence_callbacks_t cpg_callbacks = {
+ .null = cpg_virt_null,
+ .off = cpg_virt_off,
+ .on = cpg_virt_on,
+ .reboot = cpg_virt_reboot,
+ .status = cpg_virt_status,
+ .devstatus = cpg_virt_devstatus,
+ .hostlist = cpg_virt_hostlist
+};
+
+static backend_plugin_t cpg_virt_plugin = {
+ .name = NAME,
+ .version = CPG_VERSION,
+ .callbacks = &cpg_callbacks,
+ .init = cpg_virt_init,
+ .cleanup = cpg_virt_shutdown,
+};
+
+double
+BACKEND_VER_SYM(void)
+{
+ return PLUGIN_VERSION_BACKEND;
+}
+
+const backend_plugin_t *
+BACKEND_INFO_SYM(void)
+{
+ return &cpg_virt_plugin;
+}
diff --git a/agents/virt/server/cpg.c b/agents/virt/server/cpg.c
new file mode 100644
index 0000000..8f84cd8
--- /dev/null
+++ b/agents/virt/server/cpg.c
@@ -0,0 +1,411 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <malloc.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/select.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/uio.h>
+#include <list.h>
+#include <pthread.h>
+
+#include <corosync/cpg.h>
+
+#include "debug.h"
+#include "virt.h"
+#include "cpg.h"
+
+#define NODE_ID_NONE ((uint32_t) -1)
+
+struct msg_queue_node {
+ list_head();
+ uint32_t seqno;
+#define STATE_CLEAR 0
+#define STATE_MESSAGE 1
+ uint32_t state;
+ void *msg;
+ size_t msglen;
+};
+
+struct wire_msg {
+#define TYPE_REQUEST 0
+#define TYPE_REPLY 1
+#define TYPE_STORE_VM 2
+ uint32_t type;
+ uint32_t seqno;
+ uint32_t target;
+ uint32_t pad;
+ char data[0];
+};
+
+static uint32_t seqnum = 0;
+static struct msg_queue_node *pending = NULL;
+static cpg_handle_t cpg_handle;
+static struct cpg_name gname;
+
+static pthread_mutex_t cpg_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cpg_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t cpg_thread = 0;
+
+static pthread_mutex_t cpg_ids_mutex = PTHREAD_MUTEX_INITIALIZER;
+static uint32_t my_node_id = NODE_ID_NONE;
+static uint32_t high_id_from_callback = NODE_ID_NONE;
+
+static request_callback_fn req_callback_fn;
+static request_callback_fn store_callback_fn;
+static confchange_callback_fn conf_leave_fn;
+static confchange_callback_fn conf_join_fn;
+
+
+int
+cpg_get_ids(uint32_t *my_id, uint32_t *high_id)
+{
+ if (!my_id && !high_id)
+ return -1;
+
+ pthread_mutex_lock(&cpg_ids_mutex);
+ if (my_id)
+ *my_id = my_node_id;
+
+ if (high_id)
+ *high_id = high_id_from_callback;
+ pthread_mutex_unlock(&cpg_ids_mutex);
+
+ return 0;
+}
+
+static void
+cpg_deliver_func(cpg_handle_t h,
+ const struct cpg_name *group_name,
+ uint32_t nodeid,
+ uint32_t pid,
+ void *msg,
+ size_t msglen)
+{
+ struct msg_queue_node *n;
+ struct wire_msg *m = msg;
+ int x, found;
+
+ pthread_mutex_lock(&cpg_mutex);
+ if (m->type == TYPE_REPLY) {
+ /* Reply to a request we sent */
+ found = 0;
+
+ list_for(&pending, n, x) {
+ if (m->seqno != n->seqno)
+ continue;
+ if (m->target != my_node_id)
+ continue;
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ goto out_unlock;
+
+ /* Copy our message in to a buffer */
+ n->msglen = msglen - sizeof(*m);
+ if (!n->msglen) {
+ /* XXX do what? */
+ }
+ n->msg = malloc(n->msglen);
+ if (!n->msg) {
+ goto out_unlock;
+ }
+ n->state = STATE_MESSAGE;
+ memcpy(n->msg, (char *)msg + sizeof(*m), n->msglen);
+
+ list_remove(&pending, n);
+ list_insert(&pending, n);
+
+ dbg_printf(2, "Seqnum %d replied; removing from list\n", n->seqno);
+
+ pthread_cond_broadcast(&cpg_cond);
+ goto out_unlock;
+ }
+ pthread_mutex_unlock(&cpg_mutex);
+
+ if (m->type == TYPE_REQUEST) {
+ req_callback_fn(&m->data, msglen - sizeof(*m),
+ nodeid, m->seqno);
+ }
+ if (m->type == TYPE_STORE_VM) {
+ store_callback_fn(&m->data, msglen - sizeof(*m),
+ nodeid, m->seqno);
+ }
+
+ return;
+
+out_unlock:
+ pthread_mutex_unlock(&cpg_mutex);
+}
+
+
+static void
+cpg_config_change(cpg_handle_t h,
+ const struct cpg_name *group_name,
+ const struct cpg_address *members, size_t memberlen,
+ const struct cpg_address *left, size_t leftlen,
+ const struct cpg_address *join, size_t joinlen)
+{
+ int x;
+ int high;
+
+ pthread_mutex_lock(&cpg_ids_mutex);
+ high = my_node_id;
+
+ for (x = 0; x < memberlen; x++) {
+ if (members[x].nodeid > high)
+ high = members[x].nodeid;
+ }
+
+ high_id_from_callback = high;
+ pthread_mutex_unlock(&cpg_ids_mutex);
+
+ if (joinlen > 0)
+ conf_join_fn(join, joinlen);
+
+ if (leftlen > 0)
+ conf_leave_fn(left, leftlen);
+}
+
+
+static cpg_callbacks_t my_callbacks = {
+ .cpg_deliver_fn = cpg_deliver_func,
+ .cpg_confchg_fn = cpg_config_change
+};
+
+
+int
+cpg_send_req(void *data, size_t len, uint32_t *seqno)
+{
+ struct iovec iov;
+ struct msg_queue_node *n;
+ struct wire_msg *m;
+ size_t msgsz = sizeof(*m) + len;
+ int ret;
+
+ n = malloc(sizeof(*n));
+ if (!n)
+ return -1;
+
+ m = malloc(msgsz);
+ if (!m) {
+ free(n);
+ return -1;
+ }
+
+ /* only incremented on send */
+ n->state = STATE_CLEAR;
+ n->msg = NULL;
+ n->msglen = 0;
+
+ pthread_mutex_lock(&cpg_mutex);
+ list_insert(&pending, n);
+ n->seqno = ++seqnum;
+ m->seqno = seqnum;
+ *seqno = seqnum;
+ pthread_mutex_unlock(&cpg_mutex);
+
+ m->type = TYPE_REQUEST; /* XXX swab? */
+ m->target = NODE_ID_NONE;
+ memcpy(&m->data, data, len);
+
+ iov.iov_base = m;
+ iov.iov_len = msgsz;
+ ret = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, &iov, 1);
+
+ free(m);
+ if (ret == CS_OK)
+ return 0;
+ return -1;
+}
+
+
+int
+cpg_send_vm_state(virt_state_t *vs)
+{
+ struct iovec iov;
+ struct msg_queue_node *n;
+ struct wire_msg *m;
+ size_t msgsz = sizeof(*m) + sizeof(*vs);
+ int ret;
+
+ n = calloc(1, (sizeof(*n)));
+ if (!n)
+ return -1;
+
+ m = calloc(1, msgsz);
+ if (!m) {
+ free(n);
+ return -1;
+ }
+
+ n->state = STATE_MESSAGE;
+ n->msg = NULL;
+ n->msglen = 0;
+
+ pthread_mutex_lock(&cpg_mutex);
+ list_insert(&pending, n);
+ pthread_mutex_unlock(&cpg_mutex);
+
+ m->type = TYPE_STORE_VM;
+ m->target = NODE_ID_NONE;
+
+ memcpy(&m->data, vs, sizeof(*vs));
+
+ iov.iov_base = m;
+ iov.iov_len = msgsz;
+ ret = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, &iov, 1);
+
+ free(m);
+ if (ret == CS_OK)
+ return 0;
+
+ return -1;
+}
+
+
+int
+cpg_send_reply(void *data, size_t len, uint32_t nodeid, uint32_t seqno)
+{
+ struct iovec iov;
+ struct wire_msg *m;
+ size_t msgsz = sizeof(*m) + len;
+ int ret;
+
+ m = malloc(msgsz);
+ if (!m)
+ return -1;
+
+ /* only incremented on send */
+ m->seqno = seqno;
+ m->type = TYPE_REPLY; /* XXX swab? */
+ m->target = nodeid;
+ memcpy(&m->data, data, len);
+
+ iov.iov_base = m;
+ iov.iov_len = msgsz;
+ ret = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, &iov, 1);
+
+ free(m);
+ if (ret == CS_OK)
+ return 0;
+
+ return -1;
+}
+
+
+int
+cpg_wait_reply(void **data, size_t *len, uint32_t seqno)
+{
+ struct msg_queue_node *n;
+ int x, found = 0;
+
+ while (!found) {
+ found = 0;
+ pthread_mutex_lock(&cpg_mutex);
+ pthread_cond_wait(&cpg_cond, &cpg_mutex);
+
+ list_for(&pending, n, x) {
+ if (n->seqno != seqno)
+ continue;
+ if (n->state != STATE_MESSAGE)
+ continue;
+ found = 1;
+ goto out;
+ }
+ pthread_mutex_unlock(&cpg_mutex);
+ }
+
+out:
+ list_remove(&pending, n);
+ pthread_mutex_unlock(&cpg_mutex);
+
+ *data = n->msg;
+ *len = n->msglen;
+ free(n);
+
+ return 0;
+}
+
+
+static void *
+cpg_dispatch_thread(void *arg)
+{
+ cpg_dispatch(cpg_handle, CS_DISPATCH_BLOCKING);
+
+ return NULL;
+}
+
+
+int
+cpg_start( const char *name,
+ request_callback_fn req_cb_fn,
+ request_callback_fn store_cb_fn,
+ confchange_callback_fn join_fn,
+ confchange_callback_fn leave_fn)
+{
+ cpg_handle_t h;
+ int ret;
+
+ errno = EINVAL;
+
+ if (!name)
+ return -1;
+
+ ret = snprintf(gname.value, sizeof(gname.value), "%s", name);
+ if (ret <= 0)
+ return -1;
+
+ if (ret >= sizeof(gname.value)) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ gname.length = ret;
+
+ memset(&h, 0, sizeof(h));
+ if (cpg_initialize(&h, &my_callbacks) != CS_OK) {
+ perror("cpg_initialize");
+ return -1;
+ }
+
+ if (cpg_join(h, &gname) != CS_OK) {
+ perror("cpg_join");
+ return -1;
+ }
+
+ cpg_local_get(h, &my_node_id);
+ dbg_printf(2, "My CPG nodeid is %d\n", my_node_id);
+
+ pthread_mutex_lock(&cpg_mutex);
+ pthread_create(&cpg_thread, NULL, cpg_dispatch_thread, NULL);
+
+ memcpy(&cpg_handle, &h, sizeof(h));
+
+ req_callback_fn = req_cb_fn;
+ store_callback_fn = store_cb_fn;
+ conf_join_fn = join_fn;
+ conf_leave_fn = leave_fn;
+
+ pthread_mutex_unlock(&cpg_mutex);
+
+ return 0;
+}
+
+
+int
+cpg_stop(void)
+{
+ pthread_cancel(cpg_thread);
+ pthread_join(cpg_thread, NULL);
+ cpg_leave(cpg_handle, &gname);
+ cpg_finalize(cpg_handle);
+
+ return 0;
+}
diff --git a/agents/virt/server/cpg.h b/agents/virt/server/cpg.h
new file mode 100644
index 0000000..6873955
--- /dev/null
+++ b/agents/virt/server/cpg.h
@@ -0,0 +1,29 @@
+#ifndef __FENCE_VIRTD_CPG_H
+#define __FENCE_VIRTD_CPG_H
+
+struct cpg_fence_req {
+ char vm_name[128];
+ int request;
+ uint32_t seqno;
+ uint32_t response;
+};
+
+typedef void (*request_callback_fn)(void *data, size_t len, uint32_t nodeid,
+ uint32_t seqno);
+typedef void (*confchange_callback_fn)(const struct cpg_address *m, size_t len);
+
+int cpg_start( const char *name,
+ request_callback_fn func,
+ request_callback_fn store_func,
+ confchange_callback_fn join,
+ confchange_callback_fn leave);
+
+int cpg_get_ids(uint32_t *me, uint32_t *high);
+int cpg_stop(void);
+int cpg_send_req(void *data, size_t len, uint32_t *seqno);
+int cpg_wait_reply(void **data, size_t *len, uint32_t seqno);
+int cpg_send_reply(void *data, size_t len, uint32_t nodeid, uint32_t seqno);
+int cpg_send_vm_state(virt_state_t *vs);
+
+
+#endif
diff --git a/agents/virt/server/daemon_init.c b/agents/virt/server/daemon_init.c
new file mode 100644
index 0000000..29b33ad
--- /dev/null
+++ b/agents/virt/server/daemon_init.c
@@ -0,0 +1,215 @@
+/** @file
+ * daemon_init function, does sanity checks and calls daemon().
+ *
+ * Author: Jeff Moyer <jmoyer@redhat.com>
+ */
+/*
+ * TODO: Clean this up so that only one function constructs the
+ * pidfile /var/run/loggerd.PID, and perhaps only one function
+ * forms the /proc/PID/ path.
+ *
+ * Also need to add file locking for the pid file.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <sys/mman.h>
+#include <sys/errno.h>
+#include <libgen.h>
+#include <signal.h>
+#include <syslog.h>
+
+
+/*
+ * This should ultimately go in a header file.
+ */
+void daemon_init(const char *prog, const char *pid_file, int nofork);
+void daemon_cleanup(void);
+int check_process_running(const char *cmd, const char *pid_file, pid_t * pid);
+
+/*
+ * Local prototypes.
+ */
+static void update_pidfile(const char *filename);
+static int setup_sigmask(void);
+static char pid_filename[PATH_MAX];
+
+static int
+check_pid_valid(pid_t pid, const char *prog)
+{
+ FILE *fp;
+ DIR *dir;
+ char filename[PATH_MAX];
+ char dirpath[PATH_MAX];
+ char proc_cmdline[64]; /* yank this from kernel somewhere */
+ char *s = NULL;
+
+ memset(filename, 0, PATH_MAX);
+ memset(dirpath, 0, PATH_MAX);
+
+ snprintf(dirpath, sizeof (dirpath), "/proc/%d", pid);
+ if ((dir = opendir(dirpath)) == NULL) {
+ return 0; /* Pid has gone away. */
+ }
+ closedir(dir);
+
+ /*
+ * proc-pid directory exists. Now check to see if this
+ * PID corresponds to the daemon we want to start.
+ */
+ snprintf(filename, sizeof (filename), "/proc/%d/cmdline", pid);
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ perror("check_pid_valid");
+ return 0; /* Who cares.... Let's boogy on. */
+ }
+
+ if (!fgets(proc_cmdline, sizeof (proc_cmdline) - 1, fp)) {
+ /*
+ * Okay, we've seen processes keep a reference to a
+ * /proc/PID/stat file and not let go. Then when
+ * you try to read /proc/PID/cmline, you get either
+ * \000 or -1. In either case, we can safely assume
+ * the process has gone away.
+ */
+ fclose(fp);
+ return 0;
+ }
+ fclose(fp);
+
+ s = &(proc_cmdline[strlen(proc_cmdline)]);
+ if (*s == '\n')
+ *s = 0;
+
+ /*
+ * Check to see if this is the same executable.
+ */
+ if (strstr(proc_cmdline, prog) == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+int
+check_process_running(const char *cmd, const char *filename, pid_t * pid)
+{
+ pid_t oldpid;
+ FILE *fp = NULL;
+ int ret;
+
+ *pid = -1;
+
+ /*
+ * Read the pid from the file.
+ */
+ fp = fopen(filename, "r");
+ if (fp == NULL) { /* error */
+ return 0;
+ }
+
+ ret = fscanf(fp, "%d\n", &oldpid);
+ fclose(fp);
+
+ if ((ret == EOF) || (ret != 1))
+ return 0;
+
+ if (check_pid_valid(oldpid, cmd)) {
+ *pid = oldpid;
+ return 1;
+ }
+ return 0;
+}
+
+
+static void
+update_pidfile(const char *filename)
+{
+ FILE *fp = NULL;
+
+ strncpy(pid_filename, filename, PATH_MAX - 1);
+
+ fp = fopen(pid_filename, "w");
+ if (fp == NULL) {
+ syslog(LOG_ERR, "daemon_init: Unable to create pidfile %s: %s\n",
+ filename, strerror(errno));
+ exit(1);
+ }
+
+ fprintf(fp, "%d", getpid());
+ fclose(fp);
+}
+
+
+static int
+setup_sigmask(void)
+{
+ sigset_t set;
+
+ sigfillset(&set);
+
+ /*
+ * Dont't block signals which would cause us to dump core.
+ */
+ sigdelset(&set, SIGQUIT);
+ sigdelset(&set, SIGILL);
+ sigdelset(&set, SIGTRAP);
+ sigdelset(&set, SIGABRT);
+ sigdelset(&set, SIGFPE);
+ sigdelset(&set, SIGSEGV);
+ sigdelset(&set, SIGBUS);
+
+ /*
+ * Don't block SIGTERM or SIGCHLD
+ */
+ sigdelset(&set, SIGTERM);
+ sigdelset(&set, SIGINT);
+ sigdelset(&set, SIGQUIT);
+ sigdelset(&set, SIGCHLD);
+
+ return (sigprocmask(SIG_BLOCK, &set, NULL));
+}
+
+
+void
+daemon_init(const char *prog, const char *pid_file, int nofork)
+{
+ pid_t pid;
+
+ if (check_process_running(prog, pid_file, &pid) && (pid != getpid())) {
+ syslog(LOG_ERR,
+ "daemon_init: Process \"%s\" already running.\n",
+ prog);
+ exit(1);
+ }
+
+ if (setup_sigmask() < 0) {
+ syslog(LOG_ERR, "daemon_init: Unable to set signal mask.\n");
+ exit(1);
+ }
+
+ if (!nofork && daemon(0, 0)) {
+ syslog(LOG_ERR, "daemon_init: Unable to daemonize.\n");
+ exit(1);
+ }
+
+ update_pidfile(pid_file);
+}
+
+
+void
+daemon_cleanup(void)
+{
+ if (strlen(pid_filename))
+ unlink(pid_filename);
+}
diff --git a/agents/virt/server/history.c b/agents/virt/server/history.c
new file mode 100644
index 0000000..bd3a68c
--- /dev/null
+++ b/agents/virt/server/history.c
@@ -0,0 +1,124 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+#include <list.h>
+#include <time.h>
+
+#include "history.h"
+
+history_info_t *
+history_init(history_compare_fn func, time_t expiration, size_t element_size)
+{
+ history_info_t *hist;
+
+ errno = EINVAL;
+ if (!func || !expiration || !element_size)
+ return NULL;
+
+ hist = malloc(sizeof(*hist));
+ if (!hist)
+ return NULL;
+ memset(hist, 0, sizeof(*hist));
+
+ hist->timeout = expiration;
+ hist->element_size = element_size;
+ hist->compare_func = func;
+
+ return hist;
+}
+
+
+/*
+ * Purge our history when the entries time out.
+ *
+ * Returns 1 if a matching history node was found, or 0
+ * if not.
+ */
+int
+history_check(history_info_t *hinfo, void *stuff)
+{
+ history_node *entry = NULL;
+ time_t now;
+ int x;
+
+ if (!hinfo)
+ return 0; /* XXX */
+
+ if (!hinfo->hist)
+ return 0;
+
+ now = time(NULL);
+
+loop_again:
+ list_for((&hinfo->hist), entry, x) {
+ if (entry->when < (now - hinfo->timeout)) {
+ list_remove((&hinfo->hist), entry);
+ free(entry->data);
+ free(entry);
+ goto loop_again;
+ }
+
+ if (hinfo->compare_func(entry->data, stuff)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+int
+history_record(history_info_t *hinfo, void *data)
+{
+ history_node *entry = NULL;
+
+ errno = EINVAL;
+ if (!data || !hinfo)
+ return -1;
+
+ if (history_check(hinfo, data) == 1) {
+ errno = EEXIST;
+ return -1;
+ }
+
+ entry = malloc(sizeof(*entry));
+ if (!entry) {
+ return -1;
+ }
+ memset(entry, 0, sizeof(*entry));
+
+ entry->data = malloc(hinfo->element_size);
+ if (!entry->data) {
+ free(entry);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ memcpy(entry->data, data, hinfo->element_size);
+ entry->when = time(NULL);
+ list_insert((&hinfo->hist), entry);
+ return 0;
+}
+
+
+int
+history_wipe(history_info_t *hinfo)
+{
+ history_node *entry = NULL;
+
+ if (!hinfo)
+ return -1;
+
+ while (hinfo->hist) {
+ entry = hinfo->hist;
+ list_remove((&hinfo->hist), entry);
+ free(entry->data);
+ free(entry);
+ }
+
+ /* User must free(hinfo); */
+ return 0;
+}
diff --git a/agents/virt/server/libvirt.c b/agents/virt/server/libvirt.c
new file mode 100644
index 0000000..8f01045
--- /dev/null
+++ b/agents/virt/server/libvirt.c
@@ -0,0 +1,359 @@
+/*
+ Copyright Red Hat, Inc. 2006-2017
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/*
+ * Author: Lon Hohberger <lhh at redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <libvirt/virterror.h>
+#include <nss.h>
+#include <libgen.h>
+#include <syslog.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "simple_auth.h"
+#include "options.h"
+#include "mcast.h"
+#include "tcp.h"
+#include "virt.h"
+#include "debug.h"
+#include "uuid-test.h"
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "server_plugin.h"
+
+#define NAME "libvirt"
+#define LIBVIRT_VERSION "0.3"
+
+#define MAGIC 0x1e19317a
+
+struct libvirt_info {
+ int magic;
+ config_object_t *config;
+ int vp_count;
+ virConnectPtr *vp;
+};
+
+#define VALIDATE(arg) \
+do {\
+ if (!arg || ((struct libvirt_info *)arg)->magic != MAGIC) { \
+ errno = EINVAL;\
+ return -1; \
+ } \
+} while(0)
+
+
+static void
+libvirt_init_libvirt_conf(struct libvirt_info *info) {
+ config_object_t *config = info->config;
+ int i = 0;
+
+ if (info->vp) {
+ dbg_printf(2, "Lost libvirtd connection. Reinitializing.\n");
+ for (i = 0 ; i < info->vp_count ; i++)
+ virConnectClose(info->vp[i]);
+ free(info->vp);
+ info->vp = NULL;
+ }
+ info->vp_count = 0;
+
+ do {
+ virConnectPtr vp;
+ virConnectPtr *vpl = NULL;
+ char conf_attr[256];
+ char value[1024];
+ char *uri;
+
+ if (i != 0) {
+ snprintf(conf_attr, sizeof(conf_attr),
+ "backends/libvirt/@uri%d", i);
+ } else
+ snprintf(conf_attr, sizeof(conf_attr), "backends/libvirt/@uri");
+ ++i;
+
+ if (sc_get(config, conf_attr, value, sizeof(value)) != 0)
+ break;
+
+ uri = value;
+ vp = virConnectOpen(uri);
+ if (!vp) {
+ dbg_printf(1, "[libvirt:INIT] Failed to connect to URI: %s\n", uri);
+ continue;
+ }
+
+ vpl = realloc(info->vp, sizeof(*info->vp) * (info->vp_count + 1));
+ if (!vpl) {
+ dbg_printf(1, "[libvirt:INIT] Out of memory allocating URI: %s\n",
+ uri);
+ virConnectClose(vp);
+ continue;
+ }
+
+ info->vp = vpl;
+ info->vp[info->vp_count++] = vp;
+
+ if (i > 1)
+ dbg_printf(1, "[libvirt:INIT] Added URI%d %s\n", i - 1, uri);
+ else
+ dbg_printf(1, "[libvirt:INIT] Added URI %s\n", uri);
+ } while (1);
+}
+
+
+static int
+libvirt_bad_connections(struct libvirt_info *info) {
+ int bad = 0;
+ int i;
+
+ for (i = 0 ; i < info->vp_count ; i++) {
+ /*
+ ** Send a dummy command to trigger an error if libvirtd
+ ** died or restarted
+ */
+ virConnectNumOfDomains(info->vp[i]);
+ if (!virConnectIsAlive(info->vp[i])) {
+ dbg_printf(1, "libvirt connection %d is dead\n", i);
+ bad++;
+ }
+ }
+
+ if (info->vp_count < 1 || bad)
+ libvirt_init_libvirt_conf(info);
+
+ return bad || info->vp_count < 1;
+}
+
+static void
+libvirt_validate_connections(struct libvirt_info *info) {
+ while (1) {
+ if (libvirt_bad_connections(info))
+ sleep(1);
+ else
+ break;
+ }
+}
+
+static int
+libvirt_null(const char *vm_name, void *priv)
+{
+ dbg_printf(5, "ENTER %s %s\n", __FUNCTION__, vm_name);
+ printf("NULL operation: returning failure\n");
+ return 1;
+}
+
+
+static int
+libvirt_off(const char *vm_name, const char *src, uint32_t seqno, void *priv)
+{
+ struct libvirt_info *info = (struct libvirt_info *)priv;
+
+ dbg_printf(5, "ENTER %s %s %u\n", __FUNCTION__, vm_name, seqno);
+ VALIDATE(info);
+
+ libvirt_validate_connections(info);
+ return vm_off(info->vp, info->vp_count, vm_name);
+}
+
+
+static int
+libvirt_on(const char *vm_name, const char *src, uint32_t seqno, void *priv)
+{
+ struct libvirt_info *info = (struct libvirt_info *)priv;
+
+ dbg_printf(5, "ENTER %s %s %u\n", __FUNCTION__, vm_name, seqno);
+ VALIDATE(info);
+
+ libvirt_validate_connections(info);
+ return vm_on(info->vp, info->vp_count, vm_name);
+}
+
+
+static int
+libvirt_devstatus(void *priv)
+{
+ dbg_printf(5, "%s ---\n", __FUNCTION__);
+
+ if (priv)
+ return 0;
+ return 1;
+}
+
+
+static int
+libvirt_status(const char *vm_name, void *priv)
+{
+ struct libvirt_info *info = (struct libvirt_info *)priv;
+
+ dbg_printf(5, "ENTER %s %s\n", __FUNCTION__, vm_name);
+ VALIDATE(info);
+
+ libvirt_validate_connections(info);
+ return vm_status(info->vp, info->vp_count, vm_name);
+}
+
+
+static int
+libvirt_reboot(const char *vm_name, const char *src, uint32_t seqno, void *priv)
+{
+ struct libvirt_info *info = (struct libvirt_info *)priv;
+
+ dbg_printf(5, "ENTER %s %s %u\n", __FUNCTION__, vm_name, seqno);
+ VALIDATE(info);
+
+ libvirt_validate_connections(info);
+ return vm_reboot(info->vp, info->vp_count, vm_name);
+}
+
+
+static int
+libvirt_hostlist(hostlist_callback callback, void *arg, void *priv)
+{
+ struct libvirt_info *info = (struct libvirt_info *)priv;
+ virt_list_t *vl;
+ int x;
+
+ dbg_printf(5, "ENTER %s\n", __FUNCTION__);
+ VALIDATE(info);
+
+ libvirt_validate_connections(info);
+
+ vl = vl_get(info->vp, info->vp_count, 1);
+ if (!vl)
+ return 0;
+
+ for (x = 0; x < vl->vm_count; x++) {
+ callback(vl->vm_states[x].v_name,
+ vl->vm_states[x].v_uuid,
+ vl->vm_states[x].v_state.s_state, arg);
+
+ dbg_printf(10, "[libvirt:HOSTLIST] Sent %s %s %d\n",
+ vl->vm_states[x].v_name,
+ vl->vm_states[x].v_uuid,
+ vl->vm_states[x].v_state.s_state);
+ }
+
+ vl_free(vl);
+ return 0;
+}
+
+
+static int
+libvirt_init(backend_context_t *c, config_object_t *config)
+{
+ char value[256];
+ struct libvirt_info *info = NULL;
+
+ dbg_printf(5, "ENTER [%s:%d %s]\n", __FILE__, __LINE__, __FUNCTION__);
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return -1;
+ info->magic = MAGIC;
+ info->config = config;
+
+ libvirt_init_libvirt_conf(info);
+
+ if (sc_get(config, "fence_virtd/@debug", value, sizeof(value)) == 0)
+ dset(atoi(value));
+
+ if (info->vp_count < 1) {
+ dbg_printf(1, "[libvirt:INIT] Could not connect to any hypervisors\n");
+ if (info->vp)
+ free(info->vp);
+ free(info);
+ return -1;
+ }
+
+ *c = (void *) info;
+ return 0;
+}
+
+
+static int
+libvirt_shutdown(backend_context_t c)
+{
+ struct libvirt_info *info = (struct libvirt_info *)c;
+ int i;
+ int ret = 0;
+
+ VALIDATE(info);
+
+ for (i = 0 ; i < info->vp_count ; i++) {
+ if (virConnectClose(info->vp[i]) < 0)
+ ret = -errno;
+ }
+
+ free(info->vp);
+ free(info);
+ return ret;
+}
+
+
+static fence_callbacks_t libvirt_callbacks = {
+ .null = libvirt_null,
+ .off = libvirt_off,
+ .on = libvirt_on,
+ .reboot = libvirt_reboot,
+ .status = libvirt_status,
+ .devstatus = libvirt_devstatus,
+ .hostlist = libvirt_hostlist
+};
+
+static backend_plugin_t libvirt_plugin = {
+ .name = NAME,
+ .version = LIBVIRT_VERSION,
+ .callbacks = &libvirt_callbacks,
+ .init = libvirt_init,
+ .cleanup = libvirt_shutdown,
+};
+
+double
+BACKEND_VER_SYM(void)
+{
+ return PLUGIN_VERSION_BACKEND;
+}
+
+const backend_plugin_t *
+BACKEND_INFO_SYM(void)
+{
+ return &libvirt_plugin;
+}
diff --git a/agents/virt/server/main.c b/agents/virt/server/main.c
new file mode 100644
index 0000000..fe57899
--- /dev/null
+++ b/agents/virt/server/main.c
@@ -0,0 +1,281 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <libgen.h>
+#include <stdint.h>
+#include <syslog.h>
+
+/* Local includes */
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "xvm.h"
+#include "server_plugin.h"
+#include "simple_auth.h"
+#include "debug.h"
+
+/* configure.c */
+int daemon_init(const char *prog, const char *pid_file, int nofork);
+int daemon_cleanup(void);
+
+
+static void
+usage(void)
+{
+ printf("Usage: fence_virtd [options]\n");
+ printf(" -F Do not daemonize.\n");
+ printf(" -f <file> Use <file> as configuration file.\n");
+ printf(" -d <level> Set debugging level to <level>.\n");
+ printf(" -c Configuration mode.\n");
+ printf(" -l List plugins.\n");
+ printf(" -w Wait for initialization.\n");
+ printf(" -p <file> Use <file> to record the active process id.\n");
+}
+
+
+static int run = 1;
+static void
+exit_handler(int sig)
+{
+ run = 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ char val[4096];
+ char listener_name[80];
+ char backend_name[80];
+ const char *config_file = SYSCONFDIR "/fence_virt.conf";
+ char *pid_file = NULL;
+ config_object_t *config = NULL;
+ map_object_t *map = NULL;
+ const listener_plugin_t *lp;
+ const backend_plugin_t *p;
+ listener_context_t listener_ctx = NULL;
+ backend_context_t backend_ctx = NULL;
+ int debug_set = 0, foreground = 0, wait_for_init = 0;
+ int opt, configure = 0;
+
+ config = sc_init();
+ map = map_init();
+
+ if (!config || !map) {
+ perror("malloc");
+ return -1;
+ }
+
+ while ((opt = getopt(argc, argv, "Ff:d:cwlhp:")) != EOF) {
+ switch(opt) {
+ case 'F':
+ printf("Background mode disabled\n");
+ foreground = 1;
+ break;
+ case 'f':
+ printf("Using %s\n", optarg);
+ config_file = optarg;
+ break;
+ case 'p':
+ printf("Using %s\n", optarg);
+ pid_file = optarg;
+ break;
+ case 'd':
+ debug_set = atoi(optarg);
+ break;
+ case 'c':
+ configure = 1;
+ break;
+ case 'w':
+ wait_for_init = 1;
+ break;
+ case 'l':
+ plugin_dump();
+ return 0;
+ case 'h':
+ case '?':
+ usage();
+ return 0;
+ default:
+ return -1;
+ }
+ }
+
+ if (configure) {
+ return do_configure(config, config_file);
+ }
+
+ if (sc_parse(config, config_file) != 0) {
+ printf("Failed to parse %s\n", config_file);
+ return -1;
+ }
+
+ if (debug_set) {
+ snprintf(val, sizeof(val), "%d", debug_set);
+ sc_set(config, "fence_virtd/@debug", val);
+ } else {
+ if (sc_get(config, "fence_virtd/@debug", val, sizeof(val))==0)
+ debug_set = atoi(val);
+ }
+
+ dset(debug_set);
+
+ if (!foreground) {
+ if (sc_get(config, "fence_virtd/@foreground",
+ val, sizeof(val)) == 0)
+ foreground = atoi(val);
+ }
+
+ if (!wait_for_init) {
+ if (sc_get(config, "fence_virtd/@wait_for_init",
+ val, sizeof(val)) == 0)
+ wait_for_init = atoi(val);
+ if (!wait_for_init) {
+ /* XXX compat */
+ if (sc_get(config, "fence_virtd/@wait_for_backend",
+ val, sizeof(val)) == 0)
+ wait_for_init = atoi(val);
+ }
+ }
+
+ if (dget() > 3)
+ sc_dump(config, stdout);
+
+ if (sc_get(config, "fence_virtd/@backend", backend_name,
+ sizeof(backend_name))) {
+ printf("Failed to determine backend.\n");
+ printf("%s\n", val);
+ return -1;
+ }
+
+ dbg_printf(1, "Backend plugin: %s\n", backend_name);
+
+ if (sc_get(config, "fence_virtd/@listener", listener_name,
+ sizeof(listener_name))) {
+ printf("Failed to determine backend.\n");
+ printf("%s\n", val);
+ return -1;
+ }
+
+ dbg_printf(1, "Listener plugin: %s\n", listener_name);
+
+ if (sc_get(config, "fence_virtd/@module_path", val,
+ sizeof(val))) {
+#ifdef MODULE_PATH
+ snprintf(val, sizeof(val), MODULE_PATH);
+#else
+ printf("Failed to determine module path.\n");
+ return -1;
+#endif
+ }
+
+ dbg_printf(1, "Searching %s for plugins...\n", val);
+
+ opt = plugin_search(val);
+ if (opt > 0) {
+ dbg_printf(1, "%d plugins found\n", opt);
+ } else {
+ printf("No plugins found\n");
+ return 1;
+ }
+
+ if (dget() > 3)
+ plugin_dump();
+
+ lp = plugin_find_listener(listener_name);
+ if (!lp) {
+ printf("Could not find listener \"%s\"\n", listener_name);
+ return 1;
+ }
+
+ p = plugin_find_backend(backend_name);
+ if (!p) {
+ printf("Could not find backend \"%s\"\n", backend_name);
+ return 1;
+ }
+
+ if (pid_file == NULL) {
+ pid_file = malloc(PATH_MAX);
+ memset(pid_file, 0, PATH_MAX);
+ snprintf(pid_file, PATH_MAX, "/var/run/%s.pid", basename(argv[0]));
+ }
+
+ if (check_file_permissions(config_file) != 0)
+ return -1;
+
+ sprintf(val, "listeners/%s/@key_file", listener_name);
+ if (sc_get(config, val,
+ val, sizeof(val)-1) == 0) {
+ dbg_printf(1, "Got %s for key_file\n", val);
+ } else {
+ snprintf(val, sizeof(val), "%s", DEFAULT_KEY_FILE);
+ }
+
+ if (check_file_permissions(val) != 0)
+ return -1;
+
+ openlog(basename(argv[0]), LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
+ daemon_init(basename(argv[0]), pid_file, foreground);
+
+ signal(SIGINT, exit_handler);
+ signal(SIGTERM, exit_handler);
+ signal(SIGQUIT, exit_handler);
+
+ syslog(LOG_NOTICE, "fence_virtd starting. Listener: %s Backend: %s",
+ listener_name, backend_name);
+
+ while (p->init(&backend_ctx, config) < 0) {
+ if (!wait_for_init || !run) {
+ if (foreground) {
+ printf("Backend plugin %s failed to initialize\n",
+ backend_name);
+ }
+ syslog(LOG_ERR,
+ "Backend plugin %s failed to initialize\n",
+ backend_name);
+ return 1;
+ }
+ sleep(5);
+ }
+
+ if (map_load(map, config) < 0) {
+ syslog(LOG_WARNING, "Failed to load static maps\n");
+ }
+
+ /* only client we have now is mcast (fence_xvm behavior) */
+ while (lp->init(&listener_ctx, p->callbacks, config, map,
+ backend_ctx) != 0) {
+ if (!wait_for_init || !run) {
+ if (foreground) {
+ printf("Listener plugin %s failed to initialize\n",
+ listener_name);
+ }
+ syslog(LOG_ERR,
+ "Listener plugin %s failed to initialize\n",
+ listener_name);
+ return 1;
+ }
+ sleep(5);
+ }
+
+ while (run && lp->dispatch(listener_ctx, NULL) >= 0);
+
+ syslog(LOG_NOTICE, "fence_virtd shutting down");
+
+ map_release(map);
+ sc_release(config);
+
+ lp->cleanup(listener_ctx);
+ p->cleanup(backend_ctx);
+
+ plugin_unload();
+ daemon_cleanup();
+
+ return 0;
+}
diff --git a/agents/virt/server/mcast.c b/agents/virt/server/mcast.c
new file mode 100644
index 0000000..a95ab37
--- /dev/null
+++ b/agents/virt/server/mcast.c
@@ -0,0 +1,622 @@
+/*
+ Copyright Red Hat, Inc. 2006
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/*
+ * Author: Lon Hohberger <lhh at redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <nss.h>
+#include <libgen.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "simple_auth.h"
+#include "options.h"
+#include "mcast.h"
+#include "tcp.h"
+#include "debug.h"
+#include "fdops.h"
+#include "list.h"
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "server_plugin.h"
+#include "history.h"
+
+#define NAME "multicast"
+#define MCAST_VERSION "1.3"
+
+#define MCAST_MAGIC 0xabb911a3
+
+#define VALIDATE(info) \
+do {\
+ if (!info || info->magic != MCAST_MAGIC)\
+ return -EINVAL;\
+} while(0)
+
+typedef struct _mcast_options {
+ char *addr;
+ char *key_file;
+ int ifindex;
+ int family;
+ unsigned int port;
+ unsigned int hash;
+ unsigned int auth;
+ unsigned int flags;
+} mcast_options;
+
+
+typedef struct _mcast_info {
+ uint64_t magic;
+ void *priv;
+ map_object_t *map;
+ history_info_t *history;
+ char key[MAX_KEY_LEN];
+ mcast_options args;
+ const fence_callbacks_t *cb;
+ ssize_t key_len;
+ int mc_sock;
+ int need_kill;
+} mcast_info;
+
+
+struct mcast_hostlist_arg {
+ map_object_t *map;
+ const char *src;
+ int fd;
+};
+
+
+/*
+ * See if we fenced this node recently (successfully)
+ * If so, ignore the request for a few seconds.
+ *
+ * We purge our history when the entries time out.
+ */
+static int
+check_history(void *a, void *b) {
+ fence_req_t *old = a, *current = b;
+
+ if (old->request == current->request &&
+ old->seqno == current->seqno &&
+ !strcasecmp((const char *)old->domain,
+ (const char *)current->domain)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+connect_tcp(fence_req_t *req, fence_auth_type_t auth,
+ void *key, size_t key_len)
+{
+ int fd = -1;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ char buf[128];
+
+ switch(req->family) {
+ case PF_INET:
+ memset(&sin, 0, sizeof(sin));
+ memcpy(&sin.sin_addr, req->address,
+ sizeof(sin.sin_addr));
+ sin.sin_family = PF_INET;
+ fd = ipv4_connect(&sin.sin_addr, req->port,
+ 5);
+ if (fd < 0) {
+ printf("Failed to call back\n");
+ return -1;
+ }
+ break;
+ case PF_INET6:
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6.sin6_addr, req->address,
+ sizeof(sin6.sin6_addr));
+ sin.sin_family = PF_INET6;
+ fd = ipv6_connect(&sin6.sin6_addr, req->port,
+ 5);
+
+ memset(buf,0,sizeof(buf));
+ inet_ntop(PF_INET6, &sin6.sin6_addr, buf, sizeof(buf));
+
+ if (fd < 0) {
+ printf("Failed to call back %s\n", buf);
+ return -1;
+ }
+ break;
+ default:
+ printf("Family = %d\n", req->family);
+ return -1;
+ }
+
+ /* Noops if auth == AUTH_NONE */
+ if (sock_response(fd, auth, key, key_len, 10) <= 0) {
+ printf("Failed to respond to challenge\n");
+ close(fd);
+ return -1;
+ }
+
+ if (sock_challenge(fd, auth, key, key_len, 10) <= 0) {
+ printf("Remote failed challenge\n");
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+
+
+static int
+mcast_hostlist(const char *vm_name, const char *vm_uuid,
+ int state, void *priv)
+{
+ struct mcast_hostlist_arg *arg = (struct mcast_hostlist_arg *)priv;
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+
+ if (map_check2(arg->map, arg->src, vm_uuid, vm_name) == 0) {
+ /* if we don't have access to fence this VM,
+ * we should not see it in a hostlist either */
+ return 0;
+ }
+
+ strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain) - 1);
+ strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid) - 1);
+ hinfo.state = state;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+
+static int
+mcast_hostlist_begin(int fd)
+{
+ struct timeval tv;
+ char val = (char)RESP_HOSTLIST;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ return _write_retry(fd, &val, 1, &tv);
+}
+
+
+static int
+mcast_hostlist_end(int fd)
+{
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+
+ printf("Sending terminator packet\n");
+
+ memset(&hinfo, 0, sizeof(hinfo));
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = _write_retry(fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+
+static int
+do_fence_request_tcp(fence_req_t *req, mcast_info *info)
+{
+ char ip_addr_src[1024];
+ int fd = -1;
+ char response = 1;
+ struct mcast_hostlist_arg arg;
+
+ fd = connect_tcp(req, info->args.auth, info->key, info->key_len);
+ if (fd < 0) {
+ dbg_printf(2, "Could not send reply to fence request: %s\n",
+ strerror(errno));
+ goto out;
+ }
+
+ inet_ntop(req->family, req->address,
+ ip_addr_src, sizeof(ip_addr_src));
+
+ dbg_printf(2, "Request %d seqno %d src %s target %s\n",
+ req->request, req->seqno, ip_addr_src, req->domain);
+
+ switch(req->request) {
+ case FENCE_NULL:
+ response = info->cb->null((char *)req->domain, info->priv);
+ break;
+ case FENCE_ON:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->on((char *)req->domain, ip_addr_src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_OFF:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->off((char *)req->domain, ip_addr_src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_REBOOT:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->reboot((char *)req->domain, ip_addr_src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_STATUS:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->status((char *)req->domain, info->priv);
+ break;
+ case FENCE_DEVSTATUS:
+ response = info->cb->devstatus(info->priv);
+ break;
+ case FENCE_HOSTLIST:
+ arg.map = info->map;
+ arg.src = ip_addr_src;
+ arg.fd = fd;
+
+ mcast_hostlist_begin(arg.fd);
+ response = info->cb->hostlist(mcast_hostlist, &arg,
+ info->priv);
+ mcast_hostlist_end(arg.fd);
+ break;
+ }
+
+ dbg_printf(3, "Sending response to caller...\n");
+ if (_write_retry(fd, &response, 1, NULL) < 0) {
+ perror("write");
+ }
+
+ /* XVM shotguns multicast packets, so we want to avoid
+ * acting on the same request multiple times if the first
+ * attempt was successful.
+ */
+ history_record(info->history, req);
+out:
+ if (fd != -1)
+ close(fd);
+
+ return 1;
+}
+
+
+static int
+mcast_dispatch(listener_context_t c, struct timeval *timeout)
+{
+ mcast_info *info;
+ fence_req_t data;
+ fd_set rfds;
+ struct sockaddr_in sin;
+ int len;
+ int n;
+ socklen_t slen;
+
+ info = (mcast_info *)c;
+ VALIDATE(info);
+
+ FD_ZERO(&rfds);
+ FD_SET(info->mc_sock, &rfds);
+
+ n = select((info->mc_sock)+1, &rfds, NULL, NULL, timeout);
+ if (n <= 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ n = 0;
+ else
+ dbg_printf(2, "select: %s\n", strerror(errno));
+ return n;
+ }
+
+ slen = sizeof(sin);
+ len = recvfrom(info->mc_sock, &data, sizeof(data), 0,
+ (struct sockaddr *)&sin, &slen);
+
+ if (len <= 0) {
+ perror("recvfrom");
+ return len;
+ }
+
+ swab_fence_req_t(&data);
+
+ if (!verify_request(&data, info->args.hash, info->key,
+ info->key_len)) {
+ printf("Key mismatch; dropping packet\n");
+ return 0;
+ }
+
+ printf("Request %d seqno %d domain %s\n", data.request, data.seqno,
+ data.domain);
+
+ if (history_check(info->history, &data) == 1) {
+ printf("We just did this request; dropping packet\n");
+ return 0;
+ }
+
+ switch(info->args.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ printf("Plain TCP request\n");
+ do_fence_request_tcp(&data, info);
+ break;
+ default:
+ printf("XXX Unhandled authentication\n");
+ }
+
+ return 0;
+}
+
+
+static int
+mcast_config(config_object_t *config, mcast_options *args)
+{
+ char value[1024];
+ int errors = 0;
+
+ if (sc_get(config, "fence_virtd/@debug", value, sizeof(value))==0)
+ dset(atoi(value));
+
+ if (sc_get(config, "listeners/multicast/@key_file",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for key_file\n", value);
+ args->key_file = strdup(value);
+ } else {
+ args->key_file = strdup(DEFAULT_KEY_FILE);
+ if (!args->key_file) {
+ dbg_printf(1, "Failed to allocate memory\n");
+ return -1;
+ }
+ }
+
+ args->hash = DEFAULT_HASH;
+ if (sc_get(config, "listeners/multicast/@hash",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for hash\n", value);
+ if (!strcasecmp(value, "none")) {
+ args->hash = HASH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->hash = HASH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->hash = HASH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->hash = HASH_SHA512;
+ } else {
+ dbg_printf(1, "Unsupported hash: %s\n", value);
+ ++errors;
+ }
+ }
+
+ args->auth = DEFAULT_AUTH;
+ if (sc_get(config, "listeners/multicast/@auth",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for auth\n", value);
+ if (!strcasecmp(value, "none")) {
+ args->auth = AUTH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->auth = AUTH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->auth = AUTH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->auth = AUTH_SHA512;
+ } else {
+ dbg_printf(1, "Unsupported auth: %s\n", value);
+ ++errors;
+ }
+ }
+
+ args->family = PF_INET;
+ if (sc_get(config, "listeners/multicast/@family",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for family\n", value);
+ if (!strcasecmp(value, "ipv4")) {
+ args->family = PF_INET;
+ } else if (!strcasecmp(value, "ipv6")) {
+ args->family = PF_INET6;
+ } else {
+ dbg_printf(1, "Unsupported family: %s\n", value);
+ ++errors;
+ }
+ }
+
+ if (sc_get(config, "listeners/multicast/@address",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for address\n", value);
+ args->addr = strdup(value);
+ } else {
+ if (args->family == PF_INET) {
+ args->addr = strdup(IPV4_MCAST_DEFAULT);
+ } else {
+ args->addr = strdup(IPV6_MCAST_DEFAULT);
+ }
+ }
+ if (!args->addr) {
+ return -1;
+ }
+
+ args->port = DEFAULT_MCAST_PORT;
+ if (sc_get(config, "listeners/multicast/@port",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for port\n", value);
+ args->port = atoi(value);
+ if (args->port <= 0) {
+ dbg_printf(1, "Invalid port: %s\n", value);
+ ++errors;
+ }
+ }
+
+ args->ifindex = 0;
+ if (sc_get(config, "listeners/multicast/@interface",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for interface\n", value);
+ args->ifindex = if_nametoindex(value);
+ if (args->ifindex < 0) {
+ dbg_printf(1, "Invalid interface: %s\n", value);
+ ++errors;
+ }
+ }
+
+ return errors;
+}
+
+
+static int
+mcast_init(listener_context_t *c, const fence_callbacks_t *cb,
+ config_object_t *config, map_object_t *map, void *priv)
+{
+ mcast_info *info;
+ int mc_sock, ret;
+
+ /* Initialize NSS; required to do hashing, as silly as that
+ sounds... */
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ printf("Could not initialize NSS\n");
+ return 1;
+ }
+
+ info = malloc(sizeof(*info));
+ if (!info)
+ return -1;
+ memset(info, 0, sizeof(*info));
+
+ info->priv = priv;
+ info->cb = cb;
+ info->map = map;
+
+ ret = mcast_config(config, &info->args);
+ if (ret < 0) {
+ perror("mcast_config");
+ free(info);
+ return -1;
+ } else if (ret > 0) {
+ printf("%d errors found during configuration\n",ret);
+ free(info);
+ return -1;
+ }
+
+ if (info->args.auth != AUTH_NONE || info->args.hash != HASH_NONE) {
+ info->key_len = read_key_file(info->args.key_file,
+ info->key, sizeof(info->key));
+ if (info->key_len < 0) {
+ printf("Could not read %s; operating without "
+ "authentication\n", info->args.key_file);
+ info->args.auth = AUTH_NONE;
+ info->args.hash = HASH_NONE;
+ info->key_len = 0;
+ }
+ }
+
+ if (info->args.family == PF_INET)
+ mc_sock = ipv4_recv_sk(info->args.addr,
+ info->args.port,
+ info->args.ifindex);
+ else
+ mc_sock = ipv6_recv_sk(info->args.addr,
+ info->args.port,
+ info->args.ifindex);
+ if (mc_sock < 0) {
+ printf("Could not set up multicast listen socket\n");
+ free(info);
+ return -1;
+ }
+
+ info->magic = MCAST_MAGIC;
+ info->mc_sock = mc_sock;
+ info->history = history_init(check_history, 10, sizeof(fence_req_t));
+ *c = (listener_context_t)info;
+ return 0;
+}
+
+
+static int
+mcast_shutdown(listener_context_t c)
+{
+ mcast_info *info = (mcast_info *)c;
+
+ VALIDATE(info);
+ info->magic = 0;
+ history_wipe(info->history);
+ free(info->history);
+ free(info->args.key_file);
+ free(info->args.addr);
+ close(info->mc_sock);
+ free(info);
+
+ return 0;
+}
+
+
+static listener_plugin_t mcast_plugin = {
+ .name = NAME,
+ .version = MCAST_VERSION,
+ .init = mcast_init,
+ .dispatch = mcast_dispatch,
+ .cleanup = mcast_shutdown,
+};
+
+double
+LISTENER_VER_SYM(void)
+{
+ return PLUGIN_VERSION_LISTENER;
+}
+
+const listener_plugin_t *
+LISTENER_INFO_SYM(void)
+{
+ return &mcast_plugin;
+}
diff --git a/agents/virt/server/plugin.c b/agents/virt/server/plugin.c
new file mode 100644
index 0000000..d9a69fb
--- /dev/null
+++ b/agents/virt/server/plugin.c
@@ -0,0 +1,417 @@
+/*
+ Copyright Red Hat, Inc. 2002-2004, 2009
+
+ The Magma Cluster API Library is free software; you can redistribute
+ it and/or modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either version
+ 2.1 of the License, or (at your option) any later version.
+
+ The Magma Cluster API Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+ */
+/** @file
+ * Plugin loading routines
+ */
+
+#include "config.h"
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <malloc.h>
+#include <string.h>
+#include <dirent.h>
+
+#include "list.h"
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "server_plugin.h"
+#include "debug.h"
+
+typedef struct _plugin_list {
+ list_head();
+ const listener_plugin_t *listener;
+ const backend_plugin_t *backend;
+ void *handle;
+ plugin_type_t type;
+} plugin_list_t;
+
+static plugin_list_t *server_plugins = NULL;
+
+
+static int
+plugin_reg_backend(void *handle, const backend_plugin_t *plugin)
+{
+ plugin_list_t *newplug;
+
+ if (plugin_find_backend(plugin->name)) {
+ errno = EEXIST;
+ return -1;
+ }
+
+ newplug = malloc(sizeof(*newplug));
+ if (!newplug)
+ return -1;
+ memset(newplug, 0, sizeof(*newplug));
+ newplug->backend = plugin;
+ newplug->type = PLUGIN_BACKEND;
+ newplug->handle = handle;
+
+ list_insert(&server_plugins, newplug);
+ return 0;
+}
+
+
+static int
+plugin_reg_listener(void *handle, const listener_plugin_t *plugin)
+{
+ plugin_list_t *newplug;
+
+ if (plugin_find_listener(plugin->name)) {
+ errno = EEXIST;
+ return -1;
+ }
+
+ newplug = malloc(sizeof(*newplug));
+ if (!newplug)
+ return -1;
+ memset(newplug, 0, sizeof(*newplug));
+ newplug->listener = plugin;
+ newplug->type = PLUGIN_LISTENER;
+ newplug->handle = handle;
+
+ list_insert(&server_plugins, newplug);
+ return 0;
+}
+
+
+void
+plugin_dump(void)
+{
+ plugin_list_t *p;
+ int x, y;
+
+ y = 0;
+ list_for(&server_plugins, p, x) {
+ if (p->type == PLUGIN_BACKEND) {
+ if (!y) {
+ y = 1;
+ printf("Available backends:\n");
+ }
+ printf(" %s %s\n",
+ p->backend->name, p->backend->version);
+ }
+ }
+
+ y = 0;
+ list_for(&server_plugins, p, x) {
+ if (p->type == PLUGIN_LISTENER) {
+ if (!y) {
+ y = 1;
+ printf("Available listeners:\n");
+ }
+ printf(" %s %s\n",
+ p->listener->name, p->listener->version);
+ }
+ }
+}
+
+
+const backend_plugin_t *
+plugin_find_backend(const char *name)
+{
+ plugin_list_t *p;
+ int x;
+
+ list_for(&server_plugins, p, x) {
+ if (p->type != PLUGIN_BACKEND)
+ continue;
+ if (!strcasecmp(name, p->backend->name))
+ return p->backend;
+ }
+
+ return NULL;
+}
+
+
+const listener_plugin_t *
+plugin_find_listener(const char *name)
+{
+ plugin_list_t *p;
+ int x;
+
+ list_for(&server_plugins, p, x) {
+ if (p->type != PLUGIN_LISTENER)
+ continue;
+ if (!strcasecmp(name, p->listener->name))
+ return p->listener;
+ }
+
+ return NULL;
+}
+
+
+static int
+backend_plugin_load(void *handle, const char *libpath)
+{
+ const backend_plugin_t *plug = NULL;
+ double (*modversion)(void);
+ backend_plugin_t *(*modinfo)(void);
+
+ modversion = dlsym(handle, BACKEND_VER_STR);
+ if (!modversion) {
+ dbg_printf(1, "Failed to map %s\n", BACKEND_VER_STR);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (modversion() != PLUGIN_VERSION_BACKEND) {
+ dbg_printf(1, "API version mismatch in %s: \n"
+ " %f expected; %f received.\n", libpath,
+ PLUGIN_VERSION_BACKEND, modversion());
+ errno = EINVAL;
+ return -1;
+ }
+
+ modinfo = dlsym(handle, BACKEND_INFO_STR);
+ if (!modinfo) {
+ dbg_printf(1, "Failed to map %s\n", BACKEND_INFO_STR);
+ errno = EINVAL;
+ return -1;
+ }
+
+ plug = modinfo();
+ if (plugin_reg_backend(handle, plug) < 0) {
+ dbg_printf(1, "Failed to register %s %s\n", plug->name,
+ plug->version);
+ errno = EINVAL;
+ return -1;
+ } else {
+ dbg_printf(1, "Registered backend plugin %s %s\n",
+ plug->name, plug->version);
+ }
+
+ return 0;
+}
+
+
+static int
+listener_plugin_load(void *handle, const char *libpath)
+{
+ const listener_plugin_t *plug = NULL;
+ double (*modversion)(void);
+ listener_plugin_t *(*modinfo)(void);
+
+ modversion = dlsym(handle, LISTENER_VER_STR);
+ if (!modversion) {
+ dbg_printf(1, "Failed to map %s\n", LISTENER_VER_STR);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (modversion() != PLUGIN_VERSION_LISTENER) {
+ dbg_printf(1, "API version mismatch in %s: \n"
+ " %f expected; %f received.\n", libpath,
+ PLUGIN_VERSION_LISTENER, modversion());
+ dlclose(handle);
+ errno = EINVAL;
+ return -1;
+ }
+
+ modinfo = dlsym(handle, LISTENER_INFO_STR);
+ if (!modinfo) {
+ dbg_printf(1, "Failed to map %s\n", LISTENER_INFO_STR);
+ errno = EINVAL;
+ return -1;
+ }
+
+ plug = modinfo();
+ if (plugin_reg_listener(handle, plug) < 0) {
+ dbg_printf(1, "Failed to register %s %s\n", plug->name,
+ plug->version);
+ errno = EINVAL;
+ return -1;
+ } else {
+ dbg_printf(1, "Registered listener plugin %s %s\n",
+ plug->name, plug->version);
+ }
+
+ return 0;
+}
+
+
+/**
+ * Load a cluster plugin .so file and map all the functions
+ * provided to entries in a backend_plugin_t structure.
+ *
+ * @param libpath Path to file.
+ * @return NULL on failure, or plugin-specific
+ * (const) backend_plugin_t * structure on
+ * success.
+ */
+int
+plugin_load(const char *libpath)
+{
+ void *handle = NULL;
+
+ errno = 0;
+
+ if (!libpath) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ dbg_printf(3, "Loading plugin from %s\n", libpath);
+ handle = dlopen(libpath, RTLD_NOW);
+ if (!handle) {
+ dbg_printf(3, "Could not dlopen %s: %s\n", libpath, dlerror());
+ errno = ELIBACC;
+ return -1;
+ }
+
+ if (!backend_plugin_load(handle, libpath) ||
+ !listener_plugin_load(handle, libpath))
+ return 0;
+
+ dbg_printf(3, "%s is not a valid plugin\n", libpath);
+ dlclose(handle);
+ errno = EINVAL;
+ return -1;
+}
+
+void
+plugin_unload(void)
+{
+ plugin_list_t *p;
+ int x;
+
+ list_for(&server_plugins, p, x) {
+ dlclose(p->handle);
+ }
+}
+
+/**
+ Free up a null-terminated array of strings
+ */
+static void
+free_dirnames(char **dirnames)
+{
+ int x = 0;
+
+ for (; dirnames[x]; x++)
+ free(dirnames[x]);
+
+ free(dirnames);
+}
+
+
+static int
+_compare(const void *a, const void *b)
+{
+ return strcmp((const char *)a, (const char *)b);
+}
+
+
+/**
+ Read all entries in a directory and return them in a NULL-terminated,
+ sorted array.
+ */
+static int
+read_dirnames_sorted(const char *directory, char ***dirnames)
+{
+ DIR *dir;
+ struct dirent *entry;
+ char filename[1024];
+ int count = 0, x = 0;
+
+ dir = opendir(directory);
+ if (!dir)
+ return -1;
+
+ /* Count the number of plugins */
+ while ((entry = readdir(dir)) != NULL)
+ ++count;
+
+ /* Malloc the entries */
+ *dirnames = malloc(sizeof(char *) * (count+1));
+ if (!*dirnames) {
+#ifdef DEBUG
+ printf("%s: Failed to malloc %d bytes",
+ __FUNCTION__, (int)(sizeof(char *) * (count+1)));
+#endif
+ closedir(dir);
+ errno = ENOMEM;
+ return -1;
+ }
+ memset(*dirnames, 0, sizeof(char *) * (count + 1));
+ rewinddir(dir);
+
+ /* Store the directory names. */
+ while ((entry = readdir(dir)) != NULL) {
+ snprintf(filename, sizeof(filename), "%s/%s", directory,
+ entry->d_name);
+
+ (*dirnames)[x] = strdup(filename);
+ if (!(*dirnames)[x]) {
+#ifdef DEBUG
+ printf("Failed to duplicate %s\n",
+ filename);
+#endif
+ free_dirnames(*dirnames);
+ closedir(dir);
+ errno = ENOMEM;
+ return -1;
+ }
+ ++x;
+ }
+
+ closedir(dir);
+
+ /* Sort the directory names. */
+ qsort((*dirnames), count, sizeof(char *), _compare);
+
+ return 0;
+}
+
+
+/**
+ */
+int
+plugin_search(const char *pathname)
+{
+ int found = 0;
+ int fcount = 0;
+ char **filenames;
+
+ dbg_printf(1, "Searching for plugins in %s\n", pathname);
+ if (read_dirnames_sorted(pathname, &filenames) != 0) {
+ return -1;
+ }
+
+ for (fcount = 0; filenames[fcount]; fcount++) {
+
+ if (plugin_load(filenames[fcount]) == 0)
+ ++found;
+ }
+
+ free_dirnames(filenames);
+ if (!found) {
+ dbg_printf(1, "No usable plugins found.\n");
+ errno = ELIBACC;
+ return -1;
+ }
+
+ return found;
+}
diff --git a/agents/virt/server/serial.c b/agents/virt/server/serial.c
new file mode 100644
index 0000000..bde8218
--- /dev/null
+++ b/agents/virt/server/serial.c
@@ -0,0 +1,459 @@
+/*
+ Copyright Red Hat, Inc. 2010
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+/*
+ * Author: Lon Hohberger <lhh at redhat.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <nss.h>
+#include <libgen.h>
+
+/* Local includes */
+#include "debug.h"
+#include "fdops.h"
+#include "serial.h"
+#include "list.h"
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "server_plugin.h"
+#include "history.h"
+#include "xvm.h"
+
+#define NAME "serial"
+#define SERIAL_VERSION "0.5"
+
+#define SERIAL_PLUG_MAGIC 0x1227a000
+
+#define VALIDATE(info) \
+do {\
+ if (!info || info->magic != SERIAL_PLUG_MAGIC)\
+ return -EINVAL;\
+} while(0)
+
+
+typedef struct _serial_info {
+ uint64_t magic;
+ const fence_callbacks_t *cb;
+ void *priv;
+ char *uri;
+ char *path;
+ history_info_t *history;
+ map_object_t *maps;
+ int mode;
+ int wake_fd;
+} serial_info;
+
+
+struct serial_hostlist_arg {
+ map_object_t *map;
+ const char *src;
+ int fd;
+};
+
+
+/*
+ * See if we fenced this node recently (successfully)
+ * If so, ignore the request for a few seconds.
+ *
+ * We purge our history when the entries time out.
+ */
+static int
+check_history(void *a, void *b) {
+ serial_req_t *old = a, *current = b;
+
+ if (old->request == current->request &&
+ old->seqno == current->seqno &&
+ !strcasecmp((const char *)old->domain,
+ (const char *)current->domain)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+serial_hostlist(const char *vm_name, const char *vm_uuid,
+ int state, void *priv)
+{
+ struct serial_hostlist_arg *arg = (struct serial_hostlist_arg *)priv;
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+
+ if (map_check2(arg->map, arg->src, vm_uuid, vm_name) == 0) {
+ /* if we don't have access to fence this VM,
+ * we should not see it in a hostlist either */
+ return 0;
+ }
+
+ strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain) - 1);
+ strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid) - 1);
+ hinfo.state = state;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+
+static int
+serial_hostlist_begin(int fd)
+{
+ struct timeval tv;
+ serial_resp_t resp;
+
+ resp.magic = SERIAL_MAGIC;
+ resp.response = RESP_HOSTLIST;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ return _write_retry(fd, &resp, sizeof(resp), &tv);
+}
+
+
+static int
+serial_hostlist_end(int fd)
+{
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+
+ //printf("Sending terminator packet\n");
+
+ memset(&hinfo, 0, sizeof(hinfo));
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = _write_retry(fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+
+static int
+do_fence_request(int fd, const char *src, serial_req_t *req, serial_info *info)
+{
+ char response = RESP_FAIL;
+ struct serial_hostlist_arg arg;
+ serial_resp_t resp;
+
+ arg.fd = fd;
+
+ switch(req->request) {
+ case FENCE_NULL:
+ response = info->cb->null((char *)req->domain, info->priv);
+ break;
+ case FENCE_ON:
+ if (map_check(info->maps, src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->on((char *)req->domain, src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_OFF:
+ if (map_check(info->maps, src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->off((char *)req->domain, src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_REBOOT:
+ if (map_check(info->maps, src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->reboot((char *)req->domain, src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_STATUS:
+ if (map_check(info->maps, src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->status((char *)req->domain, info->priv);
+ break;
+ case FENCE_DEVSTATUS:
+ response = info->cb->devstatus(info->priv);
+ break;
+ case FENCE_HOSTLIST:
+ arg.map = info->maps;
+ arg.src = src;
+ arg.fd = fd;
+
+ serial_hostlist_begin(arg.fd);
+ response = info->cb->hostlist(serial_hostlist, &arg,
+ info->priv);
+ serial_hostlist_end(arg.fd);
+ break;
+ }
+
+ resp.magic = SERIAL_MAGIC;
+ resp.response = response;
+ swab_serial_resp_t(&resp);
+
+ dbg_printf(3, "Sending response to caller...\n");
+ if (_write_retry(fd, &resp, sizeof(resp), NULL) < 0)
+ perror("write");
+
+ /* XVM shotguns multicast packets, so we want to avoid
+ * acting on the same request multiple times if the first
+ * attempt was successful.
+ */
+ history_record(info->history, req);
+
+ return 1;
+}
+
+
+static int
+serial_dispatch(listener_context_t c, struct timeval *timeout)
+{
+ char src_domain[MAX_DOMAINNAME_LENGTH];
+ serial_info *info;
+ serial_req_t data;
+ fd_set rfds;
+ struct timeval tv;
+ int max;
+ int n, x, ret;
+
+ info = (serial_info *)c;
+ VALIDATE(info);
+
+ FD_ZERO(&rfds);
+ domain_sock_fdset(&rfds, &max);
+ FD_SET(info->wake_fd, &rfds);
+ if (info->wake_fd > max)
+ max = info->wake_fd;
+
+ n = select(max+1, &rfds, NULL, NULL, timeout);
+ if (n < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ n = 0;
+ else
+ dbg_printf(2, "select: %s\n", strerror(errno));
+ return n;
+ }
+
+ /*
+ * See if the goal was just to be woken up in order to refill our
+ * file descriptor set. For example, if multiple domains were
+ * created simultaneously, we would have to refill our fd_set
+ */
+ if (FD_ISSET(info->wake_fd, &rfds)) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ _read_retry(info->wake_fd, &c, 1, &tv);
+ return 0;
+ }
+
+ /*
+ * If no requests, we're done
+ */
+ if (n == 0)
+ return 0;
+
+ /* find & read request */
+ for (x = 0; x <= max; x++) {
+ if (FD_ISSET(x, &rfds)) {
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ ret = _read_retry(x, &data, sizeof(data), &tv);
+
+ if (ret != sizeof(data)) {
+ if (--n > 0)
+ continue;
+ else
+ return 0;
+ } else {
+ swab_serial_req_t(&data);
+ break;
+ }
+ }
+ }
+
+ src_domain[0] = 0;
+ domain_sock_name(x, src_domain, sizeof(src_domain));
+
+ dbg_printf(2, "Sock %d Request %d seqno %d src %s target %s\n", x,
+ data.request, data.seqno, src_domain, data.domain);
+
+ if (history_check(info->history, &data) == 1) {
+ dbg_printf(3, "We just did this request; dropping packet\n");
+ return 0;
+ }
+
+ do_fence_request(x, src_domain[0] == 0 ? NULL : src_domain,
+ &data, info);
+
+ return 0;
+}
+
+
+static int
+serial_config(config_object_t *config, serial_info *args)
+{
+ char value[1024];
+ int errors = 0;
+
+ if (sc_get(config, "fence_virtd/@debug", value, sizeof(value))==0)
+ dset(atoi(value));
+
+ if (sc_get(config, "listeners/serial/@uri",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for uri\n", value);
+ args->uri = strdup(value);
+ }
+
+ if (sc_get(config, "listeners/serial/@path",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for path\n", value);
+ args->path = strdup(value);
+ }
+
+ if (sc_get(config, "listeners/serial/@mode",
+ value, sizeof(value)-1) == 0) {
+ if (!strcasecmp(value, "vmchannel")) {
+ args->mode = 1;
+ } else if (!strcasecmp(value, "serial")) {
+ args->mode = 0;
+ } else {
+ args->mode = atoi(value);
+ if (args->mode < 0)
+ args->mode = 0;
+ }
+
+ dbg_printf(1, "Got %s for mode\n",
+ args->mode?"VMChannel":"serial");
+
+ }
+
+ return errors;
+}
+
+
+static int
+serial_init(listener_context_t *c, const fence_callbacks_t *cb,
+ config_object_t *config, map_object_t *map, void *priv)
+{
+ serial_info *info;
+ int ret;
+
+ info = malloc(sizeof(*info));
+ if (!info)
+ return -1;
+ memset(info, 0, sizeof(*info));
+
+ info->priv = priv;
+ info->cb = cb;
+
+ ret = serial_config(config, info);
+ if (ret < 0) {
+ perror("serial_config");
+ return -1;
+ } else if (ret > 0) {
+ printf("%d errors found during configuration\n",ret);
+ return -1;
+ }
+
+ info->maps = map;
+
+ info->magic = SERIAL_PLUG_MAGIC;
+ info->history = history_init(check_history, 10, sizeof(fence_req_t));
+ *c = (listener_context_t)info;
+ start_event_listener(info->uri, info->path, info->mode, &info->wake_fd);
+ sleep(1);
+
+ return 0;
+}
+
+
+static int
+serial_shutdown(listener_context_t c)
+{
+ serial_info *info = (serial_info *)c;
+
+ dbg_printf(3, "Shutting down serial\n");
+
+ VALIDATE(info);
+ info->magic = 0;
+ stop_event_listener();
+ domain_sock_cleanup();
+ history_wipe(info->history);
+ free(info->history);
+ free(info->uri);
+ free(info->path);
+ free(info);
+
+ return 0;
+}
+
+
+static listener_plugin_t serial_plugin = {
+ .name = NAME,
+ .version = SERIAL_VERSION,
+ .init = serial_init,
+ .dispatch = serial_dispatch,
+ .cleanup = serial_shutdown,
+};
+
+double
+LISTENER_VER_SYM(void)
+{
+ return PLUGIN_VERSION_LISTENER;
+}
+
+const listener_plugin_t *
+LISTENER_INFO_SYM(void)
+{
+ return &serial_plugin;
+}
diff --git a/agents/virt/server/serial.h b/agents/virt/server/serial.h
new file mode 100644
index 0000000..481400a
--- /dev/null
+++ b/agents/virt/server/serial.h
@@ -0,0 +1,20 @@
+#ifndef __VIRT_SERIAL_H
+#define __VIRT_SERIAL_H
+
+#include <sys/select.h>
+
+/* virt-sockets.c */
+int domain_sock_setup(const char *domain, const char *socket_path);
+int domain_sock_close(const char *domain);
+int domain_sock_fdset(fd_set *set, int *max);
+
+/* Find the domain name associated with a FD */
+int domain_sock_name(int fd, char *outbuf, size_t buflen);
+int domain_sock_cleanup(void);
+
+/* virt-serial.c - event thread control functions */
+int start_event_listener(const char *uri, const char *path, int mode, int *wake_fd);
+int stop_event_listener(void);
+
+
+#endif
diff --git a/agents/virt/server/static_map.c b/agents/virt/server/static_map.c
new file mode 100644
index 0000000..7bdc400
--- /dev/null
+++ b/agents/virt/server/static_map.c
@@ -0,0 +1,237 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "list.h"
+#include "debug.h"
+#include "serial.h"
+#include "uuid-test.h"
+
+struct perm_entry {
+ list_head();
+ char name[129];
+};
+
+struct perm_group {
+ list_head();
+ struct perm_entry *uuids;
+ struct perm_entry *ips;
+ char name[129];
+};
+
+
+static void
+static_map_cleanup(void **info)
+{
+ struct perm_group *groups = (struct perm_group *)(*info);
+ struct perm_group *group;
+ struct perm_entry *entry;
+
+ while (groups) {
+ group = groups;
+ list_remove(&groups, group);
+ while (group->uuids) {
+ entry = group->uuids;
+ list_remove(&group->uuids, entry);
+ free(entry);
+ }
+ while (group->ips) {
+ entry = group->ips;
+ list_remove(&group->ips, entry);
+ free(entry);
+ }
+ free(group);
+ }
+
+ *info = NULL;
+}
+
+
+static int
+static_map_check(void *info, const char *src, const char *tgt_uuid, const char *tgt_name)
+{
+ struct perm_group *groups = (struct perm_group *)info;
+ struct perm_group *group;
+ struct perm_entry *left, *tmp;
+ int x, y, uuid = 0;
+
+ if (!info)
+ return 1; /* no maps == wide open */
+
+ dbg_printf(99, "[server:map_check] map request: src: %s uuid: %s name: %s\n", src, tgt_uuid, tgt_name);
+
+ uuid = is_uuid(src);
+
+ list_for(&groups, group, x) {
+ left = NULL;
+
+ if (uuid) {
+ list_for(&group->uuids, tmp, y) {
+ if (!strcasecmp(tmp->name, src)) {
+ left = tmp;
+ break;
+ }
+ }
+ } else {
+ list_for(&group->ips, tmp, y) {
+ if (!strcasecmp(tmp->name, src)) {
+ left = tmp;
+ break;
+ }
+ }
+ }
+
+ if (!left)
+ continue;
+
+ list_for(&group->uuids, tmp, y) {
+ if (!strcasecmp(tmp->name, tgt_uuid)) {
+ return 1;
+ }
+ /* useful only for list */
+ if (tgt_name) {
+ if (!strcasecmp(tmp->name, tgt_name)) {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+static_map_load(void *config_ptr, void **perm_info)
+{
+ config_object_t *config = config_ptr;
+ int group_idx = 0;
+ int entry_idx = 0;
+ int found;
+ char value[128];
+ char buf[256];
+ char buf2[512];
+ struct perm_group *group = NULL, *groups = NULL;
+ struct perm_entry *entry = NULL;
+
+ if (!perm_info)
+ return -1;
+
+ do {
+ snprintf(buf, sizeof(buf)-1, "groups/group[%d]", ++group_idx);
+
+ if (sc_get(config, buf, value, sizeof(value)) != 0) {
+ snprintf(buf2, sizeof(buf2)-1, "%s/@uuid", buf);
+ if (sc_get(config, buf2, value, sizeof(value)) != 0) {
+ snprintf(buf2, sizeof(buf2)-1, "%s/@ip", buf);
+ if (sc_get(config, buf2, value,
+ sizeof(value)) != 0) {
+ break;
+ }
+ }
+ snprintf(buf2, sizeof(buf2)-1, "%s/@name", buf);
+ if (sc_get(config, buf2, value, sizeof(value)) != 0) {
+ snprintf(value, sizeof(value), "unnamed-%d",
+ group_idx);
+ }
+ }
+
+ group = malloc(sizeof(*group));
+ assert(group);
+ memset(group, 0, sizeof(*group));
+ strncpy(group->name, value, sizeof(group->name));
+ dbg_printf(3, "Group: %s\n", value);
+
+ found = 0;
+ entry_idx = 0;
+ do {
+ snprintf(buf2, sizeof(buf2)-1, "%s/@uuid[%d]",
+ buf, ++entry_idx);
+
+ if (sc_get(config, buf2, value, sizeof(value)) != 0) {
+ break;
+ }
+
+ ++found;
+ entry = malloc(sizeof(*entry));
+ assert(entry);
+ memset(entry, 0, sizeof(*entry));
+ strncpy(entry->name, value, sizeof(entry->name));
+ dbg_printf(3, " - UUID Entry: %s\n", value);
+
+ list_insert(&group->uuids, entry);
+
+ } while (1);
+
+ entry_idx = 0;
+ do {
+ snprintf(buf2, sizeof(buf2)-1, "%s/@ip[%d]",
+ buf, ++entry_idx);
+
+ if (sc_get(config, buf2, value, sizeof(value)) != 0) {
+ break;
+ }
+
+ ++found;
+ entry = malloc(sizeof(*entry));
+ assert(entry);
+ memset(entry, 0, sizeof(*entry));
+ strncpy(entry->name, value, sizeof(entry->name));
+ dbg_printf(3, " - IP Entry: %s\n", value);
+
+ list_insert(&group->ips, entry);
+
+ } while (1);
+
+
+ if (!found)
+ free(group);
+ else
+ list_insert(&groups, group);
+
+ } while (1);
+
+ *perm_info = groups;
+
+ return 0;
+}
+
+
+static const map_object_t static_map_obj = {
+ .load = static_map_load,
+ .check = static_map_check,
+ .cleanup = static_map_cleanup,
+ .info = NULL
+};
+
+
+void *
+map_init(void)
+{
+ map_object_t *o;
+
+ o = malloc(sizeof(*o));
+ if (!o)
+ return NULL;
+ memset(o, 0, sizeof(*o));
+ memcpy(o, &static_map_obj, sizeof(*o));
+
+ return (void *)o;
+}
+
+
+void
+map_release(void *c)
+{
+ map_object_t *o = (map_object_t *)c;
+
+ static_map_cleanup(&o->info);
+ free(c);
+}
diff --git a/agents/virt/server/tcp.c b/agents/virt/server/tcp.c
new file mode 100644
index 0000000..c1fb60c
--- /dev/null
+++ b/agents/virt/server/tcp.c
@@ -0,0 +1,575 @@
+/*
+ Copyright Red Hat, Inc. 2006-2012
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#include "config.h"
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <nss.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+/* Local includes */
+#include "xvm.h"
+#include "simple_auth.h"
+#include "options.h"
+#include "mcast.h"
+#include "tcp.h"
+#include "tcp_listener.h"
+#include "debug.h"
+#include "fdops.h"
+#include "list.h"
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "server_plugin.h"
+#include "history.h"
+
+#define NAME "tcp"
+#define TCP_VERSION "0.2"
+
+#define TCP_MAGIC 0xc3dff7a9
+
+#define VALIDATE(info) \
+do {\
+ if (!info || info->magic != TCP_MAGIC)\
+ return -EINVAL;\
+} while(0)
+
+typedef struct _tcp_options {
+ char *key_file;
+ char *addr;
+ int family;
+ unsigned int port;
+ unsigned int hash;
+ unsigned int auth;
+ unsigned int flags;
+} tcp_options;
+
+
+typedef struct _tcp_info {
+ uint64_t magic;
+ void *priv;
+ map_object_t *map;
+ history_info_t *history;
+ char key[MAX_KEY_LEN];
+ tcp_options args;
+ const fence_callbacks_t *cb;
+ ssize_t key_len;
+ int listen_sock;
+} tcp_info;
+
+
+struct tcp_hostlist_arg {
+ map_object_t *map;
+ const char *src;
+ int fd;
+};
+
+
+/*
+ * See if we fenced this node recently (successfully)
+ * If so, ignore the request for a few seconds.
+ *
+ * We purge our history when the entries time out.
+ */
+static int
+check_history(void *a, void *b) {
+ fence_req_t *old = a, *current = b;
+
+ if (old->request == current->request &&
+ old->seqno == current->seqno &&
+ !strcasecmp((const char *)old->domain,
+ (const char *)current->domain)) {
+ return 1;
+ }
+ return 0;
+}
+
+static int
+tcp_hostlist(const char *vm_name, const char *vm_uuid,
+ int state, void *priv)
+{
+ struct tcp_hostlist_arg *arg = (struct tcp_hostlist_arg *)priv;
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+
+ if (map_check2(arg->map, arg->src, vm_uuid, vm_name) == 0) {
+ /* if we don't have access to fence this VM,
+ * we should not see it in a hostlist either */
+ return 0;
+ }
+
+ strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain) - 1);
+ strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid) - 1);
+ hinfo.state = state;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+
+static int
+tcp_hostlist_begin(int fd)
+{
+ struct timeval tv;
+ char val = (char)RESP_HOSTLIST;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ return _write_retry(fd, &val, 1, &tv);
+}
+
+
+static int
+tcp_hostlist_end(int fd)
+{
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+
+ printf("Sending terminator packet\n");
+
+ memset(&hinfo, 0, sizeof(hinfo));
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = _write_retry(fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+static socklen_t
+sockaddr_len(const struct sockaddr_storage *ss)
+{
+ if (ss->ss_family == AF_INET) {
+ return sizeof(struct sockaddr_in);
+ } else {
+ return sizeof(struct sockaddr_in6);
+ }
+}
+
+static int
+do_fence_request_tcp(int fd, struct sockaddr_storage *ss, socklen_t sock_len, fence_req_t *req, tcp_info *info)
+{
+ char ip_addr_src[1024];
+ char response = 1;
+ struct tcp_hostlist_arg arg;
+ int ret;
+
+ /* Noops if auth == AUTH_NONE */
+ if (sock_response(fd, info->args.auth, info->key, info->key_len, 10) <= 0) {
+ printf("Failed to respond to challenge\n");
+ close(fd);
+ return -1;
+ }
+
+ ret = sock_challenge(fd, info->args.auth, info->key, info->key_len, 10);
+ if (ret <= 0) {
+ printf("Remote failed challenge\n");
+ close(fd);
+ return -1;
+ }
+
+
+ if (getnameinfo((struct sockaddr *)ss, sockaddr_len(ss),
+ ip_addr_src, sizeof(ip_addr_src),
+ NULL, 0,
+ NI_NUMERICHOST | NI_NUMERICSERV) < 0) {
+ printf("Unable to resolve!\n");
+ close(fd);
+ return -1;
+ }
+
+ dbg_printf(2, "Request %d seqno %d src %s target %s\n",
+ req->request, req->seqno, ip_addr_src, req->domain);
+
+ switch(req->request) {
+ case FENCE_NULL:
+ response = info->cb->null((char *)req->domain, info->priv);
+ break;
+ case FENCE_ON:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->on((char *)req->domain, ip_addr_src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_OFF:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->off((char *)req->domain, ip_addr_src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_REBOOT:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->reboot((char *)req->domain, ip_addr_src,
+ req->seqno, info->priv);
+ break;
+ case FENCE_STATUS:
+ if (map_check(info->map, ip_addr_src,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->status((char *)req->domain, info->priv);
+ break;
+ case FENCE_DEVSTATUS:
+ response = info->cb->devstatus(info->priv);
+ break;
+ case FENCE_HOSTLIST:
+ arg.map = info->map;
+ arg.src = ip_addr_src;
+ arg.fd = fd;
+
+ tcp_hostlist_begin(arg.fd);
+ response = info->cb->hostlist(tcp_hostlist, &arg,
+ info->priv);
+ tcp_hostlist_end(arg.fd);
+ break;
+ }
+
+ dbg_printf(3, "Sending response to caller...\n");
+ if (_write_retry(fd, &response, 1, NULL) < 0) {
+ perror("write");
+ }
+
+ history_record(info->history, req);
+
+ if (fd != -1)
+ close(fd);
+
+ return 1;
+}
+
+
+static int
+tcp_dispatch(listener_context_t c, struct timeval *timeout)
+{
+ tcp_info *info;
+ fence_req_t data;
+ fd_set rfds;
+ int n;
+ int client_fd;
+ int ret;
+ struct timeval tv;
+ struct sockaddr_storage ss;
+ socklen_t sock_len = sizeof(ss);
+
+ if (timeout != NULL)
+ memcpy(&tv, timeout, sizeof(tv));
+ else {
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ }
+
+ info = (tcp_info *)c;
+ VALIDATE(info);
+
+ FD_ZERO(&rfds);
+ FD_SET(info->listen_sock, &rfds);
+
+ n = select(info->listen_sock + 1, &rfds, NULL, NULL, timeout);
+ if (n <= 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ n = 0;
+ else
+ dbg_printf(2, "select: %s\n", strerror(errno));
+ return n;
+ }
+
+ client_fd = accept(info->listen_sock, (struct sockaddr *)&ss, &sock_len);
+ if (client_fd < 0) {
+ perror("accept");
+ return -1;
+ }
+
+ dbg_printf(3, "Accepted client...\n");
+
+ ret = _read_retry(client_fd, &data, sizeof(data), &tv);
+ if (ret != sizeof(data)) {
+ dbg_printf(3, "Invalid request (read %d bytes)\n", ret);
+ close(client_fd);
+ return 0;
+ }
+
+ swab_fence_req_t(&data);
+
+ if (!verify_request(&data, info->args.hash, info->key,
+ info->key_len)) {
+ printf("Key mismatch; dropping client\n");
+ close(client_fd);
+ return 0;
+ }
+
+ dbg_printf(3, "Request %d seqno %d domain %s\n",
+ data.request, data.seqno, data.domain);
+
+ if (history_check(info->history, &data) == 1) {
+ printf("We just did this request; dropping client\n");
+ close(client_fd);
+ return 0;
+ }
+
+ switch(info->args.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ printf("Plain TCP request\n");
+ do_fence_request_tcp(client_fd, &ss, sock_len, &data, info);
+ break;
+ default:
+ printf("XXX Unhandled authentication\n");
+ }
+
+ return 0;
+}
+
+
+static int
+tcp_config(config_object_t *config, tcp_options *args)
+{
+ char value[1024];
+ int errors = 0;
+
+ if (sc_get(config, "fence_virtd/@debug", value, sizeof(value))==0)
+ dset(atoi(value));
+
+ if (sc_get(config, "listeners/tcp/@key_file",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for key_file\n", value);
+ args->key_file = strdup(value);
+ } else {
+ args->key_file = strdup(DEFAULT_KEY_FILE);
+ if (!args->key_file) {
+ dbg_printf(1, "Failed to allocate memory\n");
+ return -1;
+ }
+ }
+
+ args->hash = DEFAULT_HASH;
+ if (sc_get(config, "listeners/tcp/@hash",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for hash\n", value);
+ if (!strcasecmp(value, "none")) {
+ args->hash = HASH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->hash = HASH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->hash = HASH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->hash = HASH_SHA512;
+ } else {
+ dbg_printf(1, "Unsupported hash: %s\n", value);
+ ++errors;
+ }
+ }
+
+ args->auth = DEFAULT_AUTH;
+ if (sc_get(config, "listeners/tcp/@auth",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for auth\n", value);
+ if (!strcasecmp(value, "none")) {
+ args->hash = AUTH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->hash = AUTH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->hash = AUTH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->hash = AUTH_SHA512;
+ } else {
+ dbg_printf(1, "Unsupported auth: %s\n", value);
+ ++errors;
+ }
+ }
+
+ args->family = PF_INET;
+ if (sc_get(config, "listeners/tcp/@family",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for family\n", value);
+ if (!strcasecmp(value, "ipv4")) {
+ args->family = PF_INET;
+ } else if (!strcasecmp(value, "ipv6")) {
+ args->family = PF_INET6;
+ } else {
+ dbg_printf(1, "Unsupported family: %s\n", value);
+ ++errors;
+ }
+ }
+
+ if (sc_get(config, "listeners/tcp/@address",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for address\n", value);
+ args->addr = strdup(value);
+ } else {
+ if (args->family == PF_INET) {
+ args->addr = strdup(IPV4_TCP_ADDR_DEFAULT);
+ } else {
+ args->addr = strdup(IPV6_TCP_ADDR_DEFAULT);
+ }
+ }
+ if (!args->addr) {
+ return -1;
+ }
+
+ args->port = DEFAULT_MCAST_PORT;
+ if (sc_get(config, "listeners/tcp/@port",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for port\n", value);
+ args->port = atoi(value);
+ if (args->port <= 0) {
+ dbg_printf(1, "Invalid port: %s\n", value);
+ ++errors;
+ }
+ }
+
+ return errors;
+}
+
+
+static int
+tcp_init(listener_context_t *c, const fence_callbacks_t *cb,
+ config_object_t *config, map_object_t *map, void *priv)
+{
+ tcp_info *info;
+ int listen_sock, ret;
+
+ /* Initialize NSS; required to do hashing, as silly as that
+ sounds... */
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ printf("Could not initialize NSS\n");
+ return 1;
+ }
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return -1;
+
+ info->priv = priv;
+ info->cb = cb;
+ info->map = map;
+
+ ret = tcp_config(config, &info->args);
+ if (ret < 0)
+ perror("tcp_config");
+ else if (ret > 0)
+ printf("%d errors found during configuration\n",ret);
+
+ if (ret != 0) {
+ if (info->args.key_file)
+ free(info->args.key_file);
+ if (info->args.addr)
+ free(info->args.addr);
+ free(info);
+ return -1;
+ }
+
+ if (info->args.auth != AUTH_NONE || info->args.hash != HASH_NONE) {
+ info->key_len = read_key_file(info->args.key_file,
+ info->key, sizeof(info->key));
+ if (info->key_len < 0) {
+ printf("Could not read %s; operating without "
+ "authentication\n", info->args.key_file);
+ info->args.auth = AUTH_NONE;
+ info->args.hash = HASH_NONE;
+ info->key_len = 0;
+ }
+ }
+
+ if (info->args.family == PF_INET) {
+ listen_sock = ipv4_listen(info->args.addr, info->args.port, 10);
+ } else {
+ listen_sock = ipv6_listen(info->args.addr, info->args.port, 10);
+ }
+
+ if (listen_sock < 0) {
+ printf("Could not set up listen socket\n");
+ if (info->args.key_file)
+ free(info->args.key_file);
+ if (info->args.addr)
+ free(info->args.addr);
+ free(info);
+ return -1;
+ }
+
+ info->magic = TCP_MAGIC;
+ info->listen_sock = listen_sock;
+ info->history = history_init(check_history, 10, sizeof(fence_req_t));
+ *c = (listener_context_t)info;
+ return 0;
+}
+
+
+static int
+tcp_shutdown(listener_context_t c)
+{
+ tcp_info *info = (tcp_info *)c;
+
+ VALIDATE(info);
+ info->magic = 0;
+ history_wipe(info->history);
+ free(info->history);
+ free(info->args.key_file);
+ free(info->args.addr);
+ close(info->listen_sock);
+ free(info);
+
+ return 0;
+}
+
+
+static listener_plugin_t tcp_plugin = {
+ .name = NAME,
+ .version = TCP_VERSION,
+ .init = tcp_init,
+ .dispatch = tcp_dispatch,
+ .cleanup = tcp_shutdown,
+};
+
+double
+LISTENER_VER_SYM(void)
+{
+ return PLUGIN_VERSION_LISTENER;
+}
+
+const listener_plugin_t *
+LISTENER_INFO_SYM(void)
+{
+ return &tcp_plugin;
+}
diff --git a/agents/virt/server/uuid-test.c b/agents/virt/server/uuid-test.c
new file mode 100644
index 0000000..3116ef9
--- /dev/null
+++ b/agents/virt/server/uuid-test.c
@@ -0,0 +1,66 @@
+#include "config.h"
+
+#include <uuid/uuid.h>
+#include <errno.h>
+#include <string.h>
+
+#include "uuid-test.h"
+
+int
+is_uuid(const char *value)
+{
+ uuid_t id;
+ char test_value[37];
+
+ if (strlen(value) < 36) {
+ return 0;
+ }
+
+ memset(id, 0, sizeof(uuid_t));
+
+ if (uuid_is_null(id) < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (uuid_parse(value, id) < 0) {
+ return 0;
+ }
+
+ memset(test_value, 0, sizeof(test_value));
+ uuid_unparse(id, test_value);
+
+ if (strcasecmp(value, test_value)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifdef STANDALONE
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+
+ if (argc < 2) {
+ printf("Usage: uuidtest <value>\n");
+ return 1;
+ }
+
+ ret = is_uuid(argv[1]);
+ if (ret == 0) {
+ printf("%s is NOT a uuid\n", argv[1]);
+ } else if (ret == 1) {
+ printf("%s is a uuid\n", argv[1]);
+ } else {
+ printf("Error: %s\n", strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/agents/virt/server/uuid-test.h b/agents/virt/server/uuid-test.h
new file mode 100644
index 0000000..164fec7
--- /dev/null
+++ b/agents/virt/server/uuid-test.h
@@ -0,0 +1,14 @@
+#ifndef __UUID_TEST_H
+#define __UUID_TEST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int is_uuid(const char *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/agents/virt/server/virt-serial.c b/agents/virt/server/virt-serial.c
new file mode 100644
index 0000000..6b369bc
--- /dev/null
+++ b/agents/virt/server/virt-serial.c
@@ -0,0 +1,444 @@
+// #include <config.h>
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <libvirt/libvirt.h>
+
+#include <libxml/xmlreader.h>
+
+#include "simpleconfig.h"
+#include "debug.h"
+
+#define DEBUG0(fmt) dbg_printf(5,"%s:%d :: " fmt "\n", \
+ __func__, __LINE__)
+#define DEBUG1(fmt, ...) dbg_printf(5, "%s:%d: " fmt "\n", \
+ __func__, __LINE__, __VA_ARGS__)
+
+#include "serial.h"
+
+#define STREQ(a,b) (strcmp((a),(b)) == 0)
+
+static pthread_t event_tid = 0;
+static int run = 0;
+
+/* Prototypes */
+const char *eventToString(int event);
+int myDomainEventCallback1(virConnectPtr conn, virDomainPtr dom,
+ int event, int detail, void *opaque);
+
+void usage(const char *pname);
+
+struct domain_info {
+ virDomainPtr dom;
+ virDomainEventType event;
+};
+
+static int
+is_in_directory(const char *dir, const char *pathspec)
+{
+ char *last_slash = NULL;
+ size_t dirlen, pathlen;
+
+ if (!dir || !pathspec)
+ return 0;
+
+ dirlen = strlen(dir);
+ pathlen = strlen(pathspec);
+
+ /*
+ printf("dirlen = %d pathlen = %d\n",
+ dirlen, pathlen);
+ */
+
+ /* chop off trailing slashes */
+ while (dirlen && dir[dirlen-1]=='/')
+ --dirlen;
+
+ /* chop off leading slashes */
+ while (dirlen && dir[0] == '/') {
+ ++dir;
+ --dirlen;
+ }
+
+ /* chop off leading slashes */
+ while (pathlen && pathspec[0] == '/') {
+ ++pathspec;
+ --pathlen;
+ }
+
+ if (!dirlen || !pathlen)
+ return 0;
+
+ if (pathlen <= dirlen)
+ return 0;
+
+ last_slash = strrchr(pathspec, '/');
+
+ if (!last_slash)
+ return 0;
+
+ while (*last_slash == '/' && last_slash > pathspec)
+ --last_slash;
+
+ if (last_slash == pathspec)
+ return 0;
+
+ pathlen = last_slash - pathspec + 1;
+ /*printf("real dirlen = %d real pathlen = %d\n",
+ dirlen, pathlen);*/
+ if (pathlen != dirlen)
+ return 0;
+
+ /* todo - intelligently skip multiple slashes mid-path */
+ return !strncmp(dir, pathspec, dirlen);
+}
+
+
+static int
+domainStarted(virDomainPtr mojaDomain, const char *path, int mode)
+{
+ char dom_uuid[42];
+ char *xml;
+ xmlDocPtr doc;
+ xmlNodePtr cur, devices, child, serial;
+ xmlAttrPtr attr, attr_mode, attr_path;
+
+ if (!mojaDomain)
+ return -1;
+
+ virDomainGetUUIDString(mojaDomain, dom_uuid);
+
+ xml = virDomainGetXMLDesc(mojaDomain, 0);
+ // printf("%s\n", xml);
+ // @todo: free mojaDomain
+
+ // parseXML output
+ doc = xmlParseMemory(xml, strlen(xml));
+ xmlFree(xml);
+ cur = xmlDocGetRootElement(doc);
+
+ if (cur == NULL) {
+ fprintf(stderr, "Empty doc\n");
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) "domain")) {
+ fprintf(stderr, "no domain?\n");
+ xmlFreeDoc(doc);
+ return -1;
+ }
+
+ devices = cur->xmlChildrenNode;
+ for (devices = cur->xmlChildrenNode; devices != NULL;
+ devices = devices->next) {
+ if (xmlStrcmp(devices->name, (const xmlChar *) "devices")) {
+ continue;
+ }
+
+ for (child = devices->xmlChildrenNode; child != NULL;
+ child = child->next) {
+
+ if ((!mode && xmlStrcmp(child->name, (const xmlChar *) "serial")) ||
+ (mode && xmlStrcmp(child->name, (const xmlChar *) "channel"))) {
+ continue;
+ }
+
+ attr = xmlHasProp(child, (const xmlChar *)"type");
+ if (attr == NULL)
+ continue;
+
+ if (xmlStrcmp(attr->children->content,
+ (const xmlChar *) "unix")) {
+ continue;
+ }
+
+ for (serial = child->xmlChildrenNode; serial != NULL;
+ serial = serial->next) {
+ if (xmlStrcmp(serial->name,
+ (const xmlChar *) "source")) {
+ continue;
+ }
+
+ attr_mode = xmlHasProp(serial, (const xmlChar *)"mode");
+ attr_path = xmlHasProp(serial, (const xmlChar *)"path");
+
+ if (!attr_path || !attr_mode)
+ continue;
+
+ if (xmlStrcmp(attr_mode->children->content,
+ (const xmlChar *) "bind"))
+ continue;
+
+ if (path && !is_in_directory(path, (const char *)
+ attr_path->children->content))
+ continue;
+
+ domain_sock_setup(dom_uuid, (const char *)
+ attr_path->children->content);
+ }
+ }
+ }
+
+ xmlFreeDoc(doc);
+ return 0;
+}
+
+static int
+registerExisting(virConnectPtr vp, const char *path, int mode)
+{
+ int *d_ids = NULL;
+ int d_count, x;
+ virDomainPtr dom;
+ virDomainInfo d_info;
+
+ errno = EINVAL;
+ if (!vp)
+ return -1;
+
+ d_count = virConnectNumOfDomains(vp);
+ if (d_count <= 0) {
+ if (d_count == 0) {
+ /* Successful, but no domains running */
+ errno = 0;
+ return 0;
+ }
+ goto out_fail;
+ }
+
+ d_ids = malloc(sizeof (int) * d_count);
+ if (!d_ids)
+ goto out_fail;
+
+ if (virConnectListDomains(vp, d_ids, d_count) < 0)
+ goto out_fail;
+
+ /* Ok, we have the domain IDs - let's get their names and states */
+ for (x = 0; x < d_count; x++) {
+ dom = virDomainLookupByID(vp, d_ids[x]);
+ if (!dom) {
+ /* XXX doom */
+ goto out_fail;
+ }
+
+ if (virDomainGetInfo(dom, &d_info) < 0) {
+ /* XXX no info for the domain?!! */
+ virDomainFree(dom);
+ goto out_fail;
+ }
+
+ if (d_info.state != VIR_DOMAIN_SHUTOFF &&
+ d_info.state != VIR_DOMAIN_CRASHED)
+ domainStarted(dom, path, mode);
+
+ virDomainFree(dom);
+ }
+
+ out_fail:
+ free(d_ids);
+ return 0;
+}
+
+static int
+domainStopped(virDomainPtr mojaDomain)
+{
+ char dom_uuid[42];
+
+ if (!mojaDomain)
+ return -1;
+
+ virDomainGetUUIDString(mojaDomain, dom_uuid);
+ domain_sock_close(dom_uuid);
+
+ return 0;
+}
+
+
+struct event_args {
+ char *uri;
+ char *path;
+ int mode;
+ int wake_fd;
+};
+
+static void
+connectClose(virConnectPtr conn ATTRIBUTE_UNUSED,
+ int reason,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ switch (reason) {
+ case VIR_CONNECT_CLOSE_REASON_ERROR:
+ dbg_printf(2, "Connection closed due to I/O error\n");
+ break;
+ case VIR_CONNECT_CLOSE_REASON_EOF:
+ dbg_printf(2, "Connection closed due to end of file\n");
+ break;
+ case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
+ dbg_printf(2, "Connection closed due to keepalive timeout\n");
+ break;
+ case VIR_CONNECT_CLOSE_REASON_CLIENT:
+ dbg_printf(2, "Connection closed due to client request\n");
+ break;
+ default:
+ dbg_printf(2, "Connection closed due to unknown reason\n");
+ break;
+ };
+ run = 0;
+}
+
+int
+myDomainEventCallback1(virConnectPtr conn,
+ virDomainPtr dom, int event, int detail, void *opaque)
+{
+ struct event_args *args = (struct event_args *)opaque;
+
+ if (event == VIR_DOMAIN_EVENT_STARTED ||
+ event == VIR_DOMAIN_EVENT_STOPPED) {
+ virDomainRef(dom);
+ if (event == VIR_DOMAIN_EVENT_STARTED) {
+ domainStarted(dom, args->path, args->mode);
+ virDomainFree(dom);
+ if (write(args->wake_fd, "x", 1) != 1) {
+ dbg_printf(3, "Unable to wake up thread\n");
+ }
+ } else if (event == VIR_DOMAIN_EVENT_STOPPED) {
+ domainStopped(dom);
+ virDomainFree(dom);
+ }
+ }
+
+ return 0;
+}
+
+
+static void *
+event_thread(void *arg)
+{
+ struct event_args *args = (struct event_args *)arg;
+ virConnectPtr dconn = NULL;
+ int callback1ret = -1;
+
+ dbg_printf(3, "Libvirt event listener starting\n");
+ if (args->uri)
+ dbg_printf(3," * URI: %s\n", args->uri);
+ if (args->path)
+ dbg_printf(3," * Socket path: %s\n", args->path);
+ dbg_printf(3," * Mode: %s\n", args->mode ? "VMChannel" : "Serial");
+
+ if (virEventRegisterDefaultImpl() < 0) {
+ dbg_printf(1, "Failed to register default event impl\n");
+ goto out;
+ }
+
+ dconn = virConnectOpen(args->uri);
+ if (!dconn) {
+ dbg_printf(1, "Error connecting to libvirt\n");
+ goto out;
+ }
+
+ virConnectRegisterCloseCallback(dconn, connectClose, NULL, NULL);
+
+ DEBUG0("Registering domain event cbs");
+
+ registerExisting(dconn, args->path, args->mode);
+
+ callback1ret =
+ virConnectDomainEventRegister(dconn, myDomainEventCallback1, arg, NULL);
+
+ if (callback1ret != -1) {
+ if (virConnectSetKeepAlive(dconn, 5, 5) < 0) {
+ dbg_printf(1, "Failed to start keepalive protocol\n");
+ run = 0;
+ }
+ while (run) {
+ if (virEventRunDefaultImpl() < 0) {
+ dbg_printf(1, "RunDefaultImpl Failed\n");
+ }
+ }
+
+ DEBUG0("Deregistering event handlers");
+ virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
+ }
+
+ DEBUG0("Closing connection");
+ if (dconn && virConnectClose(dconn) < 0) {
+ dbg_printf(1, "error closing libvirt connection\n");
+ }
+
+out:
+ free(args->uri);
+ free(args->path);
+ free(args);
+ return NULL;
+}
+
+
+int
+start_event_listener(const char *uri, const char *path, int mode, int *wake_fd)
+{
+ struct event_args *args = NULL;
+ int wake_pipe[2];
+
+ virInitialize();
+
+ args = malloc(sizeof(*args));
+ if (!args)
+ return -1;
+ memset(args, 0, sizeof(*args));
+
+ if (pipe2(wake_pipe, O_CLOEXEC) < 0) {
+ goto out_fail;
+ }
+
+ if (uri) {
+ args->uri = strdup(uri);
+ if (args->uri == NULL)
+ goto out_fail;
+ }
+
+ if (path) {
+ args->path = strdup(path);
+ if (args->path == NULL)
+ goto out_fail;
+ }
+
+ args->mode = mode;
+ //args->p_tid = pthread_self();
+ *wake_fd = wake_pipe[0];
+ args->wake_fd = wake_pipe[1];
+
+ run = 1;
+
+ return pthread_create(&event_tid, NULL, event_thread, args);
+
+out_fail:
+ free(args->uri);
+ free(args->path);
+ free(args);
+ return -1;
+}
+
+
+int
+stop_event_listener(void)
+{
+ run = 0;
+ //pthread_cancel(event_tid);
+ pthread_join(event_tid, NULL);
+ event_tid = 0;
+
+ return 0;
+}
+
+
diff --git a/agents/virt/server/virt-sockets.c b/agents/virt/server/virt-sockets.c
new file mode 100644
index 0000000..7f36f62
--- /dev/null
+++ b/agents/virt/server/virt-sockets.c
@@ -0,0 +1,242 @@
+#include "config.h"
+
+#include <pthread.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <list.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "serial.h"
+#include "debug.h"
+#include "simpleconfig.h"
+
+struct socket_list {
+ list_head();
+ char *domain_name;
+ char *socket_path;
+ int socket_fd;
+};
+
+static struct socket_list *socks = NULL;
+static pthread_mutex_t sock_list_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+static int
+connect_nb(int fd, struct sockaddr *dest, socklen_t len, int timeout)
+{
+ int ret, flags, err;
+ unsigned l;
+ fd_set rfds, wfds;
+ struct timeval tv;
+
+ /*
+ Set up non-blocking connect
+ */
+ flags = fcntl(fd, F_GETFL, 0);
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ return -1;
+ }
+
+ ret = connect(fd, dest, len);
+
+ if ((ret < 0) && (errno != EINPROGRESS))
+ return -1;
+
+ if (ret == 0)
+ goto done;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ if (select(fd + 1, &rfds, &wfds, NULL, &tv) == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ if (!FD_ISSET(fd, &rfds) && !FD_ISSET(fd, &wfds)) {
+ errno = EIO;
+ return -1;
+ }
+
+ l = sizeof(err);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR,
+ (void *)&err, &l) < 0) {
+ return -1;
+ }
+
+ if (err != 0) {
+ errno = err;
+ return -1;
+ }
+
+done:
+ if (fcntl(fd, F_SETFL, flags) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+
+int
+domain_sock_setup(const char *domain, const char *socket_path)
+{
+ struct sockaddr_un *sun = NULL;
+ struct socket_list *node = NULL;
+ socklen_t sun_len;
+ int sock = -1;
+
+ sun_len = sizeof(*sun) + strlen(socket_path) + 1;
+ sun = malloc(sun_len);
+ if (!sun)
+ return -1;
+
+ memset((char *)sun, 0, sun_len);
+ sun->sun_family = PF_LOCAL;
+ strncpy(sun->sun_path, socket_path, sizeof(sun->sun_path) - 1);
+
+ sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0)
+ goto out_fail;
+
+ if (connect_nb(sock, (struct sockaddr *)sun, SUN_LEN(sun), 3) < 0)
+ goto out_fail;
+
+ free(sun);
+ sun = NULL;
+
+ node = calloc(1, sizeof(*node));
+ if (!node)
+ goto out_fail;
+
+ node->domain_name = strdup(domain);
+ if (!node->domain_name)
+ goto out_fail;
+
+ node->socket_path = strdup(socket_path);
+ if (!node->socket_path)
+ goto out_fail;
+
+ node->socket_fd = sock;
+
+ pthread_mutex_lock(&sock_list_mutex);
+ list_insert(&socks, node);
+ pthread_mutex_unlock(&sock_list_mutex);
+
+ dbg_printf(3, "Registered %s on %d\n", domain, sock);
+ return 0;
+
+out_fail:
+ if (node) {
+ free(node->domain_name);
+ if (node->socket_path)
+ free(node->socket_path);
+ free(node);
+ }
+ free(sun);
+ if (sock >= 0)
+ close(sock);
+ return -1;
+}
+
+
+int
+domain_sock_close(const char *domain)
+{
+ struct socket_list *node = NULL;
+ struct socket_list *dead = NULL;
+ int x;
+
+ pthread_mutex_lock(&sock_list_mutex);
+ list_for(&socks, node, x) {
+ if (!strcasecmp(domain, node->domain_name)) {
+ list_remove(&socks, node);
+ dead = node;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&sock_list_mutex);
+
+ if (dead) {
+ dbg_printf(3, "Unregistered %s, fd%d\n",
+ dead->domain_name,
+ dead->socket_fd);
+ close(dead->socket_fd);
+ free(dead->domain_name);
+ free(dead->socket_path);
+ free(dead);
+ }
+
+ return 0;
+}
+
+
+int
+domain_sock_fdset(fd_set *fds, int *max)
+{
+ struct socket_list *node = NULL;
+ int x = 0, _max = -1;
+
+ pthread_mutex_lock(&sock_list_mutex);
+ list_for(&socks, node, x) {
+ FD_SET(node->socket_fd, fds);
+ if (node->socket_fd > _max)
+ _max = node->socket_fd;
+ }
+ pthread_mutex_unlock(&sock_list_mutex);
+
+ if (max)
+ *max = _max;
+
+ return x;
+}
+
+
+int
+domain_sock_name(int fd, char *outbuf, size_t buflen)
+{
+ struct socket_list *node = NULL;
+ int ret = 1, x = 0;
+
+ pthread_mutex_lock(&sock_list_mutex);
+ list_for(&socks, node, x) {
+ if (node->socket_fd == fd) {
+ snprintf(outbuf, buflen, "%s", node->domain_name);
+ ret = 0;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&sock_list_mutex);
+
+ return ret;
+}
+
+
+int
+domain_sock_cleanup(void)
+{
+ struct socket_list *dead= NULL;
+
+ pthread_mutex_lock(&sock_list_mutex);
+ while(socks) {
+ dead = socks;
+ list_remove(&socks, dead);
+ close(dead->socket_fd);
+ free(dead->domain_name);
+ free(dead->socket_path);
+ free(dead);
+ }
+ pthread_mutex_unlock(&sock_list_mutex);
+
+ return 0;
+}
+
diff --git a/agents/virt/server/virt.c b/agents/virt/server/virt.c
new file mode 100644
index 0000000..d4c94e9
--- /dev/null
+++ b/agents/virt/server/virt.c
@@ -0,0 +1,630 @@
+/*
+ Copyright Red Hat, Inc. 2006-2017
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <libvirt/libvirt.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include "debug.h"
+#include "uuid-test.h"
+#include "virt.h"
+
+static int
+_compare_virt(const void *_left, const void *_right)
+{
+ virt_state_t *left = (virt_state_t *)_left,
+ *right = (virt_state_t *)_right;
+
+ return strcasecmp(left->v_name, right->v_name);
+}
+
+
+static void
+_free_dom_list(virDomainPtr *dom_list, int len) {
+ int x;
+
+ if (!dom_list || len <= 0)
+ return;
+ for (x = 0 ; x < len; x++)
+ virDomainFree(dom_list[x]);
+
+ free(dom_list);
+}
+
+
+virt_list_t *vl_get(virConnectPtr *vp, int vp_count, int my_id)
+{
+ virt_list_t *vl = NULL;
+ int d_count = 0;
+ int i;
+
+ errno = EINVAL;
+ if (!vp || vp_count < 1)
+ return NULL;
+
+ for (i = 0 ; i < vp_count ; i++) {
+ int x;
+ virDomainPtr *dom_list;
+ virt_list_t *new_vl;
+
+ int ret = virConnectListAllDomains(vp[i], &dom_list, 0);
+ if (ret == 0)
+ continue;
+
+ if (ret < 0) {
+ int saved_errno = errno;
+ dbg_printf(2, "Error: virConnectListAllDomains: %d %d\n",
+ ret, saved_errno);
+ if (vl)
+ free(vl);
+ errno = saved_errno;
+ return NULL;
+ }
+
+ d_count += ret;
+ new_vl = realloc(vl, sizeof(uint32_t) + sizeof(virt_state_t) * d_count);
+ if (!new_vl) {
+ _free_dom_list(dom_list, ret);
+ free(vl);
+ return NULL;
+ }
+ vl = new_vl;
+ vl->vm_count = d_count;
+
+ /* Ok, we have the domain IDs - let's get their names and states */
+ for (x = 0; x < ret; x++) {
+ char *d_name;
+ virDomainInfo d_info;
+ char d_uuid[MAX_DOMAINNAME_LENGTH];
+ virDomainPtr dom = dom_list[x];
+
+ if (!(d_name = (char *)virDomainGetName(dom))) {
+ _free_dom_list(dom_list, ret);
+ free(vl);
+ return NULL;
+ }
+
+ if (virDomainGetUUIDString(dom, d_uuid) != 0) {
+ _free_dom_list(dom_list, ret);
+ free(vl);
+ return NULL;
+ }
+
+ if (virDomainGetInfo(dom, &d_info) < 0) {
+ _free_dom_list(dom_list, ret);
+ free(vl);
+ return NULL;
+ }
+
+ /* Store the name & state */
+ strncpy(vl->vm_states[x].v_name, d_name, MAX_DOMAINNAME_LENGTH);
+ strncpy(vl->vm_states[x].v_uuid, d_uuid, MAX_DOMAINNAME_LENGTH);
+ vl->vm_states[x].v_state.s_state = d_info.state;
+ vl->vm_states[x].v_state.s_owner = my_id;
+ }
+
+ _free_dom_list(dom_list, ret);
+ }
+ /* No domains found */
+ if (!vl)
+ return NULL;
+
+ /* We have all the locally running domains & states now */
+ /* Sort */
+ qsort(&vl->vm_states[0], vl->vm_count, sizeof(vl->vm_states[0]),
+ _compare_virt);
+ return vl;
+}
+
+int
+vl_add(virt_list_t **vl, virt_state_t *vm) {
+ virt_list_t *new_vl;
+ size_t oldlen;
+ size_t newlen;
+
+ if (!vl)
+ return -1;
+
+ if (!*vl) {
+ *vl = malloc(sizeof(uint32_t) + sizeof(virt_state_t));
+ if (!*vl)
+ return -1;
+ (*vl)->vm_count = 1;
+ memcpy(&(*vl)->vm_states[0], vm, sizeof(virt_state_t));
+ return 0;
+ }
+
+ oldlen = sizeof(uint32_t) + sizeof(virt_state_t) * (*vl)->vm_count;
+ newlen = oldlen + sizeof(virt_state_t);
+
+ new_vl = malloc(newlen);
+ if (!new_vl)
+ return -1;
+
+ memcpy(new_vl, *vl, oldlen);
+ memcpy(&new_vl->vm_states[(*vl)->vm_count], vm, sizeof(virt_state_t));
+ new_vl->vm_count++;
+
+ free(*vl);
+ *vl = new_vl;
+ return 0;
+}
+
+int vl_remove_by_owner(virt_list_t **vl, uint32_t owner) {
+ int i;
+ int removed = 0;
+ virt_list_t *new_vl;
+
+ if (!vl || !*vl)
+ return 0;
+
+ for (i = 0 ; i < (*vl)->vm_count ; i++) {
+ if ((*vl)->vm_states[i].v_state.s_owner == owner) {
+ dbg_printf(2, "Removing %s\n", (*vl)->vm_states[i].v_name);
+ memset(&(*vl)->vm_states[i].v_state, 0,
+ sizeof((*vl)->vm_states[i].v_state));
+ (*vl)->vm_states[i].v_name[0] = 0xff;
+ (*vl)->vm_states[i].v_uuid[0] = 0xff;
+ removed++;
+ }
+ }
+
+ if (!removed)
+ return 0;
+
+ qsort(&(*vl)->vm_states[0], (*vl)->vm_count, sizeof((*vl)->vm_states[0]),
+ _compare_virt);
+ (*vl)->vm_count -= removed;
+
+ new_vl = realloc(*vl, sizeof(uint32_t) + (sizeof(virt_state_t) * ((*vl)->vm_count)));
+ if (new_vl)
+ *vl = new_vl;
+ return removed;
+}
+
+
+int
+vl_update(virt_list_t **vl, virt_state_t *vm) {
+ virt_state_t *v = NULL;
+
+ if (!vl)
+ return -1;
+
+ if (!*vl)
+ return vl_add(vl, vm);
+
+ if (strlen(vm->v_uuid) > 0)
+ v = vl_find_uuid(*vl, vm->v_uuid);
+
+ if (v == NULL && strlen(vm->v_name) > 0)
+ v = vl_find_name(*vl, vm->v_name);
+
+ if (v == NULL) {
+ dbg_printf(2, "Adding new entry for VM %s\n", vm->v_name);
+ vl_add(vl, vm);
+ } else {
+ dbg_printf(2, "Updating entry for VM %s\n", vm->v_name);
+ memcpy(&v->v_state, &vm->v_state, sizeof(v->v_state));
+ }
+
+ return 0;
+}
+
+
+void
+vl_print(virt_list_t *vl)
+{
+ int x;
+
+ printf("%-24.24s %-36.36s %-5.5s %-5.5s\n", "Domain", "UUID",
+ "Owner", "State");
+ printf("%-24.24s %-36.36s %-5.5s %-5.5s\n", "------", "----",
+ "-----", "-----");
+
+ if (!vl || !vl->vm_count)
+ return;
+
+ for (x = 0; x < vl->vm_count; x++) {
+ printf("%-24.24s %-36.36s %-5.5d %-5.5d\n",
+ vl->vm_states[x].v_name,
+ vl->vm_states[x].v_uuid,
+ vl->vm_states[x].v_state.s_owner,
+ vl->vm_states[x].v_state.s_state);
+ }
+}
+
+
+virt_state_t *
+vl_find_name(virt_list_t *vl, const char *name)
+{
+ int x;
+
+ if (!vl || !name || !vl->vm_count)
+ return NULL;
+
+ for (x = 0; x < vl->vm_count; x++) {
+ if (!strcasecmp(vl->vm_states[x].v_name, name))
+ return &vl->vm_states[x];
+ }
+
+ return NULL;
+}
+
+
+virt_state_t *
+vl_find_uuid(virt_list_t *vl, const char *uuid)
+{
+ int x;
+
+ if (!vl || !uuid || !vl->vm_count)
+ return NULL;
+
+ for (x = 0; x < vl->vm_count; x++) {
+ if (!strcasecmp(vl->vm_states[x].v_uuid, uuid))
+ return &vl->vm_states[x];
+ }
+
+ return NULL;
+}
+
+
+void
+vl_free(virt_list_t *old)
+{
+ free(old);
+}
+
+
+static inline int
+wait_domain(const char *vm_name, virConnectPtr vp, int timeout)
+{
+ int tries = 0;
+ int response = 1;
+ int ret;
+ virDomainPtr vdp;
+ virDomainInfo vdi;
+ int uuid_check;
+
+ uuid_check = is_uuid(vm_name);
+
+ if (uuid_check) {
+ vdp = virDomainLookupByUUIDString(vp, (const char *)vm_name);
+ } else {
+ vdp = virDomainLookupByName(vp, vm_name);
+ }
+ if (!vdp)
+ return 0;
+
+ /* Check domain liveliness. If the domain is still here,
+ we return failure, and the client must then retry */
+ /* XXX On the xen 3.0.4 API, we will be able to guarantee
+ synchronous virDomainDestroy, so this check will not
+ be necessary */
+ do {
+ if (++tries > timeout)
+ break;
+
+ sleep(1);
+ if (uuid_check) {
+ vdp = virDomainLookupByUUIDString(vp, (const char *)vm_name);
+ } else {
+ vdp = virDomainLookupByName(vp, vm_name);
+ }
+ if (!vdp) {
+ dbg_printf(2, "Domain no longer exists\n");
+ response = 0;
+ break;
+ }
+
+ memset(&vdi, 0, sizeof(vdi));
+ ret = virDomainGetInfo(vdp, &vdi);
+ virDomainFree(vdp);
+ if (ret < 0)
+ continue;
+
+ if (vdi.state == VIR_DOMAIN_SHUTOFF) {
+ dbg_printf(2, "Domain has been shut off\n");
+ response = 0;
+ break;
+ }
+
+ dbg_printf(4, "Domain still exists (state %d) after %d seconds\n",
+ vdi.state, tries);
+ } while (1);
+
+ return response;
+}
+
+
+int
+vm_off(virConnectPtr *vp, int vp_count, const char *vm_name)
+{
+ virDomainPtr vdp = NULL;
+ virDomainInfo vdi;
+ virDomainPtr (*virt_lookup_fn)(virConnectPtr, const char *);
+ int ret = -1;
+ int i;
+
+ if (is_uuid(vm_name))
+ virt_lookup_fn = virDomainLookupByUUIDString;
+ else
+ virt_lookup_fn = virDomainLookupByName;
+
+ for (i = 0 ; i < vp_count ; i++) {
+ vdp = virt_lookup_fn(vp[i], vm_name);
+ if (vdp)
+ break;
+ }
+
+ if (!vdp) {
+ dbg_printf(2, "[virt:OFF] Domain %s does not exist\n", vm_name);
+ return 1;
+ }
+
+ if (virDomainGetInfo(vdp, &vdi) == 0 && vdi.state == VIR_DOMAIN_SHUTOFF)
+ {
+ dbg_printf(2, "[virt:OFF] Nothing to do - "
+ "domain %s is already off\n",
+ vm_name);
+ virDomainFree(vdp);
+ return 0;
+ }
+
+ syslog(LOG_NOTICE, "Destroying domain %s\n", vm_name);
+ dbg_printf(2, "[virt:OFF] Calling virDomainDestroy for %s\n", vm_name);
+
+ ret = virDomainDestroy(vdp);
+ virDomainFree(vdp);
+
+ if (ret < 0) {
+ syslog(LOG_NOTICE,
+ "Failed to destroy domain %s: %d\n", vm_name, ret);
+ dbg_printf(2, "[virt:OFF] Failed to destroy domain: %s %d\n",
+ vm_name, ret);
+ return 1;
+ }
+
+ if (ret) {
+ syslog(LOG_NOTICE, "Domain %s still exists; fencing failed\n",
+ vm_name);
+ dbg_printf(2,
+ "[virt:OFF] Domain %s still exists; fencing failed\n",
+ vm_name);
+ return 1;
+ }
+
+ dbg_printf(2, "[virt:OFF] Success for %s\n", vm_name);
+ return 0;
+}
+
+
+int
+vm_on(virConnectPtr *vp, int vp_count, const char *vm_name)
+{
+ virDomainPtr vdp = NULL;
+ virDomainInfo vdi;
+ virDomainPtr (*virt_lookup_fn)(virConnectPtr, const char *);
+ int ret = -1;
+ int i;
+
+ if (is_uuid(vm_name))
+ virt_lookup_fn = virDomainLookupByUUIDString;
+ else
+ virt_lookup_fn = virDomainLookupByName;
+
+ for (i = 0 ; i < vp_count ; i++) {
+ vdp = virt_lookup_fn(vp[i], vm_name);
+ if (vdp)
+ break;
+ }
+
+ if (!vdp) {
+ dbg_printf(2, "[virt:ON] Domain %s does not exist\n", vm_name);
+ return 1;
+ }
+
+ if (virDomainGetInfo(vdp, &vdi) == 0 && vdi.state != VIR_DOMAIN_SHUTOFF) {
+ dbg_printf(2, "Nothing to do - domain %s is already running\n",
+ vm_name);
+ virDomainFree(vdp);
+ return 0;
+ }
+
+ syslog(LOG_NOTICE, "Starting domain %s\n", vm_name);
+ dbg_printf(2, "[virt:ON] Calling virDomainCreate for %s\n", vm_name);
+
+ ret = virDomainCreate(vdp);
+ virDomainFree(vdp);
+
+ if (ret < 0) {
+ syslog(LOG_NOTICE, "Failed to start domain %s: %d\n", vm_name, ret);
+ dbg_printf(2, "[virt:ON] virDomainCreate() failed for %s: %d\n",
+ vm_name, ret);
+ return 1;
+ }
+
+ if (ret) {
+ syslog(LOG_NOTICE, "Domain %s did not start\n", vm_name);
+ dbg_printf(2, "[virt:ON] Domain %s did not start\n", vm_name);
+ return 1;
+ }
+
+ syslog(LOG_NOTICE, "Domain %s started\n", vm_name);
+ dbg_printf(2, "[virt:ON] Success for %s\n", vm_name);
+ return 0;
+}
+
+
+int
+vm_status(virConnectPtr *vp, int vp_count, const char *vm_name)
+{
+ virDomainPtr vdp = NULL;
+ virDomainInfo vdi;
+ int ret = 0;
+ int i;
+ virDomainPtr (*virt_lookup_fn)(virConnectPtr, const char *);
+
+ if (is_uuid(vm_name))
+ virt_lookup_fn = virDomainLookupByUUIDString;
+ else
+ virt_lookup_fn = virDomainLookupByName;
+
+ for (i = 0 ; i < vp_count ; i++) {
+ vdp = virt_lookup_fn(vp[i], vm_name);
+ if (vdp)
+ break;
+ }
+
+ if (!vdp) {
+ dbg_printf(2, "[virt:STATUS] Unknown VM %s - return OFF\n", vm_name);
+ return RESP_OFF;
+ }
+
+ if (virDomainGetInfo(vdp, &vdi) == 0 && vdi.state == VIR_DOMAIN_SHUTOFF) {
+ dbg_printf(2, "[virt:STATUS] VM %s is OFF\n", vm_name);
+ ret = RESP_OFF;
+ }
+
+ if (vdp)
+ virDomainFree(vdp);
+ return ret;
+}
+
+
+int
+vm_reboot(virConnectPtr *vp, int vp_count, const char *vm_name)
+{
+ virDomainPtr vdp = NULL, nvdp;
+ virDomainInfo vdi;
+ char *domain_desc;
+ virConnectPtr vcp = NULL;
+ virDomainPtr (*virt_lookup_fn)(virConnectPtr, const char *);
+ int ret;
+ int i;
+
+ if (is_uuid(vm_name))
+ virt_lookup_fn = virDomainLookupByUUIDString;
+ else
+ virt_lookup_fn = virDomainLookupByName;
+
+ for (i = 0 ; i < vp_count ; i++) {
+ vdp = virt_lookup_fn(vp[i], vm_name);
+ if (vdp) {
+ vcp = vp[i];
+ break;
+ }
+ }
+
+ if (!vdp || !vcp) {
+ dbg_printf(2,
+ "[virt:REBOOT] Nothing to do - domain %s does not exist\n",
+ vm_name);
+ return 1;
+ }
+
+ if (virDomainGetInfo(vdp, &vdi) == 0 && vdi.state == VIR_DOMAIN_SHUTOFF) {
+ dbg_printf(2, "[virt:REBOOT] Nothing to do - domain %s is off\n",
+ vm_name);
+ virDomainFree(vdp);
+ return 0;
+ }
+
+ syslog(LOG_NOTICE, "Rebooting domain %s\n", vm_name);
+ dbg_printf(5, "[virt:REBOOT] Rebooting domain %s...\n", vm_name);
+
+ domain_desc = virDomainGetXMLDesc(vdp, 0);
+
+ if (!domain_desc) {
+ dbg_printf(5, "[virt:REBOOT] Failed getting domain description "
+ "from libvirt for %s...\n", vm_name);
+ }
+
+ dbg_printf(2, "[virt:REBOOT] Calling virDomainDestroy(%p) for %s\n",
+ vdp, vm_name);
+
+ ret = virDomainDestroy(vdp);
+ if (ret < 0) {
+ dbg_printf(2,
+ "[virt:REBOOT] virDomainDestroy() failed for %s: %d/%d\n",
+ vm_name, ret, errno);
+
+ if (domain_desc)
+ free(domain_desc);
+ virDomainFree(vdp);
+ return 1;
+ }
+
+ ret = wait_domain(vm_name, vcp, 15);
+
+ if (ret) {
+ syslog(LOG_NOTICE, "Domain %s still exists; fencing failed\n", vm_name);
+ dbg_printf(2,
+ "[virt:REBOOT] Domain %s still exists; fencing failed\n",
+ vm_name);
+
+ if (domain_desc)
+ free(domain_desc);
+ virDomainFree(vdp);
+ return 1;
+ }
+
+ if (!domain_desc)
+ return 0;
+
+ /* 'on' is not a failure */
+ ret = 0;
+
+ dbg_printf(3, "[[ XML Domain Info ]]\n");
+ dbg_printf(3, "%s\n[[ XML END ]]\n", domain_desc);
+
+ dbg_printf(2, "[virt:REBOOT] Calling virDomainCreateLinux() for %s\n",
+ vm_name);
+
+ nvdp = virDomainCreateLinux(vcp, domain_desc, 0);
+ if (nvdp == NULL) {
+ /* More recent versions of libvirt or perhaps the
+ * KVM back-end do not let you create a domain from
+ * XML if there is already a defined domain description
+ * with the same name that it knows about. You must
+ * then call virDomainCreate() */
+ dbg_printf(2,
+ "[virt:REBOOT] virDomainCreateLinux() failed for %s; "
+ "Trying virDomainCreate()\n",
+ vm_name);
+
+ if (virDomainCreate(vdp) < 0) {
+ syslog(LOG_NOTICE, "Could not restart %s\n", vm_name);
+ dbg_printf(1, "[virt:REBOOT] Failed to recreate guest %s!\n",
+ vm_name);
+ }
+ }
+
+ free(domain_desc);
+ virDomainFree(vdp);
+ return ret;
+}
diff --git a/agents/virt/server/virt.h b/agents/virt/server/virt.h
new file mode 100644
index 0000000..1d9140c
--- /dev/null
+++ b/agents/virt/server/virt.h
@@ -0,0 +1,62 @@
+/*
+ Copyright Red Hat, Inc. 2006-2017
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+
+#ifndef _VIRT_H
+#define _VIRT_H
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <libvirt/libvirt.h>
+
+#include "xvm.h"
+
+typedef struct {
+ uint32_t s_owner;
+ int32_t s_state;
+} vm_state_t;
+
+typedef struct {
+ char v_name[MAX_DOMAINNAME_LENGTH + 1];
+ char v_uuid[MAX_DOMAINNAME_LENGTH + 1];
+ vm_state_t v_state;
+} virt_state_t;
+
+/**
+ This is stored in our private checkpoint section.
+ */
+typedef struct _virt_list {
+ uint32_t vm_count;
+ virt_state_t vm_states[0];
+} virt_list_t;
+
+virt_list_t *vl_get(virConnectPtr *vp, int vp_count, int my_id);
+void vl_print(virt_list_t *vl);
+void vl_free(virt_list_t *old);
+virt_state_t *vl_find_uuid(virt_list_t *vl, const char *name);
+virt_state_t *vl_find_name(virt_list_t *vl, const char *name);
+int vl_add(virt_list_t **vl, virt_state_t *vm);
+int vl_update(virt_list_t **vl, virt_state_t *vm);
+int vl_remove_by_owner(virt_list_t **vl, uint32_t owner);
+
+int vm_off(virConnectPtr *vp, int vp_count, const char *vm_name);
+int vm_on(virConnectPtr *vp, int vp_count, const char *vm_name);
+int vm_status(virConnectPtr *vp, int vp_count, const char *vm_name);
+int vm_reboot(virConnectPtr *vp, int vp_count, const char *vm_name);
+
+#endif
diff --git a/agents/virt/server/vsock.c b/agents/virt/server/vsock.c
new file mode 100644
index 0000000..1b88fa5
--- /dev/null
+++ b/agents/virt/server/vsock.c
@@ -0,0 +1,565 @@
+/*
+ Copyright Red Hat, Inc. 2017
+
+ 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, 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; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ MA 02139, USA.
+*/
+#include "config.h"
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <nss.h>
+#include <sys/socket.h>
+#include <linux/vm_sockets.h>
+
+/* Local includes */
+#include "list.h"
+#include "simpleconfig.h"
+#include "static_map.h"
+#include "server_plugin.h"
+#include "history.h"
+#include "xvm.h"
+#include "simple_auth.h"
+#include "options.h"
+#include "mcast.h"
+#include "tcp.h"
+#include "tcp_listener.h"
+#include "debug.h"
+#include "fdops.h"
+
+#define NAME "vsock"
+#define VSOCK_VERSION "0.2"
+
+#define VSOCK_MAGIC 0xa32d27c1e
+
+#define VALIDATE(info) \
+do {\
+ if (!info || info->magic != VSOCK_MAGIC)\
+ return -EINVAL;\
+} while(0)
+
+typedef struct _vsock_options {
+ char *key_file;
+ int cid;
+ unsigned int port;
+ unsigned int hash;
+ unsigned int auth;
+ unsigned int flags;
+} vsock_options;
+
+
+typedef struct _vsock_info {
+ uint64_t magic;
+ void *priv;
+ map_object_t *map;
+ history_info_t *history;
+ char key[MAX_KEY_LEN];
+ vsock_options args;
+ const fence_callbacks_t *cb;
+ ssize_t key_len;
+ int listen_sock;
+} vsock_info;
+
+
+struct vsock_hostlist_arg {
+ map_object_t *map;
+ int cid;
+ int fd;
+};
+
+
+static int get_peer_cid(int fd, uint32_t *peer_cid) {
+ struct sockaddr_vm svm;
+ socklen_t len;
+ int ret;
+
+ if (!peer_cid)
+ return -1;
+
+ len = sizeof(svm);
+ ret = getpeername(fd, (struct sockaddr *) &svm, &len);
+ if (ret < 0) {
+ printf("Error getting peer CID: %s\n", strerror(errno));
+ return -1;
+ }
+
+ *peer_cid = svm.svm_cid;
+ return 0;
+}
+
+
+/*
+ * See if we fenced this node recently (successfully)
+ * If so, ignore the request for a few seconds.
+ *
+ * We purge our history when the entries time out.
+ */
+static int
+check_history(void *a, void *b) {
+ fence_req_t *old = a, *current = b;
+
+ if (old->request == current->request &&
+ old->seqno == current->seqno &&
+ !strcasecmp((const char *)old->domain,
+ (const char *)current->domain)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+vsock_hostlist(const char *vm_name, const char *vm_uuid,
+ int state, void *priv)
+{
+ struct vsock_hostlist_arg *arg = (struct vsock_hostlist_arg *) priv;
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+ uint32_t peer_cid = 0;
+ char peer_cid_str[24];
+
+ ret = get_peer_cid(arg->fd, &peer_cid);
+ if (ret < 0) {
+ printf("Unable to get peer CID: %s\n", strerror(errno));
+ peer_cid_str[0] = '\0';
+ } else
+ snprintf(peer_cid_str, sizeof(peer_cid_str), "%u", peer_cid);
+
+ /* Noops if auth == AUTH_NONE */
+
+ if (map_check2(arg->map, peer_cid_str, vm_uuid, vm_name) == 0) {
+ /* if we don't have access to fence this VM,
+ * we should not see it in a hostlist either */
+ return 0;
+ }
+
+ strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain) - 1);
+ strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid) - 1);
+ hinfo.state = state;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+
+static int
+vsock_hostlist_begin(int fd)
+{
+ struct timeval tv;
+ char val = (char) RESP_HOSTLIST;
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ return _write_retry(fd, &val, 1, &tv);
+}
+
+
+static int
+vsock_hostlist_end(int fd)
+{
+ host_state_t hinfo;
+ struct timeval tv;
+ int ret;
+
+ printf("Sending terminator packet\n");
+
+ memset(&hinfo, 0, sizeof(hinfo));
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ ret = _write_retry(fd, &hinfo, sizeof(hinfo), &tv);
+ if (ret == sizeof(hinfo))
+ return 0;
+ return 1;
+}
+
+
+static int
+do_fence_request_vsock(int fd, fence_req_t *req, vsock_info *info)
+{
+ char response = 1;
+ struct vsock_hostlist_arg arg;
+ uint32_t peer_cid = 0;
+ char peer_cid_str[24];
+ int ret;
+
+ ret = get_peer_cid(fd, &peer_cid);
+ if (ret < 0) {
+ printf("Unable to get peer CID: %s\n", strerror(errno));
+ return -1;
+ }
+
+ snprintf(peer_cid_str, sizeof(peer_cid_str), "%u", peer_cid);
+
+ /* Noops if auth == AUTH_NONE */
+ if (sock_response(fd, info->args.auth, info->key, info->key_len, 10) <= 0) {
+ printf("CID %u Failed to respond to challenge\n", peer_cid);
+ close(fd);
+ return -1;
+ }
+
+ ret = sock_challenge(fd, info->args.auth, info->key, info->key_len, 10);
+ if (ret <= 0) {
+ printf("Remote CID %u failed challenge\n", peer_cid);
+ close(fd);
+ return -1;
+ }
+
+ dbg_printf(2, "Request %d seqno %d target %s from CID %u\n",
+ req->request, req->seqno, req->domain, peer_cid);
+
+ switch(req->request) {
+ case FENCE_NULL:
+ response = info->cb->null((char *)req->domain, info->priv);
+ break;
+ case FENCE_ON:
+ if (map_check(info->map, peer_cid_str,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->on((char *)req->domain, peer_cid_str,
+ req->seqno, info->priv);
+ break;
+ case FENCE_OFF:
+ if (map_check(info->map, peer_cid_str,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->off((char *)req->domain, peer_cid_str,
+ req->seqno, info->priv);
+ break;
+ case FENCE_REBOOT:
+ if (map_check(info->map, peer_cid_str,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->reboot((char *)req->domain, peer_cid_str,
+ req->seqno, info->priv);
+ break;
+ case FENCE_STATUS:
+ if (map_check(info->map, peer_cid_str,
+ (const char *)req->domain) == 0) {
+ response = RESP_PERM;
+ break;
+ }
+ response = info->cb->status((char *)req->domain, info->priv);
+ break;
+ case FENCE_DEVSTATUS:
+ response = info->cb->devstatus(info->priv);
+ break;
+ case FENCE_HOSTLIST:
+ arg.map = info->map;
+ arg.fd = fd;
+
+ vsock_hostlist_begin(arg.fd);
+ response = info->cb->hostlist(vsock_hostlist, &arg, info->priv);
+ vsock_hostlist_end(arg.fd);
+ break;
+ }
+
+ dbg_printf(3, "Sending response to caller CID %u...\n", peer_cid);
+ if (_write_retry(fd, &response, 1, NULL) < 0)
+ perror("write");
+
+ history_record(info->history, req);
+
+ if (fd != -1)
+ close(fd);
+
+ return 1;
+}
+
+
+static int
+vsock_dispatch(listener_context_t c, struct timeval *timeout)
+{
+ vsock_info *info;
+ fence_req_t data;
+ fd_set rfds;
+ int n;
+ int client_fd;
+ int ret;
+ struct timeval tv;
+
+ if (timeout != NULL)
+ memcpy(&tv, timeout, sizeof(tv));
+ else {
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ }
+
+ info = (vsock_info *) c;
+ VALIDATE(info);
+
+ FD_ZERO(&rfds);
+ FD_SET(info->listen_sock, &rfds);
+
+ n = select(info->listen_sock + 1, &rfds, NULL, NULL, timeout);
+ if (n <= 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ n = 0;
+ else
+ dbg_printf(2, "select: %s\n", strerror(errno));
+ return n;
+ }
+
+
+ client_fd = accept(info->listen_sock, NULL, NULL);
+ if (client_fd < 0) {
+ perror("accept");
+ return -1;
+ }
+
+ dbg_printf(3, "Accepted vsock client...\n");
+
+ ret = _read_retry(client_fd, &data, sizeof(data), &tv);
+ if (ret != sizeof(data)) {
+ dbg_printf(3, "Invalid request (read %d bytes)\n", ret);
+ close(client_fd);
+ return 0;
+ }
+
+ swab_fence_req_t(&data);
+
+ if (!verify_request(&data, info->args.hash, info->key, info->key_len)) {
+ printf("Key mismatch; dropping client\n");
+ close(client_fd);
+ return 0;
+ }
+
+ dbg_printf(3, "Request %d seqno %d domain %s\n",
+ data.request, data.seqno, data.domain);
+
+ if (history_check(info->history, &data) == 1) {
+ printf("We just did this request; dropping client\n");
+ close(client_fd);
+ return 0;
+ }
+
+ switch(info->args.auth) {
+ case AUTH_NONE:
+ case AUTH_SHA1:
+ case AUTH_SHA256:
+ case AUTH_SHA512:
+ printf("VSOCK request\n");
+ do_fence_request_vsock(client_fd, &data, info);
+ break;
+ default:
+ printf("XXX Unhandled authentication\n");
+ }
+
+ return 0;
+}
+
+
+static int
+vsock_config(config_object_t *config, vsock_options *args)
+{
+ char value[1024];
+ int errors = 0;
+
+ if (sc_get(config, "fence_virtd/@debug", value, sizeof(value))==0)
+ dset(atoi(value));
+
+ if (sc_get(config, "listeners/vsock/@key_file",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for key_file\n", value);
+ args->key_file = strdup(value);
+ } else {
+ args->key_file = strdup(DEFAULT_KEY_FILE);
+ if (!args->key_file) {
+ dbg_printf(1, "Failed to allocate memory\n");
+ return -1;
+ }
+ }
+
+ args->hash = DEFAULT_HASH;
+ if (sc_get(config, "listeners/vsock/@hash",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for hash\n", value);
+ if (!strcasecmp(value, "none")) {
+ args->hash = HASH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->hash = HASH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->hash = HASH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->hash = HASH_SHA512;
+ } else {
+ dbg_printf(1, "Unsupported hash: %s\n", value);
+ ++errors;
+ }
+ }
+
+ args->auth = DEFAULT_AUTH;
+ if (sc_get(config, "listeners/vsock/@auth",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for auth\n", value);
+ if (!strcasecmp(value, "none")) {
+ args->hash = AUTH_NONE;
+ } else if (!strcasecmp(value, "sha1")) {
+ args->hash = AUTH_SHA1;
+ } else if (!strcasecmp(value, "sha256")) {
+ args->hash = AUTH_SHA256;
+ } else if (!strcasecmp(value, "sha512")) {
+ args->hash = AUTH_SHA512;
+ } else {
+ dbg_printf(1, "Unsupported auth: %s\n", value);
+ ++errors;
+ }
+ }
+
+ args->port = DEFAULT_MCAST_PORT;
+ if (sc_get(config, "listeners/vsock/@port",
+ value, sizeof(value)-1) == 0) {
+ dbg_printf(1, "Got %s for port\n", value);
+ args->port = atoi(value);
+ if (args->port <= 0) {
+ dbg_printf(1, "Invalid port: %s\n", value);
+ ++errors;
+ }
+ }
+
+ return errors;
+}
+
+
+static int
+vsock_init(listener_context_t *c, const fence_callbacks_t *cb,
+ config_object_t *config, map_object_t *map, void *priv)
+{
+ vsock_info *info;
+ int listen_sock, ret;
+ struct sockaddr_vm svm;
+
+ if (NSS_NoDB_Init(NULL) != SECSuccess) {
+ printf("Could not initialize NSS\n");
+ return 1;
+ }
+
+ info = calloc(1, sizeof(*info));
+ if (!info)
+ return -1;
+
+ info->priv = priv;
+ info->cb = cb;
+ info->map = map;
+
+ ret = vsock_config(config, &info->args);
+ if (ret < 0)
+ perror("vsock_config");
+ else if (ret > 0)
+ printf("%d errors found during vsock listener configuration\n", ret);
+
+ if (ret != 0) {
+ if (info->args.key_file)
+ free(info->args.key_file);
+ free(info);
+ return -1;
+ }
+
+ if (info->args.auth != AUTH_NONE || info->args.hash != HASH_NONE) {
+ info->key_len = read_key_file(info->args.key_file,
+ info->key, sizeof(info->key));
+ if (info->key_len < 0) {
+ printf("Could not read %s; operating without "
+ "authentication\n", info->args.key_file);
+ info->args.auth = AUTH_NONE;
+ info->args.hash = HASH_NONE;
+ info->key_len = 0;
+ }
+ }
+
+ listen_sock = socket(PF_VSOCK, SOCK_STREAM, 0);
+ if (listen_sock < 0)
+ goto out_fail;
+
+ memset(&svm, 0, sizeof(svm));
+ svm.svm_family = AF_VSOCK;
+ svm.svm_cid = VMADDR_CID_ANY;
+ svm.svm_port = info->args.port;
+
+ if (bind(listen_sock, (struct sockaddr *) &svm, sizeof(svm)) < 0)
+ goto out_fail;
+
+ if (listen(listen_sock, 1) < 0)
+ goto out_fail;
+
+ info->magic = VSOCK_MAGIC;
+ info->listen_sock = listen_sock;
+ info->history = history_init(check_history, 10, sizeof(fence_req_t));
+ *c = (listener_context_t)info;
+ return 0;
+
+out_fail:
+ printf("Could not set up listen socket: %s\n", strerror(errno));
+ if (listen_sock >= 0)
+ close(listen_sock);
+ if (info->args.key_file)
+ free(info->args.key_file);
+ free(info);
+ return -1;
+}
+
+
+static int
+vsock_shutdown(listener_context_t c)
+{
+ vsock_info *info = (vsock_info *)c;
+
+ VALIDATE(info);
+ info->magic = 0;
+ history_wipe(info->history);
+ free(info->history);
+ free(info->args.key_file);
+ close(info->listen_sock);
+ free(info);
+
+ return 0;
+}
+
+
+static listener_plugin_t vsock_plugin = {
+ .name = NAME,
+ .version = VSOCK_VERSION,
+ .init = vsock_init,
+ .dispatch = vsock_dispatch,
+ .cleanup = vsock_shutdown,
+};
+
+double
+LISTENER_VER_SYM(void)
+{
+ return PLUGIN_VERSION_LISTENER;
+}
+
+const listener_plugin_t *
+LISTENER_INFO_SYM(void)
+{
+ return &vsock_plugin;
+}
diff --git a/agents/vmware/fence_vmware.py b/agents/vmware/fence_vmware.py
new file mode 100644
index 0000000..bc1785f
--- /dev/null
+++ b/agents/vmware/fence_vmware.py
@@ -0,0 +1,336 @@
+#!@PYTHON@ -tt
+
+#
+# The Following agent has been tested on:
+# vmrun 2.0.0 build-116503 (from VMware Server 2.0) against:
+# VMware ESX 4.0.0
+# VMware vCenter 4.0.0
+# VMware ESX 3.5
+# VMware Server 2.0.0
+# VMware ESXi 3.5 update 2
+# VMware Server 1.0.7 (works but list/status show only running VMs)
+#
+# VI Perl API 1.6 against:
+# VMware ESX 4.0.0
+# VMware vCenter 4.0.0
+# VMware ESX 3.5
+# VMware ESXi 3.5 update 2
+# VMware Virtual Center 2.5
+#
+# VMware vSphere SDK for Perl 4.0.0 against:
+# VMware ESX 4.0.0
+# VMware vCenter 4.0.0
+#
+
+import sys, re, pexpect
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay, frun
+
+### CONSTANTS ####
+# VMware type is ESX/ESXi/VC
+VMWARE_TYPE_ESX = 0
+# VMware type is Server 1.x
+VMWARE_TYPE_SERVER1 = 1
+# VMware type is Server 2.x and/or ESX 3.5 up2, ESXi 3.5 up2, VC 2.5 up2
+VMWARE_TYPE_SERVER2 = 2
+
+# Minimum required version of vmrun command
+VMRUN_MINIMUM_REQUIRED_VERSION = 2
+
+# Default path to vmhelper command
+VMHELPER_COMMAND = "fence_vmware_helper"
+# Default path to vmrun command
+VMRUN_COMMAND = "/usr/bin/vmrun"
+# Default type of vmware
+VMWARE_DEFAULT_TYPE = "esx"
+
+#### GLOBAL VARIABLES ####
+# Internal type. One of VMWARE_TYPE_, set by #vmware_check_vmware_type
+vmware_internal_type = VMWARE_TYPE_ESX
+
+# If ESX is disconnected, say, that VM is off (don't return previous state)
+vmware_disconnected_hack = False
+
+### FUNCTIONS ####
+
+#Split string in simplified DSV format to array of items
+def dsv_split(dsv_str):
+ delimiter_c = ':'
+ escape_c = '\\'
+
+ res = []
+ status = 0
+ tmp_str = ""
+
+ for x in dsv_str:
+ if status == 0:
+ if x == delimiter_c:
+ res.append(tmp_str)
+ tmp_str = ""
+ elif x == escape_c:
+ status = 1
+ else:
+ tmp_str += x
+ elif status == 1:
+ if x == delimiter_c:
+ tmp_str += delimiter_c
+ elif x == escape_c:
+ tmp_str += escape_c
+ else:
+ tmp_str += escape_c+x
+ status = 0
+
+ if tmp_str != "":
+ res.append(tmp_str)
+
+ return res
+
+# Quote string for proper existence in quoted string used for pexpect.run function
+# Ex. test'this will return test'\''this. So pexpect run will really pass ' to argument
+def quote_for_run(text):
+ dstr = ''
+
+ for c in text:
+ if c == r"'":
+ dstr += "'\\''"
+ else:
+ dstr += c
+
+ return dstr
+
+# Return string with command and additional parameters (something like vmrun -h 'host'
+def vmware_prepare_command(options, add_login_params, additional_params):
+ res = options["--exec"]
+
+ if add_login_params:
+ if vmware_internal_type == VMWARE_TYPE_ESX:
+ res += " --server '%s' --username '%s' --password '%s' "% (quote_for_run(options["--ip"]),
+ quote_for_run(options["--username"]),
+ quote_for_run(options["--password"]))
+ elif vmware_internal_type == VMWARE_TYPE_SERVER2:
+ res += " -h 'https://%s/sdk' -u '%s' -p '%s' -T server "% (quote_for_run(options["--ip"]),
+ quote_for_run(options["--username"]),
+ quote_for_run(options["--password"]))
+ elif vmware_internal_type == VMWARE_TYPE_SERVER1:
+ host_name_array = options["--ip"].split(':')
+
+ res += " -h '%s' -u '%s' -p '%s' -T server1 "% (quote_for_run(host_name_array[0]),
+ quote_for_run(options["--username"]),
+ quote_for_run(options["--password"]))
+ if len(host_name_array) > 1:
+ res += "-P '%s' "% (quote_for_run(host_name_array[1]))
+
+ if "--vmware-datacenter" in options and vmware_internal_type == VMWARE_TYPE_ESX:
+ res += "--datacenter '%s' "% (quote_for_run(options["--vmware-datacenter"]))
+
+ if additional_params != "":
+ res += additional_params
+
+ return res
+
+# Run command with timeout and parameters. Internaly uses vmware_prepare_command. Returns string
+# with output from vmrun command. If something fails (command not found, exit code is not 0), fail_usage
+# function is called (and never return).
+def vmware_run_command(options, add_login_params, additional_params, additional_timeout):
+ command = vmware_prepare_command(options, add_login_params, additional_params)
+
+ try:
+ logging.debug("%s\n", command)
+
+ (res_output, res_code) = frun(command,
+ int(options["--shell-timeout"]) + int(options["--login-timeout"]) + additional_timeout, True)
+
+ if res_code == None:
+ fail(EC_TIMED_OUT)
+ if res_code != 0 and add_login_params:
+ logging.debug("%s\n", res_output)
+ fail_usage("%s returned %s"% (options["--exec"], res_output))
+ else:
+ logging.debug("%s\n", res_output)
+
+ except pexpect.ExceptionPexpect:
+ fail_usage("Cannot run command %s"% (options["--exec"]))
+
+ return res_output
+
+# Get outlet list with status as hash table. If you will use add_vm_name, only VM with vmname is
+# returned. This is used in get_status function
+def vmware_get_outlets_vi(options, add_vm_name):
+ outlets = {}
+
+ if add_vm_name:
+ all_machines = vmware_run_command(options, True,
+ ("--operation status --vmname '%s'"% (quote_for_run(options["--plug"]))), 0)
+ else:
+ all_machines = vmware_run_command(options, True, "--operation list", int(options["--power-timeout"]))
+
+ all_machines_array = all_machines.splitlines()
+
+ for machine in all_machines_array:
+ machine_array = dsv_split(machine)
+ if len(machine_array) == 4:
+ if machine_array[0] in outlets:
+ fail_usage("Failed. More machines with same name %s found!"%(machine_array[0]))
+
+ if vmware_disconnected_hack:
+ outlets[machine_array[0]] = ("", (
+ ((machine_array[2].lower() in ["poweredon"]) and
+ (machine_array[3].lower() == "connected"))
+ and "on" or "off"))
+ else:
+ outlets[machine_array[0]] = ("", ((machine_array[2].lower() in ["poweredon"]) and "on" or "off"))
+ return outlets
+
+# Get outlet list with status as hash table.
+def vmware_get_outlets_vix(options):
+ outlets = {}
+
+ running_machines = vmware_run_command(options, True, "list", 0)
+ running_machines_array = running_machines.splitlines()[1:]
+
+ if vmware_internal_type == VMWARE_TYPE_SERVER2:
+ all_machines = vmware_run_command(options, True, "listRegisteredVM", 0)
+ all_machines_array = all_machines.splitlines()[1:]
+ elif vmware_internal_type == VMWARE_TYPE_SERVER1:
+ all_machines_array = running_machines_array
+
+ for machine in all_machines_array:
+ if machine != "":
+ outlets[machine] = ("", ((machine in running_machines_array) and "on" or "off"))
+
+ return outlets
+
+def get_outlets_status(conn, options):
+ del conn
+
+ if vmware_internal_type == VMWARE_TYPE_ESX:
+ return vmware_get_outlets_vi(options, False)
+ if vmware_internal_type == VMWARE_TYPE_SERVER1 or vmware_internal_type == VMWARE_TYPE_SERVER2:
+ return vmware_get_outlets_vix(options)
+
+def get_power_status(conn, options):
+ if vmware_internal_type == VMWARE_TYPE_ESX:
+ outlets = vmware_get_outlets_vi(options, True)
+ else:
+ outlets = get_outlets_status(conn, options)
+
+ if vmware_internal_type == VMWARE_TYPE_SERVER2 or vmware_internal_type == VMWARE_TYPE_ESX:
+ if not options["--plug"] in outlets:
+ fail_usage("Failed: You have to enter existing name of virtual machine!")
+ else:
+ return outlets[options["--plug"]][1]
+ elif vmware_internal_type == VMWARE_TYPE_SERVER1:
+ return (options["--plug"] in outlets) and "on" or "off"
+
+def set_power_status(conn, options):
+ del conn
+
+ if vmware_internal_type == VMWARE_TYPE_ESX:
+ additional_params = "--operation %s --vmname '%s'" % \
+ ((options["--action"] == "on" and "on" or "off"), quote_for_run(options["--plug"]))
+ elif vmware_internal_type == VMWARE_TYPE_SERVER1 or vmware_internal_type == VMWARE_TYPE_SERVER2:
+ additional_params = "%s '%s'" % \
+ ((options["--action"] == "on" and "start" or "stop"), quote_for_run(options["--plug"]))
+ if options["--action"] == "off":
+ additional_params += " hard"
+
+ vmware_run_command(options, True, additional_params, int(options["--power-timeout"]))
+
+# Returns True, if user uses supported vmrun version (currently >=2.0.0) otherwise False.
+def vmware_is_supported_vmrun_version(options):
+ vmware_help_str = vmware_run_command(options, False, "", 0)
+ version_re = re.search(r"vmrun version (\d\.(\d[\.]*)*)", vmware_help_str.lower())
+ if version_re == None:
+ return False # Looks like this "vmrun" is not real vmrun
+
+ version_array = version_re.group(1).split(".")
+
+ try:
+ if int(version_array[0]) < VMRUN_MINIMUM_REQUIRED_VERSION:
+ return False
+ except Exception:
+ return False
+
+ return True
+
+# Check vmware type, set vmware_internal_type to one of VMWARE_TYPE_ value and
+# options["--exec"] to path (if not specified)
+def vmware_check_vmware_type(options):
+ global vmware_internal_type
+
+ options["--vmware_type"] = options["--vmware_type"].lower()
+
+ if options["--vmware_type"] == "esx":
+ vmware_internal_type = VMWARE_TYPE_ESX
+ if "--exec" not in options:
+ options["--exec"] = VMHELPER_COMMAND
+ elif options["--vmware_type"] == "server2":
+ vmware_internal_type = VMWARE_TYPE_SERVER2
+ if "--exec" not in options:
+ options["--exec"] = VMRUN_COMMAND
+ elif options["--vmware_type"] == "server1":
+ vmware_internal_type = VMWARE_TYPE_SERVER1
+ if "--exec" not in options:
+ options["--exec"] = VMRUN_COMMAND
+ else:
+ fail_usage("vmware_type can be esx,server2 or server1!")
+
+# Main agent method
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "secure",
+ "exec", "vmware_type", "vmware_datacenter"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["secure"]["default"] = "1"
+ all_opt["vmware_type"]["default"] = VMWARE_DEFAULT_TYPE
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for VMWare"
+ docs["longdesc"] = "fence_vmware is an I/O Fencing agent \
+which can be used with the VMware ESX, VMware ESXi or VMware Server \
+to fence virtual machines.\
+\n.P\n\
+Before you can use this agent, it must be installed VI Perl Toolkit or \
+vmrun command on every node you want to make fencing.\
+\n.P\n\
+VI Perl Toolkit is preferred for VMware ESX/ESXi and Virtual Center. Vmrun \
+command is only solution for VMware Server 1/2 (this command will works against \
+ESX/ESXi 3.5 up2 and VC up2 too, but not cluster aware!) and is available as part \
+of VMware VIX API SDK package. VI Perl and VIX API SDK are both available from \
+VMware web pages (not int RHEL repository!). \
+\n.P\n\
+You can specify type of VMware you are connecting to with \\fB-d\\fP switch \
+(or \\fIvmware_type\\fR for stdin). Possible values are esx, server2 and server1.\
+Default value is esx, which will use VI Perl. With server1 and server2, vmrun \
+command is used.\
+\n.P\n\
+After you have successfully installed VI Perl Toolkit or VIX API, you should \
+be able to run fence_vmware_helper (part of this agent) or vmrun command. \
+This agent supports only vmrun from version 2.0.0 (VIX API 1.6.0)."
+ docs["vendorurl"] = "http://www.vmware.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ # Check vmware type and set path
+ vmware_check_vmware_type(options)
+
+ # Test user vmrun command version
+ if vmware_internal_type == VMWARE_TYPE_SERVER1 or vmware_internal_type == VMWARE_TYPE_SERVER2:
+ if not vmware_is_supported_vmrun_version(options):
+ fail_usage("Unsupported version of vmrun command! You must use at least version %d!" %
+ (VMRUN_MINIMUM_REQUIRED_VERSION))
+
+ # Operate the fencing device
+ result = fence_action(None, options, set_power_status, get_power_status, get_outlets_status)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/vmware/fence_vmware_helper.pl b/agents/vmware/fence_vmware_helper.pl
new file mode 100644
index 0000000..a0b5cea
--- /dev/null
+++ b/agents/vmware/fence_vmware_helper.pl
@@ -0,0 +1,276 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $ME = $0;
+
+END {
+ defined fileno STDOUT or return;
+ close STDOUT and return;
+ warn "$ME: failed to close standard output: $!\n";
+ $? ||= 1;
+}
+
+my ($RELEASE_VERSION, $REDHAT_COPYRIGHT, $BUILD_DATE);
+
+#BEGIN_VERSION_GENERATION
+$RELEASE_VERSION="";
+$REDHAT_COPYRIGHT="";
+$BUILD_DATE="";
+#END_VERSION_GENERATION
+
+#### FUNCTIONS #####
+# Show error message
+sub show_error {
+ print STDERR @_;
+}
+
+sub my_exit {
+ my ($exit_code)=@_;
+
+ # Disconnect from server
+ Util::disconnect();
+
+ exit $exit_code;
+}
+
+# Convert one field (string) to format acceptable by DSV. This
+# means replace any : with \: and \ with \\.
+sub convert_field_to_dsv {
+ my ($input_line)=@_;
+
+ $input_line =~ s/([\\:])/\\$1/g;
+ return $input_line
+}
+
+#### Global variables #####
+# Aditional options
+my %opts = (
+ 'operation' => {
+ type => "=s",
+ help => "The operation to perform (on,off,list,status). "
+ . "Operations on/off/status require name of the virtual machine",
+ default => "list",
+ required => 0,
+ },
+ 'vmname' => {
+ type => "=s",
+ help => "The name of the virtual machine",
+ required => 0,
+ },
+ 'datacenter' => {
+ type => "=s",
+ help => "The name of the datacenter",
+ required => 0,
+ }
+);
+
+#################
+##### MAIN ######
+#################
+
+# Conditional use of VIRuntime
+eval "use VMware::VIRuntime;";
+
+if ($@) {
+ show_error "Please install VI Perl API package to use this tool!\nPerl error: $@";
+ exit 1;
+}
+
+# Parse options
+Opts::add_options(%opts);
+Opts::parse();
+Opts::validate();
+
+if (!(Opts::get_option('operation')=~/^(on|off|list|status)$/i)) {
+ show_error "Operation should be on, off, list or status!\n";
+ exit 2;
+}
+
+my $operation=lc(Opts::get_option('operation'));
+
+if (($operation ne 'list') && (!defined Opts::get_option('vmname'))) {
+ show_error "Operation on, off, status require vmname parameter!\n";
+ exit 2;
+}
+
+
+# Try connect to machine
+eval {
+ Util::connect();
+};
+
+if ($@) {
+ show_error "Cannot connect to server!\nVMware error:".$@;
+ exit 3;
+}
+
+my ($datacenter, $datacenter_view, $vm_views,$vm);
+# We are connected to machine
+
+# If user want's datacenter, we must first find datacenter
+my %filter=(view_type => 'VirtualMachine');
+
+if( defined (Opts::get_option('datacenter')) ) {
+ $datacenter = Opts::get_option('datacenter');
+ $datacenter_view = Vim::find_entity_view(view_type => 'Datacenter',
+ filter => { name => $datacenter });
+ if (!$datacenter_view) {
+ show_error "Cannot find datacenter ".$datacenter."!\n";
+
+ my_exit 4;
+ }
+
+ $filter{'begin_entity'}=$datacenter_view;
+}
+
+if ($operation ne 'list') {
+ $filter{'filter'}= {"config.name" => Opts::get_option('vmname')};
+}
+
+$vm_views = Vim::find_entity_views(%filter);
+
+my $found=0;
+
+# Traverse all found vm
+foreach $vm(@$vm_views) {
+ if (($operation eq 'list') or ($operation eq 'status')) {
+ if (!$vm->summary->config->template) {
+ print convert_field_to_dsv($vm->name).":".
+ convert_field_to_dsv($vm->summary->config->vmPathName).":".
+ convert_field_to_dsv($vm->runtime->powerState->val).":".
+ convert_field_to_dsv($vm->runtime->connectionState->val)."\n";
+ }
+ } elsif ($operation eq 'on') {
+ eval {
+ $vm->PowerOnVM();
+ };
+
+ if ($@) {
+ # If error is SoapFault with InvalidPowerState, user maybe use some auto power on tool.
+ # This is not error, warning is enought.
+ if (ref($@) eq 'SoapFault') {
+ if (ref($@->detail) eq 'InvalidPowerState') {
+ show_error "Warning: Cannot power on vm (somebody done it before???) ".Opts::get_option('vmname').
+ "!\nVMware error:".$@."\n";
+ }
+ } else {
+ # Some other more serious problem
+ show_error "Cannot power on vm ".Opts::get_option('vmname')."!\nVMware error:".$@."\n";
+ my_exit 6;
+ }
+ }
+ } elsif ($operation eq 'off') {
+ eval {
+ $vm->PowerOffVM();
+ };
+
+ if ($@) {
+ # If error is SoapFault with InvalidPowerState, user maybe use some auto power off tool.
+ # This is not error, warning is enought.
+ if (ref($@) eq 'SoapFault') {
+ if (ref($@->detail) eq 'InvalidPowerState') {
+ show_error "Warning: Cannot power off vm (somebody done it before???) ".Opts::get_option('vmname').
+ "!\nVMware error:".$@."\n";
+ }
+ } else {
+ # Some other more serious problem
+ show_error "Cannot power off vm ".Opts::get_option('vmname')."!\nVMware error:".$@."\n";
+ my_exit 6;
+ }
+ }
+ } else {
+ show_error "Operation should be on, off or list!\n";
+ my_exit 2;
+ }
+ $found++;
+}
+
+if ((!$found) && ($operation ne 'list')) {
+ show_error "Cannot find vm ".Opts::get_option('vmname')."!\n";
+ my_exit 5;
+}
+
+# Should be 0 -> success all, or 6 in case of error
+my_exit 0;
+
+__END__
+
+=head1 NAME
+
+fence_vmware_helper - Perform list of virtual machines and
+ poweron, poweroff of operations on virtual machines.
+
+=head1 SYNOPSIS
+
+ fence_vmware_helper --operation <on|off|list|status> [options]
+
+=head1 DESCRIPTION
+
+This VI Perl command-line utility provides an interface for
+seven common provisioning operations on one or more virtual
+machines: powering on, powering off and listing virtual mode.
+
+=head1 OPTIONS
+
+=head2 GENERAL OPTIONS
+
+=over
+
+=item B<operation>
+
+Operation to be performed. One of the following:
+
+ <on> (power on one or more virtual machines),
+ <off> (power off one or more virtual machines),
+ <list> (list virtual machines and their status)
+ <status> (same as list, but show only machines with vmname)
+
+=item B<vmname>
+
+Optional. Name of the virtual machine on which the
+operation is to be performed.
+
+=item B<datacenter>
+
+Optional. Name of the datacenter for the virtual machine(s).
+Operations will be performed on all the virtual machines under the given datacenter.
+
+=back
+
+=head1 EXAMPLES
+
+Power on a virtual machine
+
+ fence_vmware_helper --username administrator --password administrator --operation on
+ --vmname rhel --server win1
+
+ fence_vmware_helper --username administrator --password administrator --operation on
+ --vmname rhel --server win1 --datacenter Datacenter
+
+Power off a virtual machine
+
+ fence_vmware_helper --username administrator --password administrator --operation off
+ --vmname rhel --server win1
+
+ perl fence_vmware_helper --username administrator --password administrator --operation off
+ --vmname rhel --server win1 --datacenter Datacenter
+
+List of virtual machines
+
+ fence_vmware_helper --username administrator --password administrator --server win1
+
+ fence_vmware_helper --username administrator --password administrator --server win1
+ --operation list
+
+Get status of virtual machine
+
+ fence_vmware_helper --username administrator --password administrator --server win1
+ --vmname rhel --operation status
+
+=head1 SUPPORTED PLATFORMS
+
+All operations supported on ESX 3.0.1
+
+All operations supported on Virtual Center 2.0.1
diff --git a/agents/vmware_rest/fence_vmware_rest.py b/agents/vmware_rest/fence_vmware_rest.py
new file mode 100644
index 0000000..4b884fc
--- /dev/null
+++ b/agents/vmware_rest/fence_vmware_rest.py
@@ -0,0 +1,229 @@
+#!@PYTHON@ -tt
+
+import sys
+import pycurl, io, json
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS
+
+if sys.version_info[0] > 2: import urllib.parse as urllib
+else: import urllib
+
+state = {"POWERED_ON": "on", 'POWERED_OFF': "off", 'SUSPENDED': "off"}
+
+def get_power_status(conn, options):
+ try:
+ res = send_command(conn, "vcenter/vm?filter.names={}".format(urllib.quote(options["--plug"])))["value"]
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ fail(EC_STATUS)
+
+ if len(res) == 0:
+ fail(EC_STATUS)
+
+ options["id"] = res[0]["vm"]
+
+ result = res[0]["power_state"]
+
+ return state[result]
+
+def set_power_status(conn, options):
+ action = {
+ "on" : "start",
+ "off" : "stop"
+ }[options["--action"]]
+
+ try:
+ send_command(conn, "vcenter/vm/{}/power/{}".format(options["id"], action), "POST")
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ fail(EC_STATUS)
+
+def get_list(conn, options):
+ outlets = {}
+
+ try:
+ command = "vcenter/vm"
+ if "--filter" in options:
+ command = command + "?" + options["--filter"]
+ res = send_command(conn, command)
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ if str(e).startswith("400"):
+ if options.get("--original-action") == "monitor":
+ return outlets
+ else:
+ logging.error("More than 1000 VMs returned. Use --filter parameter to limit which VMs to list.")
+ fail(EC_STATUS)
+ else:
+ fail(EC_STATUS)
+
+ for r in res["value"]:
+ outlets[r["name"]] = ("", state[r["power_state"]])
+
+ return outlets
+
+def connect(opt):
+ conn = pycurl.Curl()
+
+ ## setup correct URL
+ if "--ssl-secure" in opt or "--ssl-insecure" in opt:
+ conn.base_url = "https:"
+ else:
+ conn.base_url = "http:"
+ if "--api-path" in opt:
+ api_path = opt["--api-path"]
+ else:
+ api_path = "/rest"
+
+ conn.base_url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + api_path + "/"
+
+ ## send command through pycurl
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Accept: application/json",
+ ])
+
+ conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
+ conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"])
+
+ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
+
+ if "--ssl-secure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ elif "--ssl-insecure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+
+ try:
+ result = send_command(conn, "com/vmware/cis/session", "POST")
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ fail(EC_LOGIN_DENIED)
+
+ # set session id for later requests
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Accept: application/json",
+ "vmware-api-session-id: {}".format(result["value"]),
+ ])
+
+ return conn
+
+def disconnect(conn):
+ try:
+ send_command(conn, "com/vmware/cis/session", "DELETE")
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ conn.close()
+
+def send_command(conn, command, method="GET"):
+ url = conn.base_url + command
+
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+
+ web_buffer = io.BytesIO()
+
+ if method == "GET":
+ conn.setopt(pycurl.POST, 0)
+ if method == "POST":
+ conn.setopt(pycurl.POSTFIELDS, "")
+ if method == "DELETE":
+ conn.setopt(pycurl.CUSTOMREQUEST, "DELETE")
+
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+
+ try:
+ conn.perform()
+ except Exception as e:
+ raise(e)
+
+ rc = conn.getinfo(pycurl.HTTP_CODE)
+ result = web_buffer.getvalue().decode("UTF-8")
+
+ web_buffer.close()
+
+ if len(result) > 0:
+ result = json.loads(result)
+
+ if rc != 200:
+ if len(result) > 0:
+ raise Exception("{}: {}".format(rc,
+ result["value"]["messages"][0]["default_message"]))
+ else:
+ raise Exception("Remote returned {} for request to {}".format(rc, url))
+
+ logging.debug("url: {}".format(url))
+ logging.debug("method: {}".format(method))
+ logging.debug("response code: {}".format(rc))
+ logging.debug("result: {}\n".format(result))
+
+ return result
+
+def define_new_opts():
+ all_opt["api_path"] = {
+ "getopt" : ":",
+ "longopt" : "api-path",
+ "help" : "--api-path=[path] The path part of the API URL",
+ "default" : "/rest",
+ "required" : "0",
+ "shortdesc" : "The path part of the API URL",
+ "order" : 2}
+ all_opt["filter"] = {
+ "getopt" : ":",
+ "longopt" : "filter",
+ "help" : "--filter=[filter] Filter to only return relevant VMs"
+ " (e.g. \"filter.names=node1&filter.names=node2\").",
+ "required" : "0",
+ "shortdesc" : "Filter to only return relevant VMs. It can be used to avoid "
+ "the agent failing when more than 1000 VMs should be returned.",
+ "order" : 2}
+
+
+def main():
+ device_opt = [
+ "ipaddr",
+ "api_path",
+ "login",
+ "passwd",
+ "ssl",
+ "notls",
+ "web",
+ "port",
+ "filter",
+ ]
+
+ atexit.register(atexit_handler)
+ define_new_opts()
+
+ all_opt["shell_timeout"]["default"] = "5"
+ all_opt["power_wait"]["default"] = "1"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for VMware REST API"
+ docs["longdesc"] = """fence_vmware_rest is an I/O Fencing agent which can be \
+used with VMware API to fence virtual machines.
+
+NOTE: If there's more than 1000 VMs there is a filter parameter to work around \
+the API limit. See https://code.vmware.com/apis/62/vcenter-management#/VM%20/get_vcenter_vm \
+for full list of filters."""
+ docs["vendorurl"] = "https://www.vmware.com"
+ show_docs(options, docs)
+
+ ####
+ ## Fence operations
+ ####
+ run_delay(options)
+
+ conn = connect(options)
+ atexit.register(disconnect, conn)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_list)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/vmware_soap/fence_vmware_soap.py b/agents/vmware_soap/fence_vmware_soap.py
new file mode 100644
index 0000000..4a4ec17
--- /dev/null
+++ b/agents/vmware_soap/fence_vmware_soap.py
@@ -0,0 +1,265 @@
+#!@PYTHON@ -tt
+
+import sys
+import shutil, tempfile, suds
+import logging, requests
+import atexit, signal
+sys.path.append("@FENCEAGENTSLIBDIR@")
+
+from suds.client import Client
+from suds.sudsobject import Property
+from suds.transport.http import HttpAuthenticated
+from suds.transport import Reply, TransportError
+from fencing import *
+from fencing import fail, fail_usage, EC_STATUS, EC_LOGIN_DENIED, EC_INVALID_PRIVILEGES, EC_WAITING_ON, EC_WAITING_OFF
+from fencing import run_delay
+
+options_global = None
+conn_global = None
+
+class RequestsTransport(HttpAuthenticated):
+ def __init__(self, **kwargs):
+ self.cert = kwargs.pop('cert', None)
+ self.verify = kwargs.pop('verify', True)
+ self.session = requests.Session()
+ # super won't work because not using new style class
+ HttpAuthenticated.__init__(self, **kwargs)
+
+ def send(self, request):
+ self.addcredentials(request)
+ resp = self.session.post(request.url, data=request.message, headers=request.headers, cert=self.cert, verify=self.verify)
+ result = Reply(resp.status_code, resp.headers, resp.content)
+ return result
+
+def soap_login(options):
+ run_delay(options)
+
+ if "--ssl-secure" in options or "--ssl-insecure" in options:
+ if "--ssl-insecure" in options:
+ import ssl
+ import urllib3
+ if hasattr(ssl, '_create_unverified_context'):
+ ssl._create_default_https_context = ssl._create_unverified_context
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+ verify = False
+ else:
+ verify = True
+ url = "https://"
+ else:
+ verify = False
+ url = "http://"
+
+ url += options["--ip"] + ":" + str(options["--ipport"]) + "/sdk"
+
+ tmp_dir = tempfile.mkdtemp()
+ tempfile.tempdir = tmp_dir
+ atexit.register(remove_tmp_dir, tmp_dir)
+
+ try:
+ headers = {"Content-Type" : "text/xml;charset=UTF-8", "SOAPAction" : "vim25"}
+ login_timeout = int(options["--login-timeout"]) or 15
+ conn = Client(url + "/vimService.wsdl", location=url, transport=RequestsTransport(verify=verify), headers=headers, timeout=login_timeout)
+
+ mo_ServiceInstance = Property('ServiceInstance')
+ mo_ServiceInstance._type = 'ServiceInstance'
+ ServiceContent = conn.service.RetrieveServiceContent(mo_ServiceInstance)
+ mo_SessionManager = Property(ServiceContent.sessionManager.value)
+ mo_SessionManager._type = 'SessionManager'
+
+ conn.service.Login(mo_SessionManager, options["--username"], options["--password"])
+ except requests.exceptions.SSLError as ex:
+ fail_usage("Server side certificate verification failed: %s" % ex)
+ except Exception as e:
+ logging.error("Server side certificate verification failed: {}".format(str(e)))
+ fail(EC_LOGIN_DENIED)
+
+ options["ServiceContent"] = ServiceContent
+ options["mo_SessionManager"] = mo_SessionManager
+ return conn
+
+def process_results(results, machines, uuid, mappingToUUID):
+ for m in results.objects:
+ info = {}
+ for i in m.propSet:
+ info[i.name] = i.val
+ # Prevent error KeyError: 'config.uuid' when reaching systems which P2V failed,
+ # since these systems don't have a valid UUID
+ if "config.uuid" in info:
+ machines[info["name"]] = (info["config.uuid"], info["summary.runtime.powerState"])
+ uuid[info["config.uuid"]] = info["summary.runtime.powerState"]
+ mappingToUUID[m.obj.value] = info["config.uuid"]
+
+ return (machines, uuid, mappingToUUID)
+
+def get_power_status(conn, options):
+ mo_ViewManager = Property(options["ServiceContent"].viewManager.value)
+ mo_ViewManager._type = "ViewManager"
+
+ mo_RootFolder = Property(options["ServiceContent"].rootFolder.value)
+ mo_RootFolder._type = "Folder"
+
+ mo_PropertyCollector = Property(options["ServiceContent"].propertyCollector.value)
+ mo_PropertyCollector._type = 'PropertyCollector'
+
+ ContainerView = conn.service.CreateContainerView(mo_ViewManager, recursive=1,
+ container=mo_RootFolder, type=['VirtualMachine'])
+ mo_ContainerView = Property(ContainerView.value)
+ mo_ContainerView._type = "ContainerView"
+
+ FolderTraversalSpec = conn.factory.create('ns0:TraversalSpec')
+ FolderTraversalSpec.name = "traverseEntities"
+ FolderTraversalSpec.path = "view"
+ FolderTraversalSpec.skip = False
+ FolderTraversalSpec.type = "ContainerView"
+
+ objSpec = conn.factory.create('ns0:ObjectSpec')
+ objSpec.obj = mo_ContainerView
+ objSpec.selectSet = [FolderTraversalSpec]
+ objSpec.skip = True
+
+ propSpec = conn.factory.create('ns0:PropertySpec')
+ propSpec.all = False
+ propSpec.pathSet = ["name", "summary.runtime.powerState", "config.uuid"]
+ propSpec.type = "VirtualMachine"
+
+ propFilterSpec = conn.factory.create('ns0:PropertyFilterSpec')
+ propFilterSpec.propSet = [propSpec]
+ propFilterSpec.objectSet = [objSpec]
+
+ try:
+ raw_machines = conn.service.RetrievePropertiesEx(mo_PropertyCollector, propFilterSpec)
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_STATUS)
+
+ (machines, uuid, mappingToUUID) = process_results(raw_machines, {}, {}, {})
+
+ # Probably need to loop over the ContinueRetreive if there are more results after 1 iteration.
+ while hasattr(raw_machines, 'token'):
+ try:
+ raw_machines = conn.service.ContinueRetrievePropertiesEx(mo_PropertyCollector, raw_machines.token)
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_STATUS)
+ (more_machines, more_uuid, more_mappingToUUID) = process_results(raw_machines, {}, {}, {})
+ machines.update(more_machines)
+ uuid.update(more_uuid)
+ mappingToUUID.update(more_mappingToUUID)
+ # Do not run unnecessary SOAP requests
+ if "--uuid" in options and options["--uuid"] in uuid:
+ break
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return machines
+ else:
+ if "--uuid" not in options:
+ if options["--plug"].startswith('/'):
+ ## Transform InventoryPath to UUID
+ mo_SearchIndex = Property(options["ServiceContent"].searchIndex.value)
+ mo_SearchIndex._type = "SearchIndex"
+
+ vm = conn.service.FindByInventoryPath(mo_SearchIndex, options["--plug"])
+
+ try:
+ options["--uuid"] = mappingToUUID[vm.value]
+ except KeyError:
+ fail(EC_STATUS)
+ except AttributeError:
+ fail(EC_STATUS)
+ else:
+ ## Name of virtual machine instead of path
+ ## warning: if you have same names of machines this won't work correctly
+ try:
+ (options["--uuid"], _) = machines[options["--plug"]]
+ except KeyError:
+ fail(EC_STATUS)
+ except AttributeError:
+ fail(EC_STATUS)
+
+ try:
+ if uuid[options["--uuid"]] == "poweredOn":
+ return "on"
+ else:
+ return "off"
+ except KeyError:
+ fail(EC_STATUS)
+
+def set_power_status(conn, options):
+ mo_SearchIndex = Property(options["ServiceContent"].searchIndex.value)
+ mo_SearchIndex._type = "SearchIndex"
+ vm = conn.service.FindByUuid(mo_SearchIndex, vmSearch=1, uuid=options["--uuid"])
+
+ mo_machine = Property(vm.value)
+ mo_machine._type = "VirtualMachine"
+
+ try:
+ if options["--action"] == "on":
+ conn.service.PowerOnVM_Task(mo_machine)
+ else:
+ conn.service.PowerOffVM_Task(mo_machine)
+ except suds.WebFault as ex:
+ if (str(ex).find("Permission to perform this operation was denied")) >= 0:
+ fail(EC_INVALID_PRIVILEGES)
+ else:
+ if options["--action"] == "on":
+ fail(EC_WAITING_ON)
+ else:
+ fail(EC_WAITING_OFF)
+
+def remove_tmp_dir(tmp_dir):
+ shutil.rmtree(tmp_dir)
+
+def logout():
+ try:
+ conn_global.service.Logout(options_global["mo_SessionManager"])
+ except Exception:
+ pass
+
+def signal_handler(signum, frame):
+ raise Exception("Signal \"%d\" received which has triggered an exit of the process." % signum)
+
+def main():
+ global options_global
+ global conn_global
+ device_opt = ["ipaddr", "login", "passwd", "web", "ssl", "notls", "port"]
+
+ atexit.register(atexit_handler)
+ atexit.register(logout)
+
+ signal.signal(signal.SIGTERM, signal_handler)
+
+ options_global = check_input(device_opt, process_input(device_opt))
+
+ ##
+ ## Fence agent specific defaults
+ #####
+ docs = {}
+ docs["shortdesc"] = "Fence agent for VMWare over SOAP API"
+ docs["longdesc"] = "fence_vmware_soap is an I/O Fencing agent \
+which can be used with the virtual machines managed by VMWare products \
+that have SOAP API v4.1+. \
+\n.P\n\
+Name of virtual machine (-n / port) has to be used in inventory path \
+format (e.g. /datacenter/vm/Discovered virtual machine/myMachine). \
+In the cases when name of yours VM is unique you can use it instead. \
+Alternatively you can always use UUID to access virtual machine."
+ docs["vendorurl"] = "http://www.vmware.com"
+ show_docs(options_global, docs)
+
+ logging.basicConfig(level=logging.INFO)
+ logging.getLogger('suds.client').setLevel(logging.CRITICAL)
+ logging.getLogger("requests").setLevel(logging.CRITICAL)
+ logging.getLogger("urllib3").setLevel(logging.CRITICAL)
+
+ ##
+ ## Operate the fencing device
+ ####
+ conn_global = soap_login(options_global)
+
+ result = fence_action(conn_global, options_global, set_power_status, get_power_status, get_power_status)
+
+ ## Logout from system is done automatically via atexit()
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/vmware_vcloud/fence_vmware_vcloud.py b/agents/vmware_vcloud/fence_vmware_vcloud.py
new file mode 100644
index 0000000..7626b82
--- /dev/null
+++ b/agents/vmware_vcloud/fence_vmware_vcloud.py
@@ -0,0 +1,214 @@
+#!@PYTHON@ -tt
+
+import sys
+import pycurl, io
+import logging
+import atexit
+import xml.etree.ElementTree as etree
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, run_delay, EC_LOGIN_DENIED, EC_STATUS
+
+state = {"POWERED_ON": "on", 'POWERED_OFF': "off", 'SUSPENDED': "off"}
+
+def get_power_status(conn, options):
+ try:
+ VM = send_command(conn, "vApp/vm-{}".format(options["--plug"]))
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ fail(EC_STATUS)
+
+ options["id"] = VM.attrib['href'].split('/vm-', 1)[1]
+
+ if (VM.attrib['status'] == '3'):
+ return state['SUSPENDED']
+ elif (VM.attrib['status'] == '4'):
+ return state['POWERED_ON']
+ elif (VM.attrib['status'] == '8'):
+ return state['POWERED_OFF']
+ return EC_STATUS
+
+
+def set_power_status(conn, options):
+ action = {
+ "on" : "powerOn",
+ "off" : "powerOff",
+ "shutdown": "shutdown",
+ "suspend": "suspend",
+ "reset": "reset"
+ }[options["--action"]]
+ try:
+ VM = send_command(conn, "vApp/vm-{}/power/action/{}".format(options["--plug"], action), "POST")
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ fail(EC_STATUS)
+
+def get_list(conn, options):
+ outlets = {}
+
+ VMsResponse = send_command(conn, "vms/query")
+
+ for VM in VMsResponse.iter('{http://www.vmware.com/vcloud/v1.5}VMRecord'):
+ if '/vApp/' not in VM.attrib['href']:
+ continue
+ uuid = (VM.attrib['href'].split('/vm-', 1))[1]
+ outlets['['+ uuid + '] ' + VM.attrib['containerName'] + '\\' + VM.attrib['name']] = (VM.attrib['status'], state[VM.attrib['status']])
+
+ return outlets
+
+def connect(opt):
+ conn = pycurl.Curl()
+
+ ## setup correct URL
+ if "--ssl-secure" in opt or "--ssl-insecure" in opt:
+ conn.base_url = "https:"
+ else:
+ conn.base_url = "http:"
+
+ conn.base_url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + opt["--api-path"] + "/"
+
+ ## send command through pycurl
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Accept: application/*+xml;version=1.5",
+ ])
+
+ conn.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
+ conn.setopt(pycurl.USERPWD, opt["--username"] + ":" + opt["--password"])
+
+ conn.setopt(pycurl.TIMEOUT, int(opt["--shell-timeout"]))
+ if "--ssl-secure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ elif "--ssl-insecure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+
+ headers = {}
+ try:
+ result = send_command(conn, "sessions", "POST", headers)
+ except Exception as e:
+ logging.debug("Failed: {}".format(e))
+ fail(EC_LOGIN_DENIED)
+
+ # set session id for later requests
+ conn.setopt(pycurl.HTTPHEADER, [
+ "Accept: application/*+xml;version=1.5",
+ "x-vcloud-authorization: {}".format(headers['x-vcloud-authorization']),
+ ])
+
+ return conn
+
+def disconnect(conn):
+ send_command(conn, "session", "DELETE")
+ conn.close()
+
+def parse_headers(data):
+ headers = {}
+ data = data.split("\r\n")
+ for header_line in data[1:]:
+ if ':' not in header_line:
+ break
+ name, value = header_line.split(':', 1)
+ name = name.strip()
+ value = value.strip()
+ name = name.lower()
+ headers[name] = value
+
+ return headers
+
+def send_command(conn, command, method="GET", headers={}):
+ url = conn.base_url + command
+
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+
+ web_buffer = io.BytesIO()
+ headers_buffer = io.BytesIO()
+
+ if method == "GET":
+ conn.setopt(pycurl.POST, 0)
+ elif method == "POST":
+ conn.setopt(pycurl.POSTFIELDS, "")
+ elif method == "DELETE":
+ conn.setopt(pycurl.CUSTOMREQUEST, "DELETE")
+
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+ conn.setopt(pycurl.HEADERFUNCTION, headers_buffer.write)
+
+ try:
+ conn.perform()
+ except Exception as e:
+ raise(e)
+
+ rc = conn.getinfo(pycurl.HTTP_CODE)
+ result = web_buffer.getvalue().decode()
+ headers.update(parse_headers(headers_buffer.getvalue().decode()))
+
+ headers_buffer.close()
+ web_buffer.close()
+
+ if len(result) > 0:
+ result = etree.fromstring(result)
+
+ if rc != 200 and rc != 202 and rc != 204:
+ if len(result) > 0:
+ raise Exception("{}: {}".format(rc, result["value"]["messages"][0]["default_message"]))
+ else:
+ raise Exception("Remote returned {} for request to {}".format(rc, url))
+
+ logging.debug("url: {}".format(url))
+ logging.debug("method: {}".format(method))
+ logging.debug("response code: {}".format(rc))
+ logging.debug("result: {}\n".format(result))
+
+ return result
+
+def define_new_opts():
+ all_opt["api_path"] = {
+ "getopt" : ":",
+ "longopt" : "api-path",
+ "help" : "--api-path=[path] The path part of the API URL",
+ "default" : "/api",
+ "required" : "0",
+ "shortdesc" : "The path part of the API URL",
+ "order" : 2}
+
+def main():
+ device_opt = [
+ "ipaddr",
+ "api_path",
+ "login",
+ "passwd",
+ "ssl",
+ "notls",
+ "web",
+ "port",
+ ]
+
+ atexit.register(atexit_handler)
+ define_new_opts()
+
+ all_opt["shell_timeout"]["default"] = "5"
+ all_opt["power_wait"]["default"] = "1"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for VMware vCloud Director API"
+ docs["longdesc"] = "fence_vmware_vcloud is an I/O Fencing agent which can be used with VMware vCloud Director API to fence virtual machines."
+ docs["vendorurl"] = "https://www.vmware.com"
+ show_docs(options, docs)
+
+ ####
+ ## Fence operations
+ ####
+ run_delay(options)
+
+ conn = connect(options)
+ atexit.register(disconnect, conn)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_list)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/wti/fence_wti.py b/agents/wti/fence_wti.py
new file mode 100644
index 0000000..97cc66d
--- /dev/null
+++ b/agents/wti/fence_wti.py
@@ -0,0 +1,240 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Version Firmware
+## +-----------------+---------------------------+
+## WTI RSM-8R4 ?? unable to find out ??
+## WTI MPC-??? ?? unable to find out ??
+## WTI IPS-800-CE v1.40h (no username) ('list' tested)
+#####
+
+import sys, re, pexpect
+import atexit
+import time
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fspawn, fail, fail_usage, EC_LOGIN_DENIED
+
+def get_listing(conn, options, listing_command):
+ listing = ""
+
+ conn.send_eol(listing_command)
+
+ if isinstance(options["--command-prompt"], list):
+ re_all = list(options["--command-prompt"])
+ else:
+ re_all = [options["--command-prompt"]]
+ re_next = re.compile("Enter: ", re.IGNORECASE)
+ re_all.append(re_next)
+
+ result = conn.log_expect(re_all, int(options["--shell-timeout"]))
+ listing = conn.before
+ if result == (len(re_all) - 1):
+ conn.send_eol("")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ listing += conn.before
+
+ return listing
+
+def get_plug_status(conn, options):
+ listing = get_listing(conn, options, "/S")
+
+ plug_section = 0
+ plug_index = -1
+ name_index = -1
+ status_index = -1
+ plug_header = list()
+ outlets = {}
+
+ for line in listing.splitlines():
+ if (plug_section == 2) and line.find("|") >= 0 and line.startswith("PLUG") == False:
+ plug_line = [x.strip().lower() for x in line.split("|")]
+ if len(plug_line) < len(plug_header):
+ plug_section = -1
+ if ["list", "monitor"].count(options["--action"]) == 0 and \
+ options["--plug"].lower() == plug_line[plug_index]:
+ return plug_line[status_index]
+ else:
+ ## We already believe that first column contains plug number
+ if len(plug_line[0]) != 0:
+ outlets[plug_line[0]] = (plug_line[name_index], plug_line[status_index])
+ elif plug_section == 1:
+ plug_section = 2
+ elif line.upper().startswith("PLUG"):
+ plug_section = 1
+ plug_header = [x.strip().lower() for x in line.split("|")]
+ plug_index = plug_header.index("plug")
+ name_index = plug_header.index("name")
+ status_index = plug_header.index("status")
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ return "PROBLEM"
+
+def get_plug_group_status_from_list(status_list):
+ for status in status_list:
+ if status == "on":
+ return status
+ return "off"
+
+def get_plug_group_status(conn, options):
+ listing = get_listing(conn, options, "/SG")
+
+ outlets = {}
+ line_index = 0
+ status_index = -1
+ plug_index = -1
+ name_index = -1
+
+ lines = listing.splitlines()
+ while line_index < len(lines) and line_index >= 0:
+ line = lines[line_index]
+ if line.find("|") >= 0 and line.lstrip().startswith("GROUP NAME") == False:
+ plug_line = [x.strip().lower() for x in line.split("|")]
+ if ["list", "monitor"].count(options["--action"]) == 0 and \
+ options["--plug"].lower() == plug_line[name_index]:
+ plug_status = []
+ while line_index < len(lines) and line_index >= 0:
+ plug_line = [x.strip().lower() for x in lines[line_index].split("|")]
+ if len(plug_line) >= max(name_index, status_index) and \
+ len(plug_line[plug_index]) > 0 and \
+ (len(plug_line[name_index]) == 0 or options["--plug"].lower() == plug_line[name_index]):
+ ## Firmware 1.43 does not have a valid value of plug on first line as only name is defined on that line
+ if not "---" in plug_line[status_index]:
+ plug_status.append(plug_line[status_index])
+ line_index += 1
+ else:
+ line_index = -1
+
+ return get_plug_group_status_from_list(plug_status)
+
+ else:
+ ## We already believe that first column contains plug number
+ if len(plug_line[0]) != 0:
+ group_name = plug_line[0]
+ plug_line_index = line_index + 1
+ plug_status = []
+ while plug_line_index < len(lines) and plug_line_index >= 0:
+ plug_line = [x.strip().lower() for x in lines[plug_line_index].split("|")]
+ if len(plug_line[name_index]) > 0:
+ plug_line_index = -1
+ break
+ if len(plug_line[plug_index]) > 0:
+ plug_status.append(plug_line[status_index])
+ plug_line_index += 1
+ else:
+ plug_line_index = -1
+ outlets[group_name] = (group_name, get_plug_group_status_from_list(plug_status))
+ line_index += 1
+
+ elif line.upper().lstrip().startswith("GROUP NAME"):
+ plug_header = [x.strip().lower() for x in line.split("|")]
+ name_index = plug_header.index("group name")
+ plug_index = plug_header.index("plug")
+ status_index = plug_header.index("status")
+ line_index += 2
+ else:
+ line_index += 1
+
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ results = {}
+ for group, status in list(outlets.items()):
+ results[group] = (group, status[0])
+
+ return results
+ else:
+ return "PROBLEM"
+
+def get_power_status(conn, options):
+ if ["list"].count(options["--action"]) == 0:
+ ret = get_plug_status(conn, options)
+
+ if ret == "PROBLEM":
+ ret = get_plug_group_status(conn, options)
+ else:
+ ret = dict(list(get_plug_status(conn, options).items()) + \
+ list(get_plug_group_status(conn, options).items()))
+
+ return ret
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "/on",
+ 'off': "/off"
+ }[options["--action"]]
+
+ conn.send_eol(action + " " + options["--plug"] + ",y")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "cmd_prompt", "secure", "port", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["RSM>", "MPC>", "IPS>", "TPS>", "NBB>", "NPS>", "VMR>"]
+ all_opt["login_timeout"]["default"] = "10"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for WTI"
+ docs["longdesc"] = "fence_wti is an I/O Fencing agent \
+which can be used with the WTI Network Power Switch (NPS). It logs \
+into an NPS via telnet or ssh and boots a specified plug. \
+Lengthy telnet connections to the NPS should be avoided while a GFS cluster \
+is running because the connection will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.wti.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ##
+ ## @note: if it possible that this device does not need either login, password or both of them
+ #####
+ if "--ssh" not in options:
+ try:
+ if options["--action"] in ["off", "reboot"]:
+ time.sleep(int(options["--delay"]))
+
+ options["eol"] = "\r\n"
+
+ conn = fspawn(options, options["--telnet-path"])
+ conn.send("set binary\n")
+ conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
+
+ re_login = re.compile("(login: )|(Login Name: )|(username: )|(User Name :)", re.IGNORECASE)
+ re_prompt = re.compile("|".join(["(" + x + ")" for x in options["--command-prompt"]]), re.IGNORECASE)
+
+ result = conn.log_expect([re_login, "Password: ", re_prompt], int(options["--shell-timeout"]))
+ if result == 0:
+ if "--username" in options:
+ conn.send_eol(options["--username"])
+ result = conn.log_expect([re_login, "Password: ", re_prompt], int(options["--shell-timeout"]))
+ else:
+ fail_usage("Failed: You have to set login name")
+
+ if result == 1:
+ if "--password" in options:
+ conn.send_eol(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ else:
+ fail_usage("Failed: You have to enter password or password script")
+ except pexpect.EOF:
+ fail(EC_LOGIN_DENIED)
+ except pexpect.TIMEOUT:
+ fail(EC_LOGIN_DENIED)
+ else:
+ conn = fence_login(options)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ fence_logout(conn, "/X")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/xenapi/fence_xenapi.py b/agents/xenapi/fence_xenapi.py
new file mode 100644
index 0000000..10c8ee0
--- /dev/null
+++ b/agents/xenapi/fence_xenapi.py
@@ -0,0 +1,221 @@
+#!@PYTHON@ -tt
+#
+#############################################################################
+# Copyright 2011 Matthew Clark
+# This file is part of fence-xenserver
+#
+# fence-xenserver 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.
+#
+# fence-xenserver 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/>.
+
+# Please let me know if you are using this script so that I can work out
+# whether I should continue support for it. mattjclark0407 at hotmail dot com
+#############################################################################
+
+#############################################################################
+# It's only just begun...
+# Current status: completely usable. This script is now working well and,
+# has a lot of functionality as a result of the fencing.py library and the
+# XenAPI libary.
+
+#############################################################################
+# Please let me know if you are using this script so that I can work out
+# whether I should continue support for it. mattjclark0407 at hotmail dot com
+
+import sys
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import run_delay
+import XenAPI
+
+EC_BAD_SESSION = 1
+# Find the status of the port given in the -U flag of options.
+def get_power_fn(session, options):
+ if "--verbose" in options:
+ verbose = True
+ else:
+ verbose = False
+
+ try:
+ # Get a reference to the vm specified in the UUID or vm_name/port parameter
+ vm = return_vm_reference(session, options)
+ # Query the VM for its' associated parameters
+ record = session.xenapi.VM.get_record(vm)
+ # Check that we are not trying to manipulate a template or a control
+ # domain as they show up as VM's with specific properties.
+ if not record["is_a_template"] and not record["is_control_domain"]:
+ status = record["power_state"]
+ if verbose:
+ print("UUID:", record["uuid"], "NAME:", record["name_label"], "POWER STATUS:", record["power_state"])
+ # Note that the VM can be in the following states (from the XenAPI document)
+ # Halted: VM is offline and not using any resources.
+ # Paused: All resources have been allocated but the VM itself is paused and its vCPUs are not running
+ # Running: Running
+ # Paused: VM state has been saved to disk and it is nolonger running. Note that disks remain in-Use while
+ # We want to make sure that we only return the status "off" if the machine is actually halted as the status
+ # is checked before a fencing action. Only when the machine is Halted is it not consuming resources which
+ # may include whatever you are trying to protect with this fencing action.
+ return status == "Halted" and "off" or "on"
+ except Exception as exn:
+ print(str(exn))
+
+ return "Error"
+
+# Set the state of the port given in the -U flag of options.
+def set_power_fn(session, options):
+ try:
+ # Get a reference to the vm specified in the UUID or vm_name/port parameter
+ vm = return_vm_reference(session, options)
+ # Query the VM for its' associated parameters
+ record = session.xenapi.VM.get_record(vm)
+ # Check that we are not trying to manipulate a template or a control
+ # domain as they show up as VM's with specific properties.
+ if not record["is_a_template"] and not record["is_control_domain"]:
+ if options["--action"] == "on":
+ # Start the VM
+ session.xenapi.VM.start(vm, False, True)
+ elif options["--action"] == "off":
+ # Force shutdown the VM
+ session.xenapi.VM.hard_shutdown(vm)
+ elif options["--action"] == "reboot":
+ # Force reboot the VM
+ session.xenapi.VM.hard_reboot(vm)
+ except Exception as exn:
+ print(str(exn))
+
+# Function to populate an array of virtual machines and their status
+def get_outlet_list(session, options):
+ result = {}
+ if "--verbose" in options:
+ verbose = True
+ else:
+ verbose = False
+
+ try:
+ # Return an array of all the VM's on the host
+ vms = session.xenapi.VM.get_all()
+ for vm in vms:
+ # Query the VM for its' associated parameters
+ record = session.xenapi.VM.get_record(vm)
+ # Check that we are not trying to manipulate a template or a control
+ # domain as they show up as VM's with specific properties.
+ if not record["is_a_template"] and not record["is_control_domain"]:
+ name = record["name_label"]
+ uuid = record["uuid"]
+ status = record["power_state"]
+ result[uuid] = (name, status)
+ if verbose:
+ print("UUID:", record["uuid"], "NAME:", name, "POWER STATUS:", record["power_state"])
+ except Exception as exn:
+ print(str(exn))
+
+ return result
+
+# Function to initiate the XenServer session via the XenAPI library.
+def connect_and_login(options):
+ url = options["--session-url"]
+ username = options["--username"]
+ password = options["--password"]
+
+ try:
+ # Create the XML RPC session to the specified URL.
+ session = XenAPI.Session(url)
+ # Login using the supplied credentials.
+ session.xenapi.login_with_password(username, password)
+ except Exception as exn:
+ print(str(exn))
+ # http://sources.redhat.com/cluster/wiki/FenceAgentAPI says that for no connectivity
+ # the exit value should be 1. It doesn't say anything about failed logins, so
+ # until I hear otherwise it is best to keep this exit the same to make sure that
+ # anything calling this script (that uses the same information in the web page
+ # above) knows that this is an error condition, not a msg signifying a down port.
+ sys.exit(EC_BAD_SESSION)
+ return session
+
+# return a reference to the VM by either using the UUID or the vm_name/port. If the UUID is set then
+# this is tried first as this is the only properly unique identifier.
+# Exceptions are not handled in this function, code that calls this must be ready to handle them.
+def return_vm_reference(session, options):
+ if "--verbose" in options:
+ verbose = True
+ else:
+ verbose = False
+
+ # Case where the UUID has been specified
+ if "--uuid" in options:
+ uuid = options["--uuid"].lower()
+ # When using the -n parameter for name, we get an error message (in verbose
+ # mode) that tells us that we didn't find a VM. To immitate that here we
+ # need to catch and re-raise the exception produced by get_by_uuid.
+ try:
+ return session.xenapi.VM.get_by_uuid(uuid)
+ except Exception:
+ if verbose:
+ print("No VM's found with a UUID of \"%s\"" % uuid)
+ raise
+
+ # Case where the vm_name/port has been specified
+ if "--plug" in options:
+ vm_name = options["--plug"]
+ vm_arr = session.xenapi.VM.get_by_name_label(vm_name)
+ # Need to make sure that we only have one result as the vm_name may
+ # not be unique. Average case, so do it first.
+ if len(vm_arr) == 1:
+ return vm_arr[0]
+ else:
+ if len(vm_arr) == 0:
+ if verbose:
+ print("No VM's found with a name of \"%s\"" % vm_name)
+ # NAME_INVALID used as the XenAPI throws a UUID_INVALID if it can't find
+ # a VM with the specified UUID. This should make the output look fairly
+ # consistent.
+ raise Exception("NAME_INVALID")
+ else:
+ if verbose:
+ print("Multiple VM's have the name \"%s\", use UUID instead" % vm_name)
+ raise Exception("MULTIPLE_VMS_FOUND")
+
+ # We should never get to this case as the input processing checks that either the UUID or
+ # the name parameter is set. Regardless of whether or not a VM is found the above if
+ # statements will return to the calling function (either by exception or by a reference
+ # to the VM).
+ raise Exception("VM_LOGIC_ERROR")
+
+def main():
+
+ device_opt = ["login", "passwd", "port", "no_login", "no_password", "session_url", "web"]
+
+ atexit.register(atexit_handler)
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for Citrix XenServer over XenAPI"
+ docs["longdesc"] = "\
+fence_cxs is an I/O Fencing agent used on Citrix XenServer hosts. \
+It uses the XenAPI, supplied by Citrix, to establish an XML-RPC session \
+to a XenServer host. Once the session is established, further XML-RPC \
+commands are issued in order to switch on, switch off, restart and query \
+the status of virtual machines running on the host."
+ docs["vendorurl"] = "http://www.xenproject.org"
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ xen_session = connect_and_login(options)
+ result = fence_action(xen_session, options, set_power_fn, get_power_fn, get_outlet_list)
+
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/agents/zvm/fence_zvm.c b/agents/zvm/fence_zvm.c
new file mode 100644
index 0000000..6f1469e
--- /dev/null
+++ b/agents/zvm/fence_zvm.c
@@ -0,0 +1,1056 @@
+/*
+ * fence_zvm.c: SMAPI interface for managing zVM Guests
+ *
+ * Copyright (C) 2012 Sine Nomine Associates
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Neale Ferguson <neale@sinenomine.net>
+ *
+ */
+
+#ifdef __s390__
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netiucv/iucv.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <syslog.h>
+#include "fence_zvm.h"
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define DEFAULT_TIMEOUT 300
+#define DEFAULT_DELAY 0
+
+#define ACT_OFFON 0
+#define ACT_OFF 1
+#define ACT_ON 2
+#define ACT_METADATA 3
+#define ACT_STATUS 4
+#define ACT_MONITOR 5
+#define ACT_LIST 6
+#define ACT_HELP 7
+
+static int zvm_smapi_reportError (void *, void *);
+
+static struct option longopts[] = {
+ {"action", required_argument, NULL, 'o'},
+ {"delay", required_argument, NULL, 'h'},
+ {"help", no_argument, NULL, 'h'},
+ {"ip", required_argument, NULL, 'a'},
+ {"plug", required_argument, NULL, 'n'},
+ {"timeout", required_argument, NULL, 'T'},
+ {"zvmsys", required_argument, NULL, 'z'},
+ {NULL, 0, NULL, 0}
+};
+
+static const char *optString = "a:ho:n:T:";
+
+static int zvm_metadata (void);
+static int usage (void);
+
+/**
+ * zvm_smapi_open:
+ * @zvm: z/VM driver information
+ *
+ * Opens a connection with the z/VM SMAPI server
+ */
+int
+zvm_smapi_open (zvm_driver_t * zvm)
+{
+ int rc = -1, sockaddrlen;
+ static char iucvprog[9] = "DMSRSRQU\0";
+ struct sockaddr_iucv siucv_addr;
+ const struct sockaddr *siucv_ptr = (void *) &siucv_addr;
+
+ if ((zvm->sd = socket (AF_IUCV, SOCK_STREAM, IPPROTO_IP)) != -1) {
+ memset (&siucv_addr, 0, sizeof (siucv_addr));
+ siucv_addr.siucv_family = AF_IUCV;
+ siucv_addr.siucv_port = 0;
+ siucv_addr.siucv_addr = 0;
+ memset (&siucv_addr.siucv_nodeid, ' ', 8);
+ memset (&siucv_addr.siucv_user_id, ' ', 8);
+ memset (&siucv_addr.siucv_name, ' ', 8);
+ sockaddrlen = sizeof (siucv_addr);
+ if ((rc = bind (zvm->sd, siucv_ptr, sockaddrlen)) != -1) {
+ memcpy (&siucv_addr.siucv_user_id, zvm->smapiSrv,
+ strlen (zvm->smapiSrv));
+ memcpy (&siucv_addr.siucv_name, &iucvprog, 8);
+ memcpy (&siucv_addr.siucv_nodeid, zvm->node,
+ strlen (zvm->node));
+ rc = connect (zvm->sd,
+ (__CONST_SOCKADDR_ARG) siucv_ptr,
+ sockaddrlen);
+ }
+ if (rc == -1) {
+ syslog (LOG_ERR, "Error connecting to %s - %m",
+ zvm->smapiSrv);
+ close (zvm->sd);
+ }
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageRecycle
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageRecycle (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[13];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist = sizeof (*inPlist) + strlen (zvm->target);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Recycle,
+ sizeof (inPlist->fName));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog (LOG_INFO,
+ "Recycling of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ if ((outPlist->hdr.rc ==
+ RCERR_IMAGEOP) & ((outPlist->hdr.
+ reason ==
+ RS_NOT_ACTIVE)
+ | (outPlist->
+ hdr.
+ reason ==
+ RS_BEING_DEACT)))
+ {
+ syslog (LOG_INFO,
+ "Recycling of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ rc = outPlist->hdr.rc;
+ zvm->reason =
+ outPlist->hdr.reason;
+ (void) zvm_smapi_reportError
+ (inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageDeactivate
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageDeactivate (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[16];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ struct _deactTime
+ {
+ int32_t lForceTime;
+ char forceTime[5];
+ } __attribute__((__packed__)) * deactTime;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist =
+ sizeof (*inPlist) + strlen (zvm->target) +
+ sizeof (*deactTime);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Deactivate,
+ sizeof (inPlist->fName));
+ deactTime =
+ (void *) ((intptr_t) inPlist + sizeof (*inPlist) +
+ strlen (zvm->target));
+ deactTime->lForceTime = sizeof (deactTime->forceTime);
+ memcpy (deactTime->forceTime, "IMMED",
+ sizeof (deactTime->forceTime));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog (LOG_INFO,
+ "Deactivation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ if ((outPlist->hdr.rc ==
+ RCERR_IMAGEOP) & ((outPlist->hdr.
+ reason ==
+ RS_NOT_ACTIVE)
+ | (outPlist->
+ hdr.
+ reason ==
+ RS_BEING_DEACT)))
+ {
+ syslog (LOG_INFO,
+ "Deactivation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ rc = outPlist->hdr.rc;
+ zvm->reason =
+ outPlist->hdr.reason;
+ (void) zvm_smapi_reportError
+ (inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageActivate
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageActivate (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[14];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist = sizeof (*inPlist) + strlen (zvm->target);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Activate,
+ sizeof (inPlist->fName));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog (LOG_INFO,
+ "Activation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ if ((outPlist->hdr.rc ==
+ RCERR_IMAGEOP) & (outPlist->hdr.
+ reason ==
+ RS_ALREADY_ACTIVE))
+ {
+ syslog (LOG_INFO,
+ "Activation of %s successful",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ rc = outPlist->hdr.rc;
+ zvm->reason =
+ outPlist->hdr.reason;
+ (void) zvm_smapi_reportError
+ (inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_imageQuery
+ * @zvm: z/VM driver information
+ *
+ * Queries the state of a virtual image
+ */
+int
+zvm_smapi_imageQuery (zvm_driver_t * zvm)
+{
+ struct _inPlist
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[18];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__((__packed__)) * inPlist;
+ int32_t lInPlist;
+ struct _outPlist
+ {
+ smapiOutHeader_t hdr;
+ int32_t lNames;
+ char nameArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep (zvm->delay);
+
+ lInPlist = sizeof (*inPlist) + strlen (zvm->target);
+ inPlist = malloc (lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof (inPlist->lPlist);
+ inPlist->lFName = sizeof (inPlist->fName);
+ memcpy (inPlist->fName, Image_Status_Query,
+ sizeof (inPlist->fName));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen (zvm->target);
+ memcpy (inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc =
+ zvm_smapi_send (zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv (zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ if (outPlist->hdr.reason == 0) {
+ syslog (LOG_INFO,
+ "Node %s is active",
+ zvm->target);
+ rc = 0;
+ }
+ else {
+ syslog (LOG_INFO,
+ "Node %s is inactive",
+ zvm->target);
+ rc = 2;
+ }
+ }
+ else {
+ rc = 1;
+ zvm->reason = outPlist->hdr.reason;
+ (void) zvm_smapi_reportError (inPlist,
+ outPlist);
+ }
+ }
+ }
+ free (inPlist);
+ free (outPlist);
+ }
+ else {
+ syslog (LOG_ERR, "%s - cannot allocate parameter list",
+ __func__);
+ rc = -1;
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_send:
+ * @zvm: z/VM driver information
+ * @reqid: Returned request id
+ * @req: Request parameter list
+ * @lSend: Length of request
+ *
+ * Send a request to the SMAPI server and retrieve the request id
+ */
+int
+zvm_smapi_send (zvm_driver_t * zvm, void *req, uint32_t * reqId,
+ int32_t lSend)
+{
+ int rc, nFds;
+ fd_set readFds;
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ zvm->reason = -1;
+ if ((rc = zvm_smapi_open (zvm)) == 0) {
+ rc = send (zvm->sd, req, lSend, 0);
+ if (rc != -1) {
+ FD_ZERO (&readFds);
+ FD_SET (zvm->sd, &readFds);
+ nFds = zvm->sd + 1;
+
+ if ((rc =
+ select (nFds, &readFds, NULL, NULL,
+ &timeout)) != -1) {
+ /*
+ * Get request ID
+ */
+ rc = recv (zvm->sd, reqId, sizeof (*reqId),
+ 0);
+ if (rc == -1)
+ syslog (LOG_ERR,
+ "Error receiving from SMAPI - %m");
+ }
+ }
+ else
+ syslog (LOG_ERR, "Error sending to SMAPI - %m");
+ }
+ return (rc);
+}
+
+/**
+ * zvm_smapi_recv:
+ * @zvm: z/VM driver information
+ * @req: Returned response parameter list
+ * @lRsp: Length of response
+ *
+ * Receive a response from the SMAPI server
+ */
+int
+zvm_smapi_recv (zvm_driver_t * zvm, void **rsp, int32_t * lRsp)
+{
+ int rc, lRem = 0, nFds;
+ void *pRecv = rsp;
+ fd_set readFds;
+ smapiOutHeader_t *out;
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ FD_ZERO (&readFds);
+ FD_SET (zvm->sd, &readFds);
+ nFds = zvm->sd + 1;
+
+ zvm->reason = -1;
+ if ((rc = select (nFds, &readFds, NULL, NULL, &timeout)) != -1) {
+ /*
+ * Get response length
+ */
+ if ((rc = recv (zvm->sd, lRsp, sizeof (*lRsp), 0)) != -1) {
+ lRem = *lRsp;
+ if (*rsp == NULL)
+ *rsp = malloc (*lRsp + sizeof (out->outLen));
+ out = *rsp;
+ out->outLen = *lRsp;
+ pRecv = &out->reqId;
+ while (lRem > 0) {
+ if ((rc =
+ recv (zvm->sd, pRecv, lRem, 0)) != -1) {
+ lRem -= rc;
+ pRecv = (void *) ((uintptr_t) pRecv +
+ rc);
+ }
+ else
+ syslog (LOG_ERR,
+ "Error receiving from SMAPI - %m");
+ (void) zvm_smapi_close (zvm);
+ return (rc);
+ }
+ zvm->reason = out->reason;
+ }
+ }
+ else
+ syslog (LOG_ERR, "Error receiving from SMAPI - %m");
+
+ (void) zvm_smapi_close (zvm);
+
+ return (rc);
+}
+
+/**
+ * zvm_smapi_close:
+ * @zvm: z/VM driver information
+ *
+ * Close a connection with the z/VM SMAPI server
+ */
+int
+zvm_smapi_close (zvm_driver_t * zvm)
+{
+ close (zvm->sd);
+ return (0);
+}
+
+/**
+ * zvm_smapi_reportError
+ * @inHdr - Input parameter list header
+ * @outHdr - Output parameter list header
+ *
+ * Report an error from the SMAPI server
+ */
+static int
+zvm_smapi_reportError (void *inHdr, void *oHdr)
+{
+ struct _inParm
+ {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[0];
+ } *inParm = inHdr;
+ smapiOutHeader_t *outHdr = oHdr;
+ char fName[64];
+
+ memset (fName, 0, sizeof (fName));
+ memcpy (fName, inParm->fName, inParm->lFName);
+ syslog (LOG_ERR, "%s - returned (%d,%d)",
+ fName, outHdr->rc, outHdr->reason);
+ return (-1);
+}
+
+
+/**
+ * trim - Trim spaces from string
+ * @str - Pointer to string
+ *
+ */
+static int
+trim (char *str)
+{
+ char *p;
+ int len;
+
+ if (!str)
+ return (0);
+
+ len = strlen (str);
+
+ while (len--) {
+ if (isspace (str[len])) {
+ str[len] = 0;
+ }
+ else {
+ break;
+ }
+ }
+
+ for (p = str; *p && isspace (*p); p++);
+
+ memmove (str, p, strlen (p) + 1);
+
+ return (strlen (str));
+}
+
+/**
+ * zvm_metadata - Show fence metadata
+ * @self - Path to this executable
+ *
+ */
+static int
+zvm_metadata ()
+{
+ fprintf (stdout, "<?xml version=\"1.0\" ?>\n");
+ fprintf (stdout, "<resource-agent name=\"fence_zvm\"");
+ fprintf (stdout,
+ " shortdesc=\"Fence agent for use with z/VM Virtual Machines\">\n");
+ fprintf (stdout, "<longdesc>");
+ fprintf (stdout,
+ "The fence_zvm agent is intended to be used with with z/VM SMAPI service.");
+ fprintf (stdout, "</longdesc>\n");
+ fprintf (stdout, "<vendor-url>http://www.ibm.com</vendor-url>\n");
+
+ fprintf (stdout, "<parameters>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"port\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-n, --plug\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Name of the Virtual Machine to be fenced");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"ipaddr\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-a, --ip\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Name of the SMAPI IUCV Server Virtual Machine");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"zvmsys\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"--zvmsys\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Node of the SMAPI IUCV Server Virtual Machine");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"action\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-o, --action\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"off\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Fencing action");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"delay\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"--delay\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"0\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Time to delay fencing action in seconds");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout,
+ "\t<parameter name=\"usage\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-h, --help\" />\n");
+ fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Print usage");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "</parameters>\n");
+
+ fprintf (stdout, "<actions>\n");
+ fprintf (stdout, "\t<action name=\"off\" />\n");
+ fprintf (stdout, "\t<action name=\"on\" automatic=\"0\" />\n");
+ fprintf (stdout, "\t<action name=\"list\" />\n");
+ fprintf (stdout, "\t<action name=\"metadata\" />\n");
+ fprintf (stdout, "\t<action name=\"monitor\" />\n");
+ fprintf (stdout, "\t<action name=\"reboot\" />\n");
+ fprintf (stdout, "\t<action name=\"status\" />\n");
+ fprintf (stdout, "</actions>\n");
+
+ fprintf (stdout, "</resource-agent>\n");
+
+ return (0);
+
+}
+
+/**
+ * get_options_stdin - get options from stdin
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+get_options_stdin (zvm_driver_t * zvm)
+{
+ char buf[1024], *endPtr, *opt, *arg;
+ int32_t lSrvName, lSrvNode, lTarget;
+ int fence = ACT_OFFON;
+
+ while (fgets (buf, sizeof (buf), stdin) != 0) {
+ if (trim (buf) == 0) {
+ continue;
+ }
+ if (buf[0] == '#') {
+ continue;
+ }
+
+ opt = buf;
+
+ if ((arg = strchr (opt, '=')) != 0) {
+ *arg = 0;
+ arg++;
+ }
+ else {
+ continue;
+ }
+
+ if (trim (arg) == 0)
+ continue;
+
+ if (!strcasecmp (opt, "action")) {
+ if (strcasecmp (arg, "reboot") == 0) {
+ fence = ACT_OFFON;
+ }
+ else if (strcasecmp (arg, "off") == 0) {
+ fence = ACT_OFF;
+ }
+ else if (strcasecmp (arg, "on") == 0) {
+ fence = ACT_ON;
+ }
+ else if (strcasecmp (arg, "metadata") == 0) {
+ fence = ACT_METADATA;
+ }
+ else if (strcasecmp (arg, "status") == 0) {
+ fence = ACT_STATUS;
+ }
+ else if (strcasecmp (arg, "monitor") == 0) {
+ fence = ACT_MONITOR;
+ }
+ else if (strcasecmp (arg, "list") == 0) {
+ fence = ACT_LIST;
+ }
+ else {
+ fence = ACT_HELP;
+ }
+ }
+ else if (!strcasecmp (opt, "ipaddr")) {
+ lSrvName = MIN (strlen (arg), sizeof (zvm->smapiSrv));
+ memcpy (zvm->smapiSrv, arg, lSrvName);
+ continue;
+ }
+ else if (!strcasecmp (opt, "port")) {
+ lTarget =
+ MIN (strlen (arg), sizeof (zvm->target) - 1);
+ strncpy (zvm->target, arg, lTarget);
+ continue;
+ }
+ else if (!strcasecmp (opt, "timeout")) {
+ zvm->timeOut = strtoul (arg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid timeout value specified %s "
+ "defaulting to %d", arg,
+ DEFAULT_DELAY);
+ zvm->timeOut = DEFAULT_DELAY;
+ }
+ }
+ else if (!strcasecmp (opt, "zvmsys")) {
+ lSrvNode = MIN (strlen (arg), sizeof (zvm->node));
+ memcpy (zvm->node, arg, lSrvNode);
+ continue;
+ }
+ else if (!strcasecmp (opt, "delay")) {
+ zvm->delay = strtoul (arg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid delay value specified %s "
+ "defaulting to %d", arg,
+ DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
+ }
+ else if (!strcasecmp (opt, "help")) {
+ fence = ACT_HELP;
+ }
+ }
+ return (fence);
+}
+
+/**
+ * get_options - get options from the command line
+ * @argc - Count of arguments
+ * @argv - Array of character strings
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+get_options (int argc, char **argv, zvm_driver_t * zvm)
+{
+ int c, fence = ACT_OFFON;
+ int32_t lSrvName, lSrvNode, lTarget;
+ char *endPtr;
+
+ while ((c =
+ getopt_long (argc, argv, optString, longopts, NULL)) != -1) {
+ switch (c) {
+ case 'n':
+ lTarget = MIN (strlen (optarg), sizeof (zvm->target));
+ memcpy (zvm->target, optarg, lTarget);
+ break;
+ case 'o':
+ if (strcasecmp (optarg, "reboot") == 0) {
+ fence = ACT_OFFON;
+ }
+ else if (strcasecmp (optarg, "off") == 0) {
+ fence = ACT_OFF;
+ }
+ else if (strcasecmp (optarg, "on") == 0) {
+ fence = ACT_ON;
+ }
+ else if (strcasecmp (optarg, "metadata") == 0) {
+ fence = ACT_METADATA;
+ }
+ else if (strcasecmp (optarg, "status") == 0) {
+ fence = ACT_STATUS;
+ }
+ else if (strcasecmp (optarg, "monitor") == 0) {
+ fence = ACT_MONITOR;
+ }
+ else if (strcasecmp (optarg, "list") == 0) {
+ fence = ACT_LIST;
+ }
+ else {
+ fence = ACT_HELP;
+ }
+ break;
+ case 'a':
+ lSrvName =
+ MIN (strlen (optarg), sizeof (zvm->smapiSrv));
+ memcpy (zvm->smapiSrv, optarg, lSrvName);
+ break;
+ case 'T':
+ zvm->timeOut = strtoul (optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid timeout value specified: %s - "
+ "defaulting to %d", optarg,
+ DEFAULT_TIMEOUT);
+ zvm->timeOut = DEFAULT_TIMEOUT;
+ }
+ break;
+ case 'd':
+ zvm->delay = strtoul (optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog (LOG_WARNING,
+ "Invalid delay value specified: %s - "
+ "defaulting to %d", optarg,
+ DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
+ break;
+ case 'z':
+ lSrvNode = MIN (strlen (optarg), sizeof (zvm->node));
+ memcpy (zvm->node, optarg, lSrvNode);
+ break;
+ default:
+ fence = ACT_HELP;
+ }
+ }
+ return (fence);
+}
+
+/**
+ * usage - display command syntax and parameters
+ *
+ */
+static int
+usage ()
+{
+ printf ("Usage: fence_zvm [options]\n\n"
+ "\tWhere [options] =\n"
+ "\t-o --action [action] - \"off\", \"on\", \"list\", \"metadata\", "
+ "\"monitor\", \"reboot\", \"status\"\n"
+ "\t--delay [seconds] - Time to delay fencing action in seconds\n"
+ "\t-n --plug [target] - Name of virtual machine to fence\n"
+ "\t-a --ip [server] - Name of SMAPI IUCV Request server\n"
+ "\t-T --timeout [secs] - Time to wait for fence in seconds - currently ignored\n"
+ "\t--zvmsys [node] - z/VM Node on which SMAPI server lives\n"
+ "\t-h --help - Display this usage information\n");
+ return (0);
+}
+
+/**
+ * check_param - Check that mandatory parameters have been specified
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+check_parm (zvm_driver_t * zvm)
+{
+ int rc;
+
+ if (zvm->smapiSrv[0] != 0) {
+ if (zvm->target[0] != 0) {
+ rc = 0;
+ }
+ else {
+ syslog (LOG_ERR, "Missing fence target name");
+ rc = 2;
+ }
+ }
+ else {
+ syslog (LOG_ERR, "Missing SMAPI server name");
+ rc = 1;
+ }
+ return (rc);
+}
+
+int
+main (int argc, char **argv)
+{
+ zvm_driver_t zvm;
+ int fence, rc = 0;
+
+ openlog ("fence_zvm", LOG_CONS | LOG_PID, LOG_DAEMON);
+ memset (&zvm, 0, sizeof (zvm));
+ zvm.timeOut = DEFAULT_TIMEOUT;
+ zvm.delay = DEFAULT_DELAY;
+
+ if (argc > 1)
+ fence = get_options (argc, argv, &zvm);
+ else
+ fence = get_options_stdin (&zvm);
+
+ switch (fence) {
+ case ACT_OFFON: // OFFON
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageRecycle (&zvm);
+ break;
+ case ACT_OFF: // OFF
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageDeactivate (&zvm);
+ break;
+ case ACT_ON: // ON
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageActivate (&zvm);
+ break;
+ case ACT_METADATA: // METADATA
+ rc = zvm_metadata ();
+ break;
+ case ACT_STATUS: // STATUS
+ if ((rc = check_parm (&zvm)) == 0)
+ rc = zvm_smapi_imageQuery (&zvm);
+ break;
+ case ACT_MONITOR: // MONITOR
+ rc = 0;
+ break;
+ case ACT_LIST: // LIST
+ printf ("N/A");
+ rc = 0;
+ break;
+ case ACT_HELP:
+ rc = usage ();
+ }
+ closelog ();
+ return (rc);
+}
+#else
+#include <syslog.h>
+int
+main (int argc, char **argv)
+{
+ openlog ("fence_zvm", LOG_CONS | LOG_PID, LOG_DAEMON);
+ syslog (LOG_ERR,
+ "Fencing of a z/VM agent is not possible on this platform\n");
+ closelog ();
+ return (-1);
+}
+#endif
diff --git a/agents/zvm/fence_zvm.h b/agents/zvm/fence_zvm.h
new file mode 100644
index 0000000..ca18e4d
--- /dev/null
+++ b/agents/zvm/fence_zvm.h
@@ -0,0 +1,583 @@
+/*
+ * fence_zvm.h: SMAPI interface for z/VM Guests
+ *
+ * Copyright (C) 2012 Sine Nomine Associates
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Neale Ferguson <neale@sinenomine.net>
+ *
+ */
+
+#ifndef FENCE_ZVM_H
+# define FENCE_ZVM_H
+
+# include <sys/types.h>
+
+# define SMAPI_TARGET "OVIRTADM"
+# define SMAPI_MAXCPU 96
+
+/*
+ * Return codes
+ */
+# define RC_OK 0 /* Request successful */
+# define RC_WNG 4 /* Warning */
+# define RC_ERR 8 /* Error */
+# define RCERR_SYNTAX 24 /* Function parameter syntax error */
+# define RCERR_FILE_NOT_FOUND 28 /* File not found */
+# define RCERR_FILE_CANNOT_BE_UPDATED 36 /* Name list file cannot be updated */
+# define RCERR_AUTH 100 /* Request not authorized by ESM */
+# define RCERR_NO_AUTHFILE 104 /* Authorization file not found */
+# define RCERR_AUTHFILE_RO 106 /* Authorization file cannot be updated */
+# define RCERR_EXISTS 108 /* Authorization file entry already exists */
+# define RCERR_NO_ENTRY 112 /* Authorization file entry does not exist */
+# define RCERR_USER_PW_BAD 120 /* Authentication error: Userid or pwd invalid */
+# define RCERR_PW_EXPIRED 128 /* Authentication error: password expired */
+# define RCERR_ESM 188 /* ESM failure */
+# define RCERR_PW_CHECK 192 /* Internal error: can't authenticate user or pwd */
+# define RCERR_DMSCSL 196 /* Internal Callable Services error */
+# define RCERR_IMAGEOP 200 /* Image Operation error */
+# define RCERR_LIST 200 /* Bad rc for list or list function */
+# define RCERR_IMAGEDEVU 204 /* Image Device Usage error */
+# define RCERR_IMAGEDISKU 208 /* Image Disk Usage error */
+# define RCERR_IMAGECONN 212 /* Image Connectivity Definition error */
+# define RCERR_IMAGECPU 216 /* Image CPU definition error */
+# define RCERR_VOLUME 300 /* Image Volume function error */
+# define RCERR_INTERNAL 396 /* Internal product-specific error */
+# define RCERR_IMAGE_NAME 400 /* Image Name error */
+# define RCERR_IMAGEDEF 400 /* Image Definition error */
+# define RCERR_IMAGEDEVD 404 /* Image Device Definition error */
+# define RCERR_IMAGEDISKD 408 /* Image Disk Definition error */
+# define RCERR_IMAGECONND 412 /* Image Connectivity Definition error */
+# define RCERR_PROTODEF 416 /* Prototype Definition error */
+# define RCERR_DASD_DM 420 /* Volume/region name already defined or region in group */
+# define RCERR_SEGMENT_DM 424 /* Segment definition errors */
+# define RCERR_NOTIFY 428 /* Notification subscription errors */
+# define RCERR_TAG 432 /* Local tag definition errors */
+# define RCERR_PROFILED 436 /* Profile definition errors */
+# define RCERR_POLICY_PW 444 /* Password policy error */
+# define RCERR_POLICY_ACCT 448 /* Account number policy error */
+# define RCERR_TASK 452 /* Task error */
+# define RCERR_SCSI 456 /* SCSI error */
+# define RCERR_DM 500 /* Directory Manager error */
+# define RCERR_LIST_DM 504 /* Directory Manager list error */
+# define RCERR_ASYNC_DM 592 /* Asynchronous Operation error */
+# define RCERR_INTERNAL_DM 596 /* Internal Directory Manager error */
+# define RCERR_SHSTOR 600 /* Shared Memory function error */
+# define RCERR_VIRTUALNETWORKD 620 /* Vswitch function error */
+# define RCERR_VMRM 800 /* Error from VMRM functions */
+# define RCERR_SERVER 900 /* Socket-Server error */
+
+/*
+ * Syntax error reason codes
+ */
+# define RS_NONE 0
+# define RS_TOOMANY 0
+# define RS_TANY 0
+# define RS_TBIN 2
+# define RS_UNSIGNEDINT 10
+# define RS_TNUM 10
+# define RS_UNSUPPORTED 11
+# define RS_SHORT 14
+# define RS_LESSTHANMIN 15
+# define RS_HEX 16
+# define RS_THEX 16
+# define RS_THEXHY 17
+# define RS_LONG 13
+# define RS_MORETHANMAX 18
+# define RS_UNRECOG 19
+# define RS_CONFLICTING 23
+# define RS_UNSPECIFIED 24
+# define RS_EXTRANEOUS 25
+# define RS_ALPHABETIC 26
+# define RS_TALPHA 26
+# define RS_FUNCTIONNAME 27
+# define RS_TALPHA_ 27
+# define RS_ALPHANUMERIC 36
+# define RS_TNUMALPHA 36
+# define RS_ALPHANUMERIC_ 37
+# define RS_TNUMALPHAHY 37
+# define RS_TLIST 38
+# define RS_DIRMAINTFILE 42
+# define RS_TFILE 42
+# define RS_DIRMAINTFILE_ 43
+# define RS_TFILE_ 43
+# define RS_DIRMAINTFILE_EQ 44
+# define RS_TFILE_EQ 44
+# define RS_UNEXPECTED_END 88
+# define RS_NON_BREAKING_CHAR 99
+# define RS_TNONBLANK 99
+
+/*
+ * Non-syntax related reason codes
+ */
+# define RS_NONE 0 /* Request successful */
+# define RS_INVALID_USER 2 /* Invalid user */
+# define RS_INVALID_DEVICE 2 /* invalid device */
+# define RS_NO_OSAS 4 /* No OSAs exist */
+# define RS_INVALID_OP 3 /* Invalid LAN operation */
+# define RS_INVALID_PRO 4 /* Invalid LAN promiscuity */
+# define RS_NO_DEV 4 /* No IPL device */
+# define RS_DEFERRED_SERVER 4 /* Authorization deferred to server */
+# define RS_DUP_NAME 4 /* Duplicate tag name */
+# define RS_EXISTS 4 /* Device already exists*/
+# define RS_IN_USE 4 /* Image Disk already in use */
+# define RS_IVS_NAME_USED 4 /* Group/region/volume already defined */
+# define RS_LOADDEV_NOT_FOUND 4 /* LOADDEV statement not found */
+# define RS_NO_PARTNER 4 /* Partner image not found */
+# define RS_NO_UPDATES 4 /* Directory manager not accepting update*/
+# define RS_NOT_FOUND 4 /* Image/Task Not Found */
+# define RS_NOTIFY_DUPLICATE 4 /* Duplicate subscription */
+# define RS_SEG_NAME_DUPLICATE 4 /* Segment name already used */
+# define RS_AFFINITY_SUPPRESSED 4 /* CPU defined but affinity suppressed */
+# define RS_WORK_OUTSTANDING 4 /* Image_Defintion_* asynch */
+# define RS_UNRESTRICTED_LAN 5 /* LAN is unrestricted */
+# define RS_NO_USERS 6 /* No users authorized for LAN */
+# define RS_ADAPTER_NOT_EXIST 8 /* Adapter does not exist */
+# define RS_ALREADY_ACTIVE 8 /* Image already active */
+# define RS_AUTHERR_CONNECT 8 /* Not authorized to connect */
+# define RS_AUTHERR_ESM 8 /* Request not authorized by an ESM */
+# define RS_BAD_RANGE 8 /* Bad page range */
+# define RS_DEV_NOT_FOUND 8 /* Device not found */
+# define RS_IVS_NAME_NOT_USED 8 /* Group/region/volume is not defined */
+# define RS_NAME_EXISTS 8 /* Image Name already defined */
+# define RS_NO_MEASUREMENT_DATA 8 /* No VMRM measurement query data */
+# define RS_NOT_AVAILABLE 8 /* Directory manager not available */
+# define RS_NOT_DEFINED 8 /* Image Device/Volume/Region/Group/Tag name not defined */
+# define RS_NOT_EXIST 8 /* Device does not exist */
+# define RS_NOTIFY_NOT_FOUND 8 /* No matching entries */
+# define RS_NOT_IN_USE 8 /* Image disk not in use */
+# define RS_OFFLINE 8 /* Successful; Object directory offline */
+# define RS_SEG_NAME_NOT_FOUND 8 /* Segment name not used */
+# define RS_WORKER_NOT_FOUND 8 /* Worker server not found */
+# define RS_DEV_NOT_AVAIL_TO_ATTACH 10 /* Device not found */
+# define RS_TOO_MANY_PARM 10 /* Too many parms in parameter list */
+# define RS_TOO_FEW_PARM 11 /* Too few parms in parameter list */
+# define RS_ALREADY_LOCKED 12 /* Image definition already locked */
+# define RS_AUTHERR_DM 12 /* Request not authorized by Directory Manager */
+# define RS_BUSY 12 /* Image device is busy */
+# define RS_DUP_ORDINAL 12 /* Duplicate tag ordinal */
+# define RS_FUNCTION_NOT_VALID 12 /* Not a valid SMAPI function */
+# define RS_IVS_NAME_NOT_INCLUDED 12 /* Name not included (ISR,ISQ)*/
+# define RS_LAN_NOT_EXIST 12 /* LAN does not exist */
+# define RS_LOCKED 12 /* Image definition is locked */
+# define RS_NAMESAVE_EXISTS 12 /* Namesave statementt already in directory*/
+# define RS_NEW_LIST 12 /* Successful new list created */
+# define RS_NOT_ACTIVE 12 /* Image not active */
+# define RS_NOT_INCLUDED 12 /* Region not included in group */
+# define RS_NOT_LOGGED_ON 12 /* User not logged on */
+# define RS_DEV_NOT_VOLUME 12 /* Device not a volume */
+# define RS_UPDATE_SYNTAX_ERROR 12 /* Errors in configuration update buffer */
+# define RS_FREE_MODE_NOT_AVAIL 14 /* Free mode not available */
+# define RS_AUTHERR_SERVER 16 /* Request not authorized by server */
+# define RS_BEING_DEACT 16 /* Image being deactivated */
+# define RS_CANNOT_ACCESS_DATA 16 /* Cannot access configuration or VMRM measurement data */
+# define RS_CANNOT_DELETE 16 /* Cannot delete image definition */
+# define RS_CANNOT_REVOKE 16 /* Cannot revoke tag definition */
+# define RS_CANNOT_SHARE 16 /* Image disk cannot be shared */
+# define RS_DEV_NOT_ONLINE 16 /* Device not online */
+# define RS_LIST_DESTROYED 16 /* Successful no more entries: list destroyed */
+# define RS_NO_MATCH 16 /* Parameters don't match existing directory statement */
+# define RS_NO_SHARING 16 /* Image disk sharing not allowed by target image definition */
+# define RS_NOSAVE 16 /* Could not save segment */
+# define RS_PTS_ENTRY_NOT_VALID 16 /* Parser entry not valid */
+# define RS_TAG_LONG 16 /* Tag too long */
+# define RS_VOLID_NOT_FOUND 18 /* Volid not found */
+# define RS_IS_CONNECTED 20 /* Device already connected */
+# define RS_NOT_AUTHORIZED 20 /* Not authorized for function */
+# define RS_OWNER_NOT_ACTIVE 20 /* Owner of reqested LAN not active */
+# define RS_PARM_LIST_NOT_VALID 20 /* Parameter list not valid */
+# define RS_PW_FORMAT_NOT_SUPPORTED 20 /* Directory manager does not support password format */
+# define RS_SHARE_DIFF_MODE 20 /* Image disk shared in different mode */
+# define RS_VOLID_IN_USE 20 /* Volid is in use */
+# define RS_TARGET_IMG_NOT_AUTH 20 /* Target Image not authorized to issue the command */
+# define RS_PDISKS_SAME 22 /* Parm disk 1 and 2 are same */
+# define RS_CONFLICTING_PARMS 24 /* Conflicting storage parameters */
+# define RS_LAN_NAME_EXISTS 24 /* Same name as an existing LAN */
+# define RS_LIST_NOT_FOUND 24 /* List not found */
+# define RS_NO_SPACE 24 /* Image disk space not available */
+# define RS_NOT_LOCKED 24 /* Image name is not locked */
+# define RS_PARM_DISK_LINK_ERR 24 /* Error linking parm disk (1 or 2)*/
+# define RS_SFS_ERROR 24 /* Shared File System error */
+# define RS_TYPE_NOT_SAME 24 /* Image device type not same as source */
+# define RS_UPDATE_WRITE_ERROR 24 /* Configuration update could not write files */
+# define RS_TAPE_NOT_ASSIGNED 24 /* Tape not assigned */
+# define RS_VCPU_ALREADY_EXISTS 24 /* Virtual CPU already defined */
+# define RS_VCPU_OUT_OF_RANGE 28 /* CPU beyond range defined in directory */
+# define RS_DEV_INCOMPATIBLE 28 /* Incorrect device type */
+# define RS_EMPTY 28 /* Return buffer is empty */
+# define RS_FILE_NOT_FOUND 28 /* File not found */
+# define RS_NO_MATCH_ON_SEARCH 28 /* No entries match search criteria */
+# define RS_NOT_ALL 28 /* Some images in list not activated */
+# define RS_OUTPUT_NOT_VALID 28 /* Output from function not valid */
+# define RS_PARM_DISK_NOT_RW 28 /* Parm Disk (1 or 2) not R/W */
+# define RS_PW_NEEDED 28 /* Image Disk does not have required password */
+# define RS_SEGMENT_NOT_FOUND 28 /* Shared Storage Segment not found */
+# define RS_SIZE_NOT_SAME 28 /* Image device size not same as source */
+# define RS_DEV_NOT_SHARED 28 /* Device not shared */
+# define RS_BAD_PW 32 /* Incorrect password specified for image disk */
+# define RS_NOT_CONNECTED 32 /* Device not connected */
+# define RS_NOT_IN_LIST 32 /* Name was not in list */
+# define RS_SOME_NOT_DEACT 32 /* Some Images in list not deactivated */
+# define RS_UPDATE_PROCESS_ERROR 32 /* Configuration update internal processer */
+# define RS_SYS_CONF_NOT_FOUND 32 /* System configuration file not found on PARM disk */
+# define RS_DEV_NOT_RESERVED 32 /* Device not reserved */
+# define RS_REQRESP_NOT_VALID 32 /* Internal request error */
+# define RS_SYS_CONF_BAD_DATA 34 /* Syntax Errors with original system configuration */
+# define RS_IVS_NAME_NOT_DASD 36 /* Name not DASD (for ISD) */
+# define RS_LENGTH_NOT_VALID 36 /* Length on input/output not valid */
+# define RS_NAME_IN_LIST 36 /* Name is already in list */
+# define RS_NO_VOLUME 36 /* No such DASD vol mounted on system; Unable to determine dev type */
+# define RS_SOME_NOT_RECYC 36 /* Some images in list not recycled */
+# define RS_SYS_CONF_SYNTX_ERR 36 /* Syntax errors with system configuration update*/
+# define RS_TIME_NOT_VALID 36 /* Force time for deactvation not valid */
+# define RS_VSWITCH_EXISTS 36 /* VSwitch already exists */
+# define RS_DEV_IO_ERROR 36 /* Device I/O error */
+# define RS_NO_DIR_AUTH_TO_LINK 36 /* No directory authority to link */
+# define RS_CPDISK_MODE_NOT_AVAIL 38 /* CP disk modes not available */
+# define RS_PARM_DISK_FULL 40 /* Parm Disk (1 or 2) is full */
+# define RS_VSWITCH_NOT_EXISTS 40 /* VSwitch doesn't exist */
+# define RS_NWDEV_NOT_DETACHED 40 /* Device not detached */
+# define RS_MULTIPLE 40 /* Multiple - multiple what? */
+# define RS_SOCKET 40 /* Socket error */
+# define RS_TYPE_NOT_SUPPORTED 40 /* CPU type not supported on your system */
+# define RS_PDISK_ACC_NOT_ALLOWED 42 /* Parm Disk 1 or 2 - access not allowed */
+# define RS_ALREADY_AUTH 44 /* Image already granted */
+# define RS_PDISK_PW_NOT_SUPPLIED 44 /* Parm Disk (1 or 2) password not supplied */
+# define RS_DASD_IN_USE 44 /* DASD in use */
+# define RS_IS_DISCONNECTED 48 /* Disconnected */
+# define RS_PDISK_PW_INCORRECT 46 /* Parm Disk (1 or 2) password is incorrect */
+# define RS_PARM_DISK_NOT_IN_SRVR_DIR 48 /* Parm Disk (1 or 2) is not in server's user directory */
+# define RS_VLAN_NOT_FOUND 48 /* vLAN not found */
+# define RS_MAX_CONN 52 /* Max connections reached */
+# define RS_CPRELEASE_ERROR 50 /* CPRELEASE error for Parm Disk (1 or 2) */
+# define RS_CPACCESS_ERROR 52 /* CPACCESS error for Parm Disk (1 or 2) */
+# define RS_DEF_VSWITCH_EXISTS 54 /* DEFINE exists in System Config */
+# define RS_GRANT_EXISTS 56 /* GRANT exists in System Config */
+# define RS_REVOKE_FAILED 58 /* MODIFY does not exist in System Config */
+# define RS_DEF_VSWITCH_NOT_EXIST 60 /* DEFINE does not exist in System config */
+# define RS_VSWITCH_CONFLICT 62 /* VSwitch conflict for set API */
+# define RS_DEF_MOD_MULTI_FOUND 64 /* Multiple Define or Modify statements found */
+# define RS_DEF_MOD_MULTI_ERASED 66 /* Multiple Define or Modify statements erased */
+# define RS_DATABASE 68 /* Unable to access database */
+# define RS_UNKNOWN 96 /* Connect request failed for unknown reason */
+# define RS_RETRY 99 /* Suggest retry API call */
+# define RS_ASYNC_OP_SUCCEEDED 100 /* Asynch operation succeeded */
+# define RS_ASYNC_OP_IN_PROGRESS 104 /* Asynch operation in progress */
+# define RS_ASYNC_OP_FAILED 108 /* Asynch operation failed */
+# define RS_CLASS_S_ALREADY_DEFINED 299 /* DEFSEG class S file exists */
+# define RS_NOT_YET_AVAILABLE 999 /* Function not yet available */
+# define RS_DEVNO_REQUIRES_FREE_DISK 1157 /* DEVNO parameter requires the device to be a free volume*/
+# define RS_INVALID_LANID 2783 /* invalid LAN id */
+# define RS_INVALID_LAN_PARM 2795 /* LAN parameter for this LAN id */
+# define RS_RELOCATION_ERRORS 3000 /* Relocation error(s) encountered */
+# define RS_NO_RELOCATION_ACTIVE 3001 /* No active relocations found */
+# define RS_INVALID_PARAMETER 3002 /* Invalid parameter name */
+# define RS_INVALID_OPERAND 3003 /* Invalid parameter operand */
+# define RS_MISSING_PARAMETER 3004 /* Missing parameter */
+# define RS_NOT_IN_SSI 3005 /* System not in an SSI */
+# define RS_SSI_UNSTABLE 3006 /* SSI is not in a stable state */
+# define RS_SSI_CPOWNED_CONFLICT 3007 /* The volume or slot is not on all systems in SSI */
+# define RS_NOT_SSI_MEMBER 3008 /* Not a member of an SSI cluster */
+# define RS_REPAIR_IPL_PARAM 3009 /* IPLed with the REPAIR IPL param */
+# define RS_RELOCATION_MODIFY_ERROR 3010 /* VMRELOCATE Modify error */
+# define RS_NO_SLOTS_AVAILABLE 3011 /* No unique CP_OWNED slot available on system and in config */
+# define RS_VOLUME_NOT_FOUND 3012 /* VOLUME cannot be found */
+# define RS_VOLUME_OFFLINE 3013 /* The volume is offline */
+# define RS_SHARE_UNSUPPORTED 3014 /* Volume does not support sharing */
+
+/*
+ * API functional level
+ */
+# define RS_530 0 /* 5.3.0 level */
+# define RS_540 540 /* 5.4.0 level */
+# define RS_610 610 /* 6.1.0 level */
+# define RS_611 611 /* 6.1.1 level */
+# define RS_620 620 /* 6.2.0 level */
+# define RS_621 621 /* 6.2.1 level */
+# define RS_630 630 /* 6.3.0 level */
+
+/*
+ * SMAPI Operations
+ */
+# define Asynchronous_Notification_Disable_DM "Asynchronous_Notification_Disable_DM"
+# define Asynchronous_Notification_Enable_DM "Asynchronous_Notification_Enable_DM"
+# define Asynchronous_Notification_Query_DM "Asynchronous_Notification_Query_DM"
+# define Authorization_List_Add "Authorization_List_Add"
+# define Authorization_List_Query "Authorization_List_Query"
+# define Authorization_List_Remove "Authorization_List_Remove"
+# define Check_Authentication "Check_Authentication"
+# define Delete_ABEND_Dump "Delete_ABEND_Dump"
+# define Directory_Manager_Local_Tag_Define_DM "Directory_Manager_Local_Tag_Define_DM"
+# define Directory_Manager_Local_Tag_Delete_DM "Directory_Manager_Local_Tag_Delete_DM"
+# define Directory_Manager_Local_Tag_Query_DM "Directory_Manager_Local_Tag_Query_DM"
+# define Directory_Manager_Local_Tag_Set_DM "Directory_Manager_Local_Tag_Set_DM"
+# define Directory_Manager_Search_DM "Directory_Manager_Search_DM"
+# define Directory_Manager_Task_Cancel_DM "Directory_Manager_Task_Cancel_DM"
+# define Event_Stream_Add "Event_Stream_Add"
+# define Event_Subscribe "Event_Subscribe"
+# define Event_Unsubscribe "Event_Unsubscribe"
+# define Image_Activate "Image_Activate"
+# define Image_Active_Configuration_Query "Image_Active_Configuration_Query"
+# define Image_CPU_Define "Image_CPU_Define"
+# define Image_CPU_Define_DM "Image_CPU_Define_DM"
+# define Image_CPU_Delete "Image_CPU_Delete"
+# define Image_CPU_Delete_DM "Image_CPU_Delete_DM"
+# define Image_CPU_Query "Image_CPU_Query"
+# define Image_CPU_Query_DM "Image_CPU_Query_DM"
+# define Image_CPU_Set_Maximum_DM "Image_CPU_Set_Maximum_DM"
+# define Image_Create_DM "Image_Create_DM"
+# define Image_Deactivate "Image_Deactivate"
+# define Image_Definition_Async_Updates "Image_Definition_Async_Updates"
+# define Image_Definition_Create_DM "Image_Definition_Create_DM"
+# define Image_Definition_Delete_DM "Image_Definition_Delete_DM"
+# define Image_Definition_Query_DM "Image_Definition_Query_DM"
+# define Image_Definition_Update_DM "Image_Definition_Update_DM"
+# define Image_Delete_DM "Image_Delete_DM"
+# define Image_Device_Dedicate "Image_Device_Dedicate"
+# define Image_Device_Dedicate_DM "Image_Device_Dedicate_DM"
+# define Image_Device_Reset "Image_Device_Reset"
+# define Image_Device_Undedicate "Image_Device_Undedicate"
+# define Image_Device_Undedicate_DM "Image_Device_Undedicate_DM"
+# define Image_Disk_Copy "Image_Disk_Copy"
+# define Image_Disk_Copy_DM "Image_Disk_Copy_DM"
+# define Image_Disk_Create "Image_Disk_Create"
+# define Image_Disk_Create_DM "Image_Disk_Create_DM"
+# define Image_Disk_Delete "Image_Disk_Delete"
+# define Image_Disk_Delete_DM "Image_Disk_Delete_DM"
+# define Image_Disk_Query "Image_Disk_Query"
+# define Image_Disk_Share "Image_Disk_Share"
+# define Image_Disk_Share_DM "Image_Disk_Share_DM"
+# define Image_Disk_Unshare "Image_Disk_Unshare"
+# define Image_Disk_Unshare_DM "Image_Disk_Unshare_DM"
+# define Image_IPL_Delete_DM "Image_IPL_Delete_DM"
+# define Image_IPL_Query_DM "Image_IPL_Query_DM"
+# define Image_IPL_Set_DM "Image_IPL_Set_DM"
+# define Image_Lock_DM "Image_Lock_DM"
+# define Image_Name_Query_DM "Image_Name_Query_DM"
+# define Image_Password_Set_DM "Image_Password_Set_DM"
+# define Image_Query_Activate_Time "Image_Query_Activate_Time"
+# define Image_Query_DM "Image_Query_DM"
+# define Image_Recycle "Image_Recycle"
+# define Image_Replace_DM "Image_Replace_DM"
+# define Image_SCSI_Characteristics_Define_DM "Image_SCSI_Characteristics_Define_DM"
+# define Image_SCSI_Characteristics_Query_DM "Image_SCSI_Characteristics_Query_DM"
+# define Image_Status_Query "Image_Status_Query"
+# define Image_Unlock_DM "Image_Unlock_DM"
+# define Image_Volume_Add "Image_Volume_Add"
+# define Image_Volume_Delete "Image_Volume_Delete"
+# define Image_Volume_Share "Image_Volume_Share"
+# define Image_Volume_Space_Define_DM "Image_Volume_Space_Define_DM"
+# define Image_Volume_Space_Define_Extended_DM "Image_Volume_Space_Define_Extended_DM"
+# define Image_Volume_Space_Query_DM "Image_Volume_Space_Query_DM"
+# define Image_Volume_Space_Query_Extended_DM "Image_Volume_Space_Query_Extended_DM"
+# define Image_Volume_Space_Remove_DM "Image_Volume_Space_Remove_DM"
+# define Metadata_Delete "Metadata_Delete"
+# define Metadata_Get "Metadata_Get"
+# define Metadata_Set "Metadata_Set"
+# define Name_List_Add "Name_List_Add"
+# define Name_List_Destroy "Name_List_Destroy"
+# define Name_List_Query "Name_List_Query"
+# define Name_List_Remove "Name_List_Remove"
+# define Page_or_Spool_Volume_Add "Page_or_Spool_Volume_Add"
+# define Process_ABEND_Dump "Process_ABEND_Dump"
+# define Profile_Create_DM "Profile_Create_DM"
+# define Profile_Delete_DM "Profile_Delete_DM"
+# define Profile_Lock_DM "Profile_Lock_DM"
+# define Profile_Query_DM "Profile_Query_DM"
+# define Profile_Replace_DM "Profile_Replace_DM"
+# define Profile_Unlock_DM "Profile_Unlock_DM"
+# define Prototype_Create_DM "Prototype_Create_DM"
+# define Prototype_Delete_DM "Prototype_Delete_DM"
+# define Prototype_Name_Query_DM "Prototype_Name_Query_DM"
+# define Prototype_Query_DM "Prototype_Query_DM"
+# define Prototype_Replace_DM "Prototype_Replace_DM"
+# define Query_ABEND_Dump "Query_ABEND_Dump"
+# define Query_All_DM "Query_All_DM"
+# define Query_API_Functional_Level "Query_API_Functional_Level"
+# define Query_Asynchronous_Operation_DM "Query_Asynchronous_Operation_DM"
+# define Query_Directory_Manager_Level_DM "Query_Directory_Manager_Level_DM"
+# define Response_Recovery "Response_Recovery"
+# define Shared_Memory_Access_Add_DM "Shared_Memory_Access_Add_DM"
+# define Shared_Memory_Access_Query_DM "Shared_Memory_Access_Query_DM"
+# define Shared_Memory_Access_Remove_DM "Shared_Memory_Access_Remove_DM"
+# define Shared_Memory_Create "Shared_Memory_Create"
+# define Shared_Memory_Delete "Shared_Memory_Delete"
+# define Shared_Memory_Query "Shared_Memory_Query"
+# define Shared_Memory_Replace "Shared_Memory_Replace"
+# define SSI_Query "SSI_Query"
+# define Static_Image_Changes_Activate_DM "Static_Image_Changes_Activate_DM"
+# define Static_Image_Changes_Deactivate_DM "Static_Image_Changes_Deactivate_DM"
+# define Static_Image_Changes_Immediate_DM "Static_Image_Changes_Immediate_DM"
+# define System_Config_Syntax_Check "System_Config_Syntax_Check"
+# define System_Disk_Accessibility "System_Disk_Accessibility"
+# define System_Disk_Add "System_Disk_Add"
+# define System_Disk_Query "System_Disk_Query"
+# define System_FCP_Free_Query "System_FCP_Free_Query"
+# define System_Performance_Threshold_Disable "System_Performance_Threshold_Disable"
+# define System_Performance_Threshold_Enable "System_Performance_Threshold_Enable"
+# define System_SCSI_Disk_Add "System_SCSI_Disk_Add"
+# define System_SCSI_Disk_Delete "System_SCSI_Disk_Delete"
+# define System_SCSI_Disk_Query "System_SCSI_Disk_Query"
+# define System_WWPN_Query "System_WWPN_Query"
+# define Virtual_Channel_Connection_Create "Virtual_Channel_Connection_Create"
+# define Virtual_Channel_Connection_Create_DM "Virtual_Channel_Connection_Create_DM"
+# define Virtual_Channel_Connection_Delete "Virtual_Channel_Connection_Delete"
+# define Virtual_Channel_Connection_Delete_DM "Virtual_Channel_Connection_Delete_DM"
+# define Virtual_Network_Adapter_Connect_LAN "Virtual_Network_Adapter_Connect_LAN"
+# define Virtual_Network_Adapter_Connect_LAN_DM "Virtual_Network_Adapter_Connect_LAN_DM"
+# define Virtual_Network_Adapter_Connect_Vswitch "Virtual_Network_Adapter_Connect_Vswitch"
+# define Virtual_Network_Adapter_Connect_Vswitch_DM "Virtual_Network_Adapter_Connect_Vswitch_DM"
+# define Virtual_Network_Adapter_Connect_Vswitch_Extended "Virtual_Network_Adapter_Connect_Vswitch_Extended"
+# define Virtual_Network_Adapter_Create "Virtual_Network_Adapter_Create"
+# define Virtual_Network_Adapter_Create_DM "Virtual_Network_Adapter_Create_DM"
+# define Virtual_Network_Adapter_Create_Extended "Virtual_Network_Adapter_Create_Extended"
+# define Virtual_Network_Adapter_Create_Extended_DM "Virtual_Network_Adapter_Create_Extended_DM"
+# define Virtual_Network_Adapter_Delete "Virtual_Network_Adapter_Delete"
+# define Virtual_Network_Adapter_Delete_DM "Virtual_Network_Adapter_Delete_DM"
+# define Virtual_Network_Adapter_Disconnect "Virtual_Network_Adapter_Disconnect"
+# define Virtual_Network_Adapter_Disconnect_DM "Virtual_Network_Adapter_Disconnect_DM"
+# define Virtual_Network_Adapter_Query "Virtual_Network_Adapter_Query"
+# define Virtual_Network_LAN_Access "Virtual_Network_LAN_Access"
+# define Virtual_Network_LAN_Access_Query "Virtual_Network_LAN_Access_Query"
+# define Virtual_Network_LAN_Create "Virtual_Network_LAN_Create"
+# define Virtual_Network_LAN_Delete "Virtual_Network_LAN_Delete"
+# define Virtual_Network_LAN_Query "Virtual_Network_LAN_Query"
+# define Virtual_Network_OSA_Query "Virtual_Network_OSA_Query"
+# define Virtual_Network_VLAN_Query_Stats "Virtual_Network_VLAN_Query_Stats"
+# define Virtual_Network_Vswitch_Create "Virtual_Network_Vswitch_Create"
+# define Virtual_Network_Vswitch_Create_Extended "Virtual_Network_Vswitch_Create_Extended"
+# define Virtual_Network_Vswitch_Delete "Virtual_Network_Vswitch_Delete"
+# define Virtual_Network_Vswitch_Delete_Extended "Virtual_Network_Vswitch_Delete_Extended"
+# define Virtual_Network_Vswitch_Query "Virtual_Network_Vswitch_Query"
+# define Virtual_Network_Vswitch_Query_Extended "Virtual_Network_Vswitch_Query_Extended"
+# define Virtual_Network_Vswitch_Query_Stats "Virtual_Network_Vswitch_Query_Stats"
+# define Virtual_Network_Vswitch_Set "Virtual_Network_Vswitch_Set"
+# define Virtual_Network_Vswitch_Set_Extended "Virtual_Network_Vswitch_Set_Extended"
+# define VMRELOCATE "VMRELOCATE"
+# define VMRELOCATE_Image_Attributes "VMRELOCATE_Image_Attributes"
+# define VMRELOCATE_Modify "VMRELOCATE_Modify"
+# define VMRELOCATE_Status "VMRELOCATE_Status"
+# define VMRM_Configuration_Query "VMRM_Configuration_Query"
+# define VMRM_Configuration_Update "VMRM_Configuration_Update"
+# define VMRM_Measurement_Query "VMRM_Measurement_Query"
+
+# define FORCE_IMMED "IMMED"
+# define FORCE_WITHIN "WITHIN 99999"
+
+/*
+ * Standard fields in a response from SMAPI server
+ */
+typedef struct {
+ uint32_t outLen; /* Length of output data */
+ uint32_t reqId; /* Request ID to which response refers */
+ uint32_t rc; /* Return code */
+ uint32_t reason; /* Reason code */
+} smapiOutHeader_t;
+
+typedef struct {
+ smapiOutHeader_t hdr; /* Output header */
+ uint32_t lArray; /* Length of array output */
+ char array[0]; /* Start of array output */
+} smapiArrayHeader_t;
+
+/*
+ * Structures returned from Image_Active_Configuration_Query
+ */
+typedef struct {
+ smapiOutHeader_t hdr;
+ int32_t memSize;
+ uint8_t memUnit;
+# define SMAPI_MEMUNIT_KB 1
+# define SMAPI_MEMUNIT_MB 2
+# define SMAPI_MEMUNIT_GB 3
+ uint8_t shareType;
+# define SMAPI_SHRTYPE_R 1
+# define SMAPI_SHRTYPE_A 2
+ int32_t lShare;
+ char share[0];
+} __attribute__ ((__packed__)) zvm_actImgHdr_t;
+
+typedef struct {
+ char share[5];
+} zvm_actImgShr_t;
+
+typedef struct {
+ int32_t nCPU;
+ int32_t lCPUArray;
+ char cpuArray[0];
+} zvm_actImgCPUArr_t;
+
+typedef struct {
+ int32_t lCPUStruct;
+ char cpuStruct[0];
+} zvm_actImgCPUHdr_t;
+
+typedef struct {
+ int32_t cpuNumber;
+ int32_t lCPUId;
+ char cpuId[16];
+} zvm_actImgCPUId_t;
+
+typedef struct {
+ uint8_t cpuState;
+# define SMAPI_CPUSTATE_BASE 1
+# define SMAPI_CPUSTATE_STOPPED 2
+# define SMAPI_CPUSTATE_CHECK 3
+# define SMAPI_CPUSTATE_ACTIVE 4
+ int32_t lDevArray;
+ char devArray[0];
+} __attribute__ ((__packed__)) zvm_actImgCPUState_t;
+
+typedef struct {
+ int32_t lDevStruct;
+ char devStruct[0];
+} zvm_actImgDevHdr_t;
+
+typedef struct {
+ uint8_t devType;
+# define SMAPI_DEVTYPE_CONS 1
+# define SMAPI_DEVTYPE_RDR 2
+# define SMAPI_DEVTYPE_PUN 3
+# define SMAPI_DEVTYPE_PRT 4
+# define SMAPI_DEVTYPE_DASD 5
+ int32_t lDevAddr;
+ uint8_t devAddr[4];
+} __attribute__ ((__packed__)) zvm_actImgDev_t;
+
+typedef struct {
+ int sd;
+ int reason;
+ uint32_t timeOut;
+ uint32_t delay;
+ char target[9];
+ char authUser[9];
+ char authPass[9];
+ char node[9];
+ char smapiSrv[128];
+} zvm_driver_t;
+
+int zvm_smapi_open(zvm_driver_t *);
+int zvm_smapi_send(zvm_driver_t *, void *, uint32_t *, int32_t);
+int zvm_smapi_recv(zvm_driver_t *, void **, int32_t *);
+int zvm_smapi_close(zvm_driver_t *);
+int zvm_smapi_imageActivate(zvm_driver_t *);
+int zvm_smapi_imageActiveQuery(zvm_driver_t *);
+int zvm_smapi_imageDeactivate(zvm_driver_t *);
+int zvm_smapi_imageRecycle(zvm_driver_t *);
+int zvm_smapi_imageQuery(zvm_driver_t *);
+
+#endif /* FENCE_ZVM_H */
diff --git a/agents/zvm/fence_zvm_man_page b/agents/zvm/fence_zvm_man_page
new file mode 100644
index 0000000..057cc6d
--- /dev/null
+++ b/agents/zvm/fence_zvm_man_page
@@ -0,0 +1,88 @@
+.TH fence_zvm 8
+
+.SH NAME
+fence_zvm - Power Fencing agent for GFS on System z z/VM Clusters
+
+.SH SYNOPSIS
+.B
+fence_zvm
+[\fIOPTION\fR]...
+
+.SH DESCRIPTION
+fence_zvm is a Power Fencing agent used on a GFS virtual machine in a System z z/VM cluster.
+It uses the SMAPI interface to recycle an active image.
+
+fence_zvm accepts options on the command line as well as from stdin.
+fence_node sends the options through stdin when it execs the agent.
+fence_zvm can be run by itself with command line options which is useful
+for testing.
+
+Vendor URL: http://www.sinenomine.net
+
+.SH OPTIONS
+.TP
+\fB-o --action\fP
+Fencing action: "off" - deactivate virtual machine; "on" - activate virtual machine; "metadata" - display device metadata" - describe fence agent parameters; "status" - state of virtual machine
+.TP
+\fB--delay\fP \fIseconds\fP
+Time to delay fencing action in seconds
+.TP
+\fB-n --plug\fP \fItarget\fP
+Name of virtual machine to recycle.
+.TP
+\fB-h --help\fP
+Print out a help message describing available options, then exit.
+.TP
+\fB-a --ip\fP \fIsmapi Server\fP
+\fBName\fP of SMAPI server virtual machine. To be consistent with other fence agents this name is a little misleading: it is the name of the virtual machine not its IP address or hostname.
+.TP
+\fB--zvmsys\fP \fIz/VM System\fP
+\fBName\fP of z/VM on which the SMAPI server virtual machine resides. Optional - defaults to system on which the node is running.
+.TP
+\fB-h --help\fP
+Display usage information
+.TP
+\fI-t --timeout = < shutdown timeout >\fP
+Amount of \fIgrace\fP time to give the virtual machine to shutdown cleanly before being
+forcibly terminated. Currently, this option is ignored.
+
+.SH STDIN PARAMETERS
+.TP
+\fIagent = < param >\fP
+This option is used by fence_node(8) and is ignored by fence_zvm.
+.TP
+\fIaction = < action >\fP
+Fencing action: "off" - fence off device; "metadata" - display device metadata; "status" - state of device
+.TP
+\fIport = < target >\fP
+Name of virtual machine to recycle.
+.TP
+\fIipaddr= < server name >\fP
+\fBName\fP of SMAPI server virtual machine. To be consistent with other fence agents thisname is a little misleading: it is the name of the virtual machine not its IP address or hostname.
+.TP
+\fItimeout = < shutdown timeout >\fP
+Amount of \fIgrace\fP time to give the virtual machine to shutdown cleanly before being
+forcibly terminated. Currently, this option is ignored.
+
+.SH SEE ALSO
+fence(8), fenced(8), fence_node(8)
+
+.SH NOTES
+To use this agent the z/VM SMAPI service needs to be configured to allow the virtual
+machine running this agent to connect to it and issue the image_recycle operation.
+This involves updating the VSMWORK1 AUTHLIST VMSYS:VSMWORK1. file. The entry should look
+something similar to this:
+
+.nf
+Column 1 Column 66 Column 131
+| | |
+V V V
+XXXXXXXX ALL IMAGE_CHARACTERISTICS
+.fi
+
+Where XXXXXXX is the name of the virtual machine used in the authuser field of the request. This virtual machine also has to be authorized
+to access the system's directory manager.
+
+In addition, the VM directory entry that defines this virtual machine requires the
+IUCV ANY statement (or IUCV <userid of SMAPI Server>). This authorizes use of IUCV
+to connect to the SMAPI server.
diff --git a/agents/zvm/fence_zvmip.c b/agents/zvm/fence_zvmip.c
new file mode 100644
index 0000000..b16de48
--- /dev/null
+++ b/agents/zvm/fence_zvmip.c
@@ -0,0 +1,1001 @@
+/*
+ * fence_zvmip.c: SMAPI interface for managing zVM Guests
+ *
+ * Copyright (C) 2012 Sine Nomine Associates
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Neale Ferguson <neale@sinenomine.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netiucv/iucv.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <syslog.h>
+#include "fence_zvm.h"
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define DEFAULT_TIMEOUT 300
+#define DEFAULT_DELAY 0
+
+#define ACT_OFFON 0
+#define ACT_OFF 1
+#define ACT_ON 2
+#define ACT_METADATA 3
+#define ACT_STATUS 4
+#define ACT_MONITOR 5
+#define ACT_LIST 6
+#define ACT_HELP 7
+
+static int zvm_smapi_reportError(void *, void *);
+
+static struct option longopts[] = {
+ {"action", required_argument, NULL, 'o'},
+ {"delay", required_argument, NULL, 'd'},
+ {"help", no_argument, NULL, 'h'},
+ {"ipaddr", required_argument, NULL, 'a'},
+ {"password", required_argument, NULL, 'p'},
+ {"plug", required_argument, NULL, 'n'},
+ {"timeout", required_argument, NULL, 't'},
+ {"username", required_argument, NULL, 'u'},
+ {NULL, 0, NULL, 0}
+};
+
+static const char *optString = "a:o:hn:p:t:u:";
+
+static int zvm_metadata(void);
+static int usage(void);
+
+/**
+ * zvm_smapi_open:
+ * @zvm: z/VM driver information
+ *
+ * Opens a connection with the z/VM SMAPI server
+ */
+int
+zvm_smapi_open(zvm_driver_t *zvm)
+{
+ int rc = -1,
+ option = SO_REUSEADDR,
+ optVal = 1,
+ lOption = sizeof(optVal);
+ struct addrinfo hints, *ai;
+
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_protocol = IPPROTO_TCP;
+ if ((rc = getaddrinfo(zvm->smapiSrv, "44444", &hints, &ai)) == 0) {
+ if ((zvm->sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) != -1) {
+ rc = setsockopt(zvm->sd,SOL_SOCKET,option,&optVal,lOption);
+
+ if ((rc = connect(zvm->sd, ai->ai_addr, ai->ai_addrlen)) == -1) {
+ syslog(LOG_ERR, "Error connecting to %s - %m", zvm->smapiSrv);
+ close(zvm->sd);
+ }
+ } else {
+ syslog(LOG_ERR, "Error creating socket - %m");
+ }
+ } else {
+ syslog(LOG_ERR, "Error resolving server address: %s", gai_strerror(rc));
+ }
+ return(rc);
+}
+
+/**
+ * zvm_smapi_imageRecycle
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageRecycle(zvm_driver_t *zvm)
+{
+ struct _inPlist {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[13];
+ } __attribute__ ((packed)) *inPlist;
+ struct _authUser {
+ int32_t lAuthUser;
+ char userId[0];
+ } __attribute__ ((packed)) *authUser;
+ struct _authPass {
+ int32_t lAuthPass;
+ char password[0];
+ } __attribute__ ((packed)) *authPass;
+ struct _image {
+ int32_t lTarget;
+ char target[0];
+ } __attribute__ ((packed)) *image;
+ int32_t lInPlist;
+ struct _outPlist {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep(zvm->delay);
+
+ lInPlist = sizeof(*inPlist) + sizeof(*authUser) + strlen(zvm->authUser) +
+ sizeof(*authPass) + strlen(zvm->authPass) + sizeof(*image) +
+ + strlen(zvm->target);
+ inPlist = malloc(lInPlist);
+ if (inPlist != NULL) {
+ authUser = (void *) ((uintptr_t) inPlist + sizeof(*inPlist));
+ authPass = (void *) ((uintptr_t) authUser + sizeof(*authUser) +
+ strlen(zvm->authUser));
+ image = (void *) ((uintptr_t) authPass + sizeof(*authPass) +
+ strlen(zvm->authPass));
+ inPlist->lPlist = lInPlist - sizeof(inPlist->lPlist);
+ inPlist->lFName = sizeof(inPlist->fName);
+ memcpy(inPlist->fName, Image_Recycle, sizeof(inPlist->fName));
+ authUser->lAuthUser = strlen(zvm->authUser);
+ memcpy(authUser->userId, zvm->authUser, strlen(zvm->authUser));
+ authPass->lAuthPass = strlen(zvm->authPass);
+ memcpy(authPass->password, zvm->authPass, strlen(zvm->authPass));
+ image->lTarget = strlen(zvm->target);
+ strncpy(image->target, zvm->target, strlen(zvm->target));
+ if ((rc = zvm_smapi_send(zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv(zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog(LOG_INFO, "Recycling of %s successful",
+ zvm->target);
+ rc = 0;
+ } else {
+ if ((ntohl(outPlist->hdr.rc) == RCERR_IMAGEOP) &
+ ((ntohl(outPlist->hdr.reason) == RS_NOT_ACTIVE) |
+ (ntohl(outPlist->hdr.reason) == RS_BEING_DEACT))) {
+ syslog(LOG_INFO, "Recycling of %s successful",
+ zvm->target);
+ rc = 0;
+ } else {
+ rc = ntohl(outPlist->hdr.rc);
+ zvm->reason = ntohl(outPlist->hdr.reason);
+ (void) zvm_smapi_reportError(inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free(inPlist);
+ free(outPlist);
+ } else {
+ syslog(LOG_ERR, "%s - cannot allocate parameter list", __func__);
+ rc = -1;
+ }
+ return(rc);
+}
+
+/**
+ * zvm_smapi_imageDeactivate
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageDeactivate(zvm_driver_t *zvm)
+{
+ struct _inPlist {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[16];
+ } __attribute__ ((packed)) *inPlist;
+ struct _authUser {
+ int32_t lAuthUser;
+ char userId[0];
+ } __attribute__ ((packed)) *authUser;
+ struct _authPass {
+ int32_t lAuthPass;
+ char password[0];
+ } __attribute__ ((packed)) *authPass;
+ struct _image {
+ int32_t lTarget;
+ char target[0];
+ } __attribute__ ((packed)) *image;
+ struct _deactTime {
+ int32_t lForceTime;
+ char forceTime[5];
+ } __attribute__ ((__packed__)) *deactTime;
+ int32_t lInPlist;
+ struct _outPlist {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep(zvm->delay);
+
+ lInPlist = sizeof(*inPlist) + sizeof(*authUser) + strlen(zvm->authUser) +
+ sizeof(*authPass) + strlen(zvm->authPass) + sizeof(*image) +
+ sizeof(*deactTime) + strlen(zvm->target);
+ inPlist = malloc(lInPlist);
+ if (inPlist != NULL) {
+ authUser = (void *) ((uintptr_t) inPlist + sizeof(*inPlist));
+ authPass = (void *) ((uintptr_t) authUser + sizeof(*authUser) +
+ strlen(zvm->authUser));
+ image = (void *) ((uintptr_t) authPass + sizeof(*authPass) +
+ strlen(zvm->authPass));
+ deactTime = (void *) ((intptr_t) image + sizeof(*image) +
+ strlen(zvm->target));
+ inPlist->lPlist = lInPlist - sizeof(inPlist->lPlist);
+ inPlist->lFName = sizeof(inPlist->fName);
+ memcpy(inPlist->fName, Image_Deactivate, sizeof(inPlist->fName));
+ authUser->lAuthUser = strlen(zvm->authUser);
+ memcpy(authUser->userId, zvm->authUser, strlen(zvm->authUser));
+ authPass->lAuthPass = strlen(zvm->authPass);
+ memcpy(authPass->password, zvm->authPass, strlen(zvm->authPass));
+ image->lTarget = strlen(zvm->target);
+ memcpy(image->target, zvm->target, strlen(zvm->target));
+ deactTime->lForceTime = sizeof(deactTime->forceTime);
+ memcpy(deactTime->forceTime, "IMMED", sizeof(deactTime->forceTime));
+ if ((rc = zvm_smapi_send(zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv(zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog(LOG_INFO, "Deactivation of %s successful",
+ zvm->target);
+ rc = 0;
+ } else {
+ if ((outPlist->hdr.rc == RCERR_IMAGEOP) &
+ ((outPlist->hdr.reason == RS_NOT_ACTIVE) |
+ (outPlist->hdr.reason == RS_BEING_DEACT))) {
+ syslog(LOG_INFO, "Deactivation of %s successful",
+ zvm->target);
+ rc = 0;
+ } else {
+ rc = outPlist->hdr.rc;
+ zvm->reason = outPlist->hdr.reason;
+ (void) zvm_smapi_reportError(inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free(inPlist);
+ free(outPlist);
+ } else {
+ syslog(LOG_ERR, "%s - cannot allocate parameter list", __func__);
+ rc = -1;
+ }
+ return(rc);
+}
+
+/**
+ * zvm_smapi_imageActivate
+ * @zvm: z/VM driver information
+ *
+ * Deactivates a virtual image
+ */
+int
+zvm_smapi_imageActivate(zvm_driver_t *zvm)
+{
+ struct _inPlist {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[14];
+ } __attribute__ ((packed)) *inPlist;
+ struct _authUser {
+ int32_t lAuthUser;
+ char userId[0];
+ } __attribute__ ((packed)) *authUser;
+ struct _authPass {
+ int32_t lAuthPass;
+ char password[0];
+ } __attribute__ ((packed)) *authPass;
+ struct _image {
+ int32_t lTarget;
+ char target[0];
+ } __attribute__ ((packed)) *image;
+ int32_t lInPlist;
+ struct _outPlist {
+ smapiOutHeader_t hdr;
+ int32_t nActive;
+ int32_t nInActive;
+ int32_t lFail;
+ char failArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep(zvm->delay);
+
+ lInPlist = sizeof(*inPlist) + sizeof(*authUser) + strlen(zvm->authUser) +
+ sizeof(*authPass) + strlen(zvm->authPass) + sizeof(*image) +
+ strlen(zvm->target);
+ inPlist = malloc(lInPlist);
+ if (inPlist != NULL) {
+ authUser = (void *) ((uintptr_t) inPlist + sizeof(*inPlist));
+ authPass = (void *) ((uintptr_t) authUser + sizeof(*authUser) +
+ strlen(zvm->authUser));
+ image = (void *) ((uintptr_t) authPass + sizeof(*authPass) +
+ strlen(zvm->authPass));
+ inPlist->lPlist = lInPlist - sizeof(inPlist->lPlist);
+ inPlist->lFName = sizeof(inPlist->fName);
+ memcpy(inPlist->fName, Image_Activate, sizeof(inPlist->fName));
+ authUser->lAuthUser = strlen(zvm->authUser);
+ memcpy(authUser->userId, zvm->authUser, strlen(zvm->authUser));
+ authPass->lAuthPass = strlen(zvm->authPass);
+ memcpy(authPass->password, zvm->authPass, strlen(zvm->authPass));
+ image->lTarget = strlen(zvm->target);
+ memcpy(image->target, zvm->target, strlen(zvm->target));
+ if ((rc = zvm_smapi_send(zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv(zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ syslog(LOG_INFO, "Activation of %s successful",
+ zvm->target);
+ rc = 0;
+ } else {
+ if ((outPlist->hdr.rc == RCERR_IMAGEOP) &
+ (outPlist->hdr.reason == RS_ALREADY_ACTIVE)) {
+ syslog(LOG_INFO, "Activation of %s successful",
+ zvm->target);
+ rc = 0;
+ } else {
+ rc = outPlist->hdr.rc;
+ zvm->reason = outPlist->hdr.reason;
+ (void) zvm_smapi_reportError(inPlist, outPlist);
+ }
+ }
+ }
+ }
+ free(inPlist);
+ free(outPlist);
+ } else {
+ syslog(LOG_ERR, "%s - cannot allocate parameter list", __func__);
+ rc = -1;
+ }
+ return(rc);
+}
+
+/**
+ * zvm_smapi_imageQuery
+ * @zvm: z/VM driver information
+ *
+ * Queries the state of a virtual image
+ */
+int
+zvm_smapi_imageQuery(zvm_driver_t *zvm)
+{
+ struct _inPlist {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[18];
+ int32_t lUser;
+ int32_t lPass;
+ int32_t lTarget;
+ char target[0];
+ } __attribute__ ((__packed__)) *inPlist;
+ int32_t lInPlist;
+ struct _outPlist {
+ smapiOutHeader_t hdr;
+ int32_t lNames;
+ char nameArray[0];
+ } *outPlist = NULL;
+ void *pOut = NULL;
+ int32_t lRsp;
+ uint32_t reqId;
+ int rc;
+
+ /*
+ * Implement any delay
+ */
+ if (zvm->delay > 0)
+ sleep(zvm->delay);
+
+ lInPlist = sizeof(*inPlist) + strlen(zvm->target);
+ inPlist = malloc(lInPlist);
+ if (inPlist != NULL) {
+ inPlist->lPlist = lInPlist - sizeof(inPlist->lPlist);
+ inPlist->lFName = sizeof(inPlist->fName);
+ memcpy(inPlist->fName, Image_Status_Query, sizeof(inPlist->fName));
+ inPlist->lUser = inPlist->lPass = 0;
+ inPlist->lTarget = strlen(zvm->target);
+ memcpy(inPlist->target, zvm->target, inPlist->lTarget);
+ if ((rc = zvm_smapi_send(zvm, inPlist, &reqId, lInPlist)) != -1) {
+ if ((rc = zvm_smapi_recv(zvm, &pOut, &lRsp)) != -1) {
+ outPlist = pOut;
+ if (outPlist->hdr.rc == 0) {
+ if (outPlist->hdr.reason == 0) {
+ syslog(LOG_INFO, "Node %s is active",
+ zvm->target);
+ rc = 0;
+ } else {
+ syslog(LOG_INFO, "Node %s is inactive",
+ zvm->target);
+ rc = 2;
+ }
+ } else {
+ rc = 1;
+ zvm->reason = outPlist->hdr.reason;
+ (void) zvm_smapi_reportError(inPlist, outPlist);
+ }
+ }
+ }
+ free(inPlist);
+ free(outPlist);
+ } else {
+ syslog(LOG_ERR, "%s - cannot allocate parameter list", __func__);
+ rc = -1;
+ }
+ return(rc);
+}
+
+/**
+ * zvm_smapi_send:
+ * @zvm: z/VM driver information
+ * @reqid: Returned request id
+ * @req: Request parameter list
+ * @lSend: Length of request
+ *
+ * Send a request to the SMAPI server and retrieve the request id
+ */
+int
+zvm_smapi_send(zvm_driver_t *zvm, void *req, uint32_t *reqId, int32_t lSend)
+{
+ int rc,
+ nFds;
+ fd_set readFds;
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ zvm->reason = -1;
+ if ((rc = zvm_smapi_open(zvm)) == 0) {
+ rc = send(zvm->sd,req,lSend,0);
+ if (rc != -1) {
+ FD_ZERO(&readFds);
+ FD_SET(zvm->sd,&readFds);
+ nFds = zvm->sd + 1;
+
+ if ((rc = select(nFds,&readFds,NULL,NULL,&timeout)) != -1) {
+ /*
+ * Get request ID
+ */
+ rc = recv(zvm->sd,reqId,sizeof(*reqId),0);
+ if (rc == -1)
+ syslog(LOG_ERR, "Error receiving from SMAPI - %m");
+ }
+ } else
+ syslog(LOG_ERR, "Error sending to SMAPI - %m");
+ }
+ return(rc);
+}
+
+/**
+ * zvm_smapi_recv:
+ * @zvm: z/VM driver information
+ * @req: Returned response parameter list
+ * @lRsp: Length of response
+ *
+ * Receive a response from the SMAPI server
+ */
+int
+zvm_smapi_recv(zvm_driver_t *zvm, void **rsp, int32_t *lRsp)
+{
+ int rc,
+ lRem = 0,
+ nFds;
+ void *pRecv = rsp;
+ fd_set readFds;
+ smapiOutHeader_t *out;
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+ FD_ZERO(&readFds);
+ FD_SET(zvm->sd,&readFds);
+ nFds = zvm->sd + 1;
+
+ zvm->reason = -1;
+ if ((rc = select(nFds,&readFds,NULL,NULL,&timeout)) != -1) {
+ /*
+ * Get response length
+ */
+ if ((rc = recv(zvm->sd,lRsp,sizeof(*lRsp),0)) != -1) {
+ *lRsp = ntohl(*lRsp);
+ lRem = *lRsp;
+ if (*rsp == NULL)
+ *rsp = malloc(*lRsp + sizeof(out->outLen));
+ out = *rsp;
+ out->outLen = *lRsp;
+ pRecv = &out->reqId;
+ while (lRem > 0) {
+ if ((rc = recv(zvm->sd,pRecv,lRem,0)) != -1) {
+ lRem -= rc;
+ pRecv = (void *) ((uintptr_t) pRecv + rc);
+ } else
+ syslog(LOG_ERR, "Error receiving from SMAPI - %m");
+ (void) zvm_smapi_close(zvm);
+ return(rc);
+ }
+ zvm->reason = out->reason;
+ }
+ } else
+ syslog(LOG_ERR, "Error receiving from SMAPI - %m");
+
+ (void) zvm_smapi_close(zvm);
+
+ return(rc);
+}
+
+/**
+ * zvm_smapi_close:
+ * @zvm: z/VM driver information
+ *
+ * Close a connection with the z/VM SMAPI server
+ */
+int
+zvm_smapi_close(zvm_driver_t *zvm)
+{
+ close(zvm->sd);
+ return(0);
+}
+
+/**
+ * zvm_smapi_reportError
+ * @inHdr - Input parameter list header
+ * @outHdr - Output parameter list header
+ *
+ * Report an error from the SMAPI server
+ */
+static int
+zvm_smapi_reportError(void *inHdr, void *oHdr)
+{
+ struct _inParm {
+ int32_t lPlist;
+ int32_t lFName;
+ char fName[0];
+ } *inParm = inHdr;
+ smapiOutHeader_t *outHdr = oHdr;
+ char fName[64];
+
+ memset(fName, 0, sizeof(fName));
+ memcpy(fName, inParm->fName, inParm->lFName);
+ syslog(LOG_ERR, "%s - returned (%d,%d)",
+ fName, ntohl(outHdr->rc), ntohl(outHdr->reason));
+ return(-1);
+}
+
+
+/**
+ * trim - Trim spaces from string
+ * @str - Pointer to string
+ *
+ */
+static int
+trim(char *str)
+{
+ char *p;
+ int len;
+
+ if (!str)
+ return (0);
+
+ len = strlen (str);
+
+ while (len--) {
+ if (isspace (str[len])) {
+ str[len] = 0;
+ } else {
+ break;
+ }
+ }
+
+ for (p = str; *p && isspace (*p); p++);
+
+ memmove(str, p, strlen (p) + 1);
+
+ return (strlen (str));
+}
+
+/**
+ * get_options_stdin - get options from stdin
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+get_options_stdin (zvm_driver_t *zvm)
+{
+ char buf[1024],
+ *endPtr,
+ *opt,
+ *arg;
+ int32_t lSrvName,
+ lTarget;
+ int fence = ACT_OFFON;
+
+ while (fgets (buf, sizeof (buf), stdin) != 0) {
+ if (trim(buf) == 0) {
+ continue;
+ }
+ if (buf[0] == '#') {
+ continue;
+ }
+
+ opt = buf;
+
+ if ((arg = strchr(opt, '=')) != 0) {
+ *arg = 0;
+ arg++;
+ } else {
+ continue;
+ }
+
+ if (trim(arg) == 0)
+ continue;
+
+ if (!strcasecmp (opt, "action")) {
+ if (strcasecmp(arg, "reboot") == 0) {
+ fence = ACT_OFFON;
+ } else if (strcasecmp(arg, "off") == 0) {
+ fence = ACT_OFF;
+ } else if (strcasecmp(arg, "on") == 0) {
+ fence = ACT_ON;
+ } else if (strcasecmp(arg, "metadata") == 0) {
+ fence = ACT_METADATA;
+ } else if (strcasecmp(arg, "status") == 0) {
+ fence = ACT_STATUS;
+ } else if (strcasecmp(arg, "monitor") == 0) {
+ fence = ACT_MONITOR;
+ } else if (strcasecmp(arg, "list") == 0) {
+ fence = ACT_LIST;
+ } else {
+ fence = ACT_HELP;
+ }
+ } else if (!strcasecmp (opt, "ipaddr")) {
+ lSrvName = MIN(strlen(arg), sizeof(zvm->smapiSrv)-1);
+ memcpy(zvm->smapiSrv, arg, lSrvName);
+ continue;
+ } else if (!strcasecmp (opt, "login")) {
+ lSrvName = MIN(strlen(arg), sizeof(zvm->authUser)-1);
+ memcpy(zvm->authUser, arg, lSrvName);
+ continue;
+ } else if (!strcasecmp (opt, "passwd")) {
+ lSrvName = MIN(strlen(arg), sizeof(zvm->authPass)-1);
+ memcpy(zvm->authPass, arg, lSrvName);
+ continue;
+ } else if (!strcasecmp (opt, "port")) {
+ lTarget = MIN(strlen(arg), sizeof(zvm->target)-1);
+ strncpy(zvm->target, arg, lTarget);
+ continue;
+ } if (!strcasecmp (opt, "timeout")) {
+ zvm->timeOut = strtoul(arg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog(LOG_WARNING, "Invalid timeout value specified %s "
+ "defaulting to %d",
+ arg, DEFAULT_TIMEOUT);
+ zvm->timeOut = DEFAULT_TIMEOUT;
+ }
+ } else if (!strcasecmp (opt, "help")) {
+ fence = ACT_HELP;
+ }
+ }
+ return(fence);
+}
+
+/**
+ * get_options - get options from the command line
+ * @argc - Count of arguments
+ * @argv - Array of character strings
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+get_options(int argc, char **argv, zvm_driver_t *zvm)
+{
+ int c,
+ fence = ACT_OFFON;
+ int32_t lSrvName,
+ lTarget;
+ char *endPtr;
+
+ while ((c = getopt_long(argc, argv, optString, longopts, NULL)) != -1) {
+ switch (c) {
+ case 'a' :
+ lSrvName = MIN(strlen(optarg), sizeof(zvm->smapiSrv)-1);
+ memcpy(zvm->smapiSrv, optarg, lSrvName);
+ break;
+ case 'n' :
+ lTarget = MIN(strlen(optarg), sizeof(zvm->target)-1);
+ memcpy(zvm->target, optarg, lTarget);
+ break;
+ case 'o' :
+ if (strcasecmp(optarg, "reboot") == 0) {
+ fence = ACT_OFFON;
+ } else if (strcasecmp(optarg, "off") == 0) {
+ fence = ACT_OFF;
+ } else if (strcasecmp(optarg, "on") == 0) {
+ fence = ACT_ON;
+ } else if (strcasecmp(optarg, "metadata") == 0) {
+ fence = ACT_METADATA;
+ } else if (strcasecmp(optarg, "status") == 0) {
+ fence = ACT_STATUS;
+ } else if (strcasecmp(optarg, "monitor") == 0) {
+ fence = ACT_MONITOR;
+ } else if (strcasecmp(optarg, "list") == 0) {
+ fence = ACT_LIST;
+ } else {
+ fence = ACT_HELP;
+ }
+ break;
+ case 'p' :
+ lSrvName = MIN(strlen(optarg), 8);
+ memcpy(zvm->authPass, optarg, lSrvName);
+ break;
+ case 'u' :
+ lSrvName = MIN(strlen(optarg), 8);
+ memcpy(zvm->authUser, optarg, lSrvName);
+ break;
+ case 't' :
+ zvm->timeOut = strtoul(optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog(LOG_WARNING, "Invalid timeout value specified: %s - "
+ "defaulting to %d",
+ optarg, DEFAULT_TIMEOUT);
+ zvm->timeOut = DEFAULT_TIMEOUT;
+ }
+ break;
+ case 'd' :
+ zvm->delay = strtoul(optarg, &endPtr, 10);
+ if (*endPtr != 0) {
+ syslog(LOG_WARNING, "Invalid delay value specified: %s - "
+ "defaulting to %d",
+ optarg, DEFAULT_DELAY);
+ zvm->delay = DEFAULT_DELAY;
+ }
+ break;
+ default :
+ fence = ACT_HELP;
+ }
+ }
+ return(fence);
+}
+
+/**
+ * zvm_metadata - Show fence metadata
+ * @self - Path to this executable
+ *
+ */
+static int
+zvm_metadata()
+{
+ fprintf (stdout, "<?xml version=\"1.0\" ?>\n");
+ fprintf (stdout, "<resource-agent name=\"fence_zvmip\"");
+ fprintf (stdout, " shortdesc=\"Fence agent for use with z/VM Virtual Machines\">\n");
+ fprintf (stdout, "<longdesc>");
+ fprintf (stdout, "The fence_zvm agent is intended to be used with with z/VM SMAPI service via TCP/IP");
+ fprintf (stdout, "</longdesc>\n");
+ fprintf (stdout, "<vendor-url>http://www.ibm.com</vendor-url>\n");
+
+ fprintf (stdout, "<parameters>\n");
+
+ fprintf (stdout, "\t<parameter name=\"port\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-n, --plug\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Name of the Virtual Machine to be fenced");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"ipaddr\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-i, --ip\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "IP Name or Address of SMAPI Server");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"login\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-u, --username\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Name of authorized SMAPI user");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"passwd\" unique=\"1\" required=\"1\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-p, --password\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Password of authorized SMAPI user");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"action\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-o, --action\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"off\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Fencing action");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"delay\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"--delay\" />\n");
+ fprintf (stdout, "\t\t<content type=\"string\" default=\"0\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Time to delay fencing action in seconds");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "\t<parameter name=\"usage\" unique=\"1\" required=\"0\">\n");
+ fprintf (stdout, "\t\t<getopt mixed=\"-h, --help\" />\n");
+ fprintf (stdout, "\t\t<content type=\"boolean\" />\n");
+ fprintf (stdout, "\t\t<shortdesc lang=\"en\">%s</shortdesc>\n",
+ "Print usage");
+ fprintf (stdout, "\t</parameter>\n");
+
+ fprintf (stdout, "</parameters>\n");
+
+ fprintf (stdout, "<actions>\n");
+ fprintf (stdout, "\t<action name=\"off\" />\n");
+ fprintf (stdout, "\t<action name=\"on\" automatic=\"0\" />\n");
+ fprintf (stdout, "\t<action name=\"list\" />\n");
+ fprintf (stdout, "\t<action name=\"metadata\" />\n");
+ fprintf (stdout, "\t<action name=\"monitor\" />\n");
+ fprintf (stdout, "\t<action name=\"status\" />\n");
+ fprintf (stdout, "\t<action name=\"reboot\" />\n");
+ fprintf (stdout, "</actions>\n");
+
+ fprintf (stdout, "</resource-agent>\n");
+
+ return(0);
+
+}
+
+/**
+ * usage - display command syntax and parameters
+ *
+ */
+static int
+usage()
+{
+ fprintf(stderr,"Usage: fence_zvmip [options]\n\n"
+ "\tWhere [options] =\n"
+ "\t-o --action [action] - \"off\", \"on\", \"list\", \"metadata\", "
+ "\"monitor\", \"reboot\", \"status\"\n"
+ "\t--delay [seconds] - Time to delay fencing action in seconds\n"
+ "\t-n --plug [target] - Name of virtual machine to fence\n"
+ "\t-a --ip [server] - IP Name/Address of SMAPI Server\n"
+ "\t-u --username [user] - Name of autorized SMAPI user\n"
+ "\t-p --password [pass] - Password of autorized SMAPI user\n"
+ "\t-t --timeout [secs] - Time to wait for fence in seconds - currently ignored\n"
+ "\t-h --help - Display this usage information\n");
+ return(1);
+}
+
+/**
+ * check_param - Check that mandatory parameters have been specified
+ * @zvm - Pointer to driver information
+ *
+ */
+static int
+check_parm(zvm_driver_t *zvm)
+{
+ int rc;
+
+ if (zvm->smapiSrv[0] != 0) {
+ if (zvm->target[0] != 0) {
+ if (zvm->authUser[0] != 0) {
+ if (zvm->authPass[0] != 0) {
+ rc = 0;
+ } else {
+ syslog(LOG_ERR, "Missing authorized password");
+ rc = 4;
+ }
+ } else {
+ syslog(LOG_ERR, "Missing authorized user name");
+ rc = 3;
+ }
+ } else {
+ syslog(LOG_ERR, "Missing fence target name");
+ rc = 2;
+ }
+ } else {
+ syslog(LOG_ERR, "Missing SMAPI server name");
+ rc = 1;
+ }
+ return(rc);
+}
+
+int
+main(int argc, char **argv)
+{
+ zvm_driver_t zvm;
+ int fence = 1,
+ rc = 0;
+
+ openlog ("fence_zvmip", LOG_CONS|LOG_PID, LOG_DAEMON);
+ memset(&zvm, 0, sizeof(zvm));
+ zvm.timeOut = DEFAULT_TIMEOUT;
+ zvm.delay = DEFAULT_DELAY;
+
+ if (argc > 1)
+ fence = get_options(argc, argv, &zvm);
+ else
+ fence = get_options_stdin(&zvm);
+
+ switch(fence) {
+ case ACT_OFFON : // OFFON
+ if ((rc = check_parm(&zvm)) == 0)
+ rc = zvm_smapi_imageRecycle(&zvm);
+ break;
+ case ACT_OFF : // OFF
+ if ((rc = check_parm(&zvm)) == 0)
+ rc = zvm_smapi_imageDeactivate(&zvm);
+ break;
+ case ACT_ON : // ON
+ if ((rc = check_parm(&zvm)) == 0)
+ rc = zvm_smapi_imageActivate(&zvm);
+ break;
+ case ACT_METADATA : // METADATA
+ rc = zvm_metadata();
+ break;
+ case ACT_STATUS : // STATUS
+ if ((rc = check_parm(&zvm)) == 0)
+ rc = zvm_smapi_imageQuery(&zvm);
+ break;
+ case ACT_MONITOR : // MONITOR
+ rc = 0;
+ break;
+ case ACT_LIST :
+ printf("N/A");
+ break;
+ case ACT_HELP :
+ rc = usage();
+ }
+ closelog();
+ return (rc);
+}
diff --git a/agents/zvm/fence_zvmip.py b/agents/zvm/fence_zvmip.py
new file mode 100644
index 0000000..4f538e1
--- /dev/null
+++ b/agents/zvm/fence_zvmip.py
@@ -0,0 +1,226 @@
+#!@PYTHON@ -tt
+
+import sys
+import atexit
+import socket
+import struct
+import logging
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, fail_usage, run_delay, EC_LOGIN_DENIED, EC_TIMED_OUT
+
+INT4 = 4
+
+def open_socket(options):
+ try:
+ if "--inet6-only" in options:
+ protocol = socket.AF_INET6
+ elif "--inet4-only" in options:
+ protocol = socket.AF_INET
+ else:
+ protocol = 0
+ (_, _, _, _, addr) = socket.getaddrinfo( \
+ options["--ip"], options["--ipport"], protocol,
+ 0, socket.IPPROTO_TCP, socket.AI_PASSIVE
+ )[0]
+ except socket.gaierror:
+ fail(EC_LOGIN_DENIED)
+
+ if "--ssl-secure" in options or "--ssl-insecure" in options:
+ import ssl
+ sock = socket.socket()
+ sslcx = ssl.create_default_context()
+ if "--ssl-insecure" in options:
+ sslcx.check_hostname = False
+ sslcx.verify_mode = ssl.CERT_NONE
+ conn = sslcx.wrap_socket(sock, server_hostname=options["--ip"])
+ else:
+ conn = socket.socket()
+ conn.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ conn.settimeout(float(options["--shell-timeout"]) or None)
+ try:
+ conn.connect(addr)
+ except socket.error as e:
+ logging.debug(e)
+ fail(EC_LOGIN_DENIED)
+
+ return conn
+
+def smapi_pack_string(string):
+ return struct.pack("!i%ds" % (len(string)), len(string), string.encode("UTF-8"))
+
+def prepare_smapi_command(options, smapi_function, additional_args):
+ packet_size = 3*INT4 + len(smapi_function) + len(options["--username"]) + len(options["--password"])
+ for arg in additional_args:
+ packet_size += INT4 + len(arg)
+
+ command = struct.pack("!i", packet_size)
+ command += smapi_pack_string(smapi_function)
+ command += smapi_pack_string(options["--username"])
+ command += smapi_pack_string(options["--password"])
+ for arg in additional_args:
+ command += smapi_pack_string(arg)
+
+ return command
+
+def get_power_status(conn, options):
+ del conn
+
+ if options.get("--original-action", None) == "monitor":
+ (return_code, reason_code, images_active) = \
+ get_list_of_images(options, "Check_Authentication", None)
+
+ logging.debug("Check_Authenticate (%d,%d)", return_code, reason_code)
+ if return_code == 0:
+ return {}
+ else:
+ fail(EC_LOGIN_DENIED)
+
+ if options["--action"] == "list":
+ # '*' = list all active images
+ options["--plug"] = "*"
+
+ (return_code, reason_code, images_active) = \
+ get_list_of_images(options, "Image_Status_Query", options["--plug"])
+ logging.debug("Image_Status_Query results are (%d,%d)", return_code, reason_code)
+
+ if not options["--action"] == "list":
+ if (return_code == 0) and (reason_code == 0):
+ return "on"
+ elif (return_code == 0) and (reason_code == 12):
+ # We are running always with --missing-as-off because we can not check if image
+ # is defined or not (look at rhbz#1188750)
+ return "off"
+ else:
+ return "unknown"
+ else:
+ (return_code, reason_code, images_defined) = \
+ get_list_of_images(options, "Image_Name_Query_DM", options["--username"])
+ logging.debug("Image_Name_Query_DM results are (%d,%d)", return_code, reason_code)
+
+ return dict([(i, ("", "on" if i in images_active else "off")) for i in images_defined])
+
+def set_power_status(conn, options):
+ conn = open_socket(options)
+
+ packet = None
+ if options["--action"] == "on":
+ packet = prepare_smapi_command(options, "Image_Activate", [options["--plug"]])
+ elif options["--action"] == "off":
+ packet = prepare_smapi_command(options, "Image_Deactivate", [options["--plug"], "IMMED"])
+ conn.send(packet)
+
+ request_id = struct.unpack("!i", conn.recv(INT4))[0]
+ (output_len, request_id, return_code, reason_code) = struct.unpack("!iiii", conn.recv(INT4 * 4))
+ logging.debug("Image_(De)Activate results are (%d,%d)", return_code, reason_code)
+
+ conn.close()
+ return
+
+def get_list_of_images(options, command, data_as_plug):
+ conn = open_socket(options)
+
+ if data_as_plug is None:
+ packet = prepare_smapi_command(options, command, [])
+ else:
+ packet = prepare_smapi_command(options, command, [data_as_plug])
+
+ conn.send(packet)
+
+ try:
+ request_id = struct.unpack("!i", conn.recv(INT4))[0]
+ (output_len, request_id, return_code, reason_code) = struct.unpack("!iiii", conn.recv(INT4 * 4))
+ except struct.error:
+ logging.debug(sys.exc_info())
+ fail_usage("Failed: Unable to connect to {} port: {} SSL: {} \n".format(options["--ip"], options["--ipport"], bool("--ssl" in options)))
+
+ images = set()
+
+ if output_len > 3*INT4:
+ recvflag = socket.MSG_WAITALL if "--ssl-secure" not in options and "--ssl-insecure" not in options else 0
+ array_len = struct.unpack("!i", conn.recv(INT4))[0]
+ data = ""
+
+ while True:
+ read_data = conn.recv(1024, recvflag).decode("UTF-8")
+ data += read_data
+ if array_len == len(data):
+ break
+ elif not read_data:
+ logging.error("Failed: Not enough data read from socket")
+ fail(EC_TIMED_OUT)
+
+ parsed_len = 0
+ while parsed_len < array_len:
+ string_len = struct.unpack("!i", data[parsed_len:parsed_len+INT4].encode("UTF-8"))[0]
+ parsed_len += INT4
+ image_name = struct.unpack("!%ds" % (string_len), data[parsed_len:parsed_len+string_len].encode("UTF-8"))[0].decode("UTF-8")
+ parsed_len += string_len
+ images.add(image_name)
+
+ conn.close()
+ return (return_code, reason_code, images)
+
+def define_new_opts():
+ all_opt["disable_ssl"] = {
+ "getopt" : "",
+ "longopt" : "disable-ssl",
+ "help" : "--disable-ssl Don't use SSL connection",
+ "required" : "0",
+ "shortdesc" : "Don't use SSL",
+ "order": 2
+ }
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "port", "method", "missing_as_off",
+ "inet4_only", "inet6_only", "ssl", "disable_ssl"]
+
+ atexit.register(atexit_handler)
+ define_new_opts()
+
+ all_opt["ssl"]["help"] = "-z, --ssl Use SSL connection with verifying certificate (Default)"
+
+ all_opt["ipport"]["default"] = "44444"
+ all_opt["shell_timeout"]["default"] = "5"
+ all_opt["missing_as_off"]["default"] = "1"
+ all_opt["ssl"]["default"] = "1"
+ options = check_input(device_opt, process_input(device_opt), other_conditions=True)
+
+ if "--disable-ssl" in options or options["--ssl"] == "0":
+ for k in ["--ssl", "--ssl-secure", "--ssl-insecure"]:
+ if k in options:
+ del options[k]
+
+ if len(options.get("--plug", "")) > 8:
+ fail_usage("Failed: Name of image can not be longer than 8 characters")
+
+ if options["--action"] == "validate-all":
+ sys.exit(0)
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for use with z/VM Virtual Machines"
+ docs["longdesc"] = """The fence_zvm agent is intended to be used with with z/VM SMAPI service via TCP/IP
+
+To use this agent the z/VM SMAPI service needs to be configured to allow the virtual machine running this agent to connect to it and issue
+the image_recycle operation. This involves updating the VSMWORK1 AUTHLIST VMSYS:VSMWORK1. file. The entry should look something similar to
+this:
+
+Column 1 Column 66 Column 131
+
+ | | |
+ V V V
+
+XXXXXXXX ALL IMAGE_CHARACTERISTICS
+
+Where XXXXXXX is the name of the virtual machine used in the authuser field of the request. This virtual machine also has to be authorized
+to access the system's directory manager.
+"""
+ docs["vendorurl"] = "http://www.ibm.com"
+ show_docs(options, docs)
+
+ run_delay(options)
+ result = fence_action(None, options, set_power_status, get_power_status, get_power_status)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..f718cc6
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+# ("-I make" is superfluous, kept only for legacy purposes, if any)
+autoreconf -i -I make -v && echo Now run ./configure and make
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..65a9718
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,593 @@
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.63])
+
+# TODO: port .gitarchiver
+
+AC_INIT([fence-agents],
+ [m4_esyscmd([make/git-version-gen .tarball-version])],
+ [developers@clusterlabs.org])
+
+AC_CONFIG_AUX_DIR([.])
+
+# Don't let AC_PROC_CC (invoked by AC_USE_SYSTEM_EXTENSIONS) replace
+# undefined CFLAGS with -g -O2, overriding our special OPT_CFLAGS.
+: ${CFLAGS=""}
+AC_USE_SYSTEM_EXTENSIONS
+AM_INIT_AUTOMAKE([1.13 dist-bzip2 dist-xz color-tests -Wno-portability subdir-objects])
+
+# Sanitize path
+
+if test "$prefix" = "NONE"; then
+ prefix="/usr"
+ if test "$localstatedir" = "\${prefix}/var"; then
+ localstatedir="/var"
+ fi
+ if test "$sysconfdir" = "\${prefix}/etc"; then
+ sysconfdir="/etc"
+ fi
+ if test "$libdir" = "\${exec_prefix}/lib"; then
+ if test -e /usr/lib64; then
+ libdir="/usr/lib64"
+ else
+ libdir="/usr/lib"
+ fi
+ fi
+fi
+
+case $exec_prefix in
+ NONE) exec_prefix=$prefix;;
+ prefix) exec_prefix=$prefix;;
+esac
+
+# It is necessary to have this done before libtool does linker detection.
+# See also: https://github.com/kronosnet/kronosnet/issues/107
+# --as-needed: Modern systems have builtin ceil() making -lm superfluous but
+# AC_SEARCH_LIBS can't detect this because it tests with a false prototype
+AX_CHECK_LINK_FLAG([-Wl,--enable-new-dtags],
+ [AM_LDFLAGS=-Wl,--enable-new-dtags],
+ [AC_MSG_ERROR(["Linker support for --enable-new-dtags is required"])])
+AX_CHECK_LINK_FLAG([-Wl,--as-needed], [AM_LDFLAGS="$AM_LDFLAGS -Wl,--as-needed"])
+
+LT_PREREQ([2.2.6])
+LT_INIT
+
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_SRCDIR([lib/fencing.py.py])
+AC_CONFIG_HEADERS([make/config.h])
+
+AC_CANONICAL_HOST
+AC_PROG_LIBTOOL
+
+AC_LANG([C])
+
+# Checks for programs.
+
+# check stolen from gnulib/m4/gnu-make.m4
+if ! ${MAKE-make} --version /cannot/make/this >/dev/null 2>&1; then
+ AC_MSG_ERROR([you don't seem to have GNU make; it is required])
+fi
+
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_GCC_TRADITIONAL
+AC_PROG_LN_S
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_PROG_AWK
+AC_PROG_CXX
+AC_PROG_YACC
+AC_PROG_LEX
+PKG_PROG_PKG_CONFIG
+
+## local helper functions
+
+# this function checks if CC support options passed as
+# args. Global CFLAGS are ignored during this test.
+cc_supports_flag() {
+ local CFLAGS="-Werror $@"
+ AC_MSG_CHECKING([whether $CC supports "$@"])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[ ]])],
+ [RC=0; AC_MSG_RESULT([yes])],
+ [RC=1; AC_MSG_RESULT([no])])
+ return $RC
+}
+
+# Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_HEADER_TIME
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h malloc.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h syslog.h termios.h unistd.h libintl.h limits.h netdb.h stddef.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_INLINE
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT32_T
+AC_TYPE_OFF_T
+AC_TYPE_SIGNAL
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+AC_FUNC_CLOSEDIR_VOID
+AC_FUNC_MEMCMP
+AC_FUNC_SELECT_ARGTYPES
+AC_FUNC_STAT
+AC_CHECK_FUNCS([alarm atexit bzero dup2 memmove memset select socket strcasecmp strchr strdup strerror strtol gettimeofday])
+
+# local options
+AC_ARG_ENABLE([debug],
+ [ --enable-debug enable debug build. ],
+ [ default="no" ])
+
+AC_ARG_WITH([fenceagentslibdir],
+ [ --with-fenceagentslibdir=PATH
+ installation path for fence library. ],
+ [ FENCEAGENTSLIBDIR="$withval" ],
+ [ FENCEAGENTSLIBDIR="${datadir}/fence" ])
+
+AC_ARG_WITH([agents],
+ [ --with-agents=LIST
+ list of agents to build/ship (default: all). ],
+ [ AGENTS_LIST="$withval" ],
+ [ AGENTS_LIST="all" ])
+
+FENCETMPDIR=${localstatedir}/run/fence-agents
+AC_ARG_WITH(fencetmpdir,
+ [ --with-fencetmpdir=DIR directory for fence agents state files [${FENCETMPDIR}]],
+ [ FENCETMPDIR="$withval" ])
+
+# Expand $prefix
+eval FENCETMPDIR="`eval echo ${FENCETMPDIR}`"
+AC_DEFINE_UNQUOTED(FENCETMPDIR,"$FENCETMPDIR", Where Fence agents keep state files)
+AC_SUBST(FENCETMPDIR)
+
+
+if test "x$AGENTS_LIST" = x; then
+ AC_ERROR([No agents selected])
+fi
+
+# PKG_CHECK_MODULES will fail if systemd is not found by default, so make sure
+# we set the proper vars and deal with it
+PKG_CHECK_MODULES([systemd], [systemd], [HAS_SYSTEMD=yes], [HAS_SYSTEMD=no])
+if test "x$HAS_SYSTEMD" == "xyes"; then
+ PKG_CHECK_VAR([SYSTEMD_TMPFILES_DIR], [systemd], [tmpfilesdir])
+ if test "x$SYSTEMD_TMPFILES_DIR" == "x"; then
+ AC_MSG_ERROR([Unable to detect systemd tmpfiles directory automatically])
+ fi
+
+ # sanitize systed vars when using non standard prefix
+ if test "$prefix" != "/usr"; then
+ SYSTEMD_TMPFILES_DIR="$prefix/$SYSTEMD_TMPFILES_DIR"
+ AC_SUBST([SYSTEMD_TMPFILES_DIR])
+ fi
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test "x$HAS_SYSTEMD" == xyes ])
+
+FENCE_KDUMP=0
+if echo "$AGENTS_LIST" | grep -q -E "all|kdump"; then
+ case "$host_os" in
+ *bsd*)
+ ;;
+ *)
+ FENCE_KDUMP=1
+ ;;
+ esac
+ AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/kdump( |$)//")
+fi
+
+FENCE_MANUAL=0
+if echo "$AGENTS_LIST" | grep -q -E "all|manual"; then
+ FENCE_MANUAL=1
+ AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/manual( |$)//")
+fi
+
+FENCE_MPATH=0
+if echo "$AGENTS_LIST" | grep -q -E "all|mpath"; then
+ FENCE_MPATH=1
+fi
+
+FENCE_SCSI=0
+if echo "$AGENTS_LIST" | grep -q -E "all|scsi"; then
+ FENCE_SCSI=1
+fi
+
+FENCE_ZVM=0
+if echo "$AGENTS_LIST" | grep -q -E "zvm( |$)"; then
+ FENCE_ZVM=1
+fi
+
+FENCE_VIRT=0
+if echo "$AGENTS_LIST" | grep -q -E "all|(^| )virt( |$)"; then
+ AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s/(^| )virt( |$)//")
+ case "$host_os" in
+ *bsd*)
+ ;;
+ *)
+ FENCE_VIRT=1
+
+ VIRT_AM_LDFLAGS="$AM_LDFLAGS -fPIC -fPIE -Wl,-z,now"
+ AC_SUBST([VIRT_AM_LDFLAGS])
+
+ VIRT_AM_CFLAGS="-fPIC -fPIE -I\$(top_srcdir)/agents/virt/include -D_GNU_SOURCE"
+ AC_SUBST([VIRT_AM_CFLAGS])
+
+ VIRT_COMMON_LDFLAGS="-Wl,-wrap,syslog,-wrap,closelog"
+ AC_SUBST([VIRT_COMMON_LDFLAGS])
+
+ VIRT_COMMON_LIBS="-Wl,-Bstatic -L\$(top_builddir)/agents/virt/common -lfence_virt -Wl,-Bdynamic"
+ AC_SUBST([VIRT_COMMON_LIBS])
+
+ VIRT_CONFIG_LIBS="-L\$(top_builddir)/agents/virt/config -lsimpleconfig"
+ AC_SUBST([VIRT_CONFIG_LIBS])
+
+ # Checks for libraries.
+ AX_PTHREAD(,[AC_MSG_ERROR([POSIX threads support is required])])
+ PKG_CHECK_MODULES([nss], [nss])
+ PKG_CHECK_MODULES([xml2], [libxml-2.0])
+ PKG_CHECK_MODULES([uuid], [uuid])
+ saved_LIBS="$LIBS"
+ LIBS=
+ AC_SEARCH_LIBS([dlopen], [dl dld], , [AC_MSG_ERROR([dlopen not found])])
+ AC_SUBST([dl_LIBS], [$LIBS])
+ LIBS="$saved_LIBS"
+ ;;
+ esac
+fi
+
+if test "x$AGENTS_LIST" != xall; then
+ for j in $AGENTS_LIST; do
+ if ! test -f agents/$j/fence_$j*.py; then
+ AC_ERROR([Agent $j does not exist])
+ fi
+ AGENTS_LIST=`echo "$AGENTS_LIST" | sed -E -e "s#$j([^_/]|$)#$j/fence_$j\1#g" -e "s#zvm/fence_zvm( |$)#zvm/fence_zvmip\1#g"`
+ done
+fi
+
+if test "x$AGENTS_LIST" = xall; then
+ AGENTS_LIST=`find $srcdir/agents -mindepth 2 -maxdepth 2 -name 'fence_*.py' -print0 | xargs -0 | sed -E -e 's#[^ ]*/agents/##g' -e 's#lib/[A-Za-z_.]*( |$)##g' -e 's#nss_wrapper/[A-Za-z_.]*( |$)##g' -e 's#autodetect/[A-Za-z_.]*( |$)##g'`
+fi
+
+XENAPILIB=0
+if echo "$AGENTS_LIST" | grep -q xenapi; then
+ XENAPILIB=1
+fi
+
+## random vars
+
+LOGDIR=${localstatedir}/log/cluster
+CLUSTERVARRUN=${localstatedir}/run/cluster
+CLUSTERDATA=${datadir}/cluster
+
+AC_PATH_PROGS(XMLLINT, xmllint)
+AM_CONDITIONAL(BUILD_DOC, test "x$XMLLINT" != "x" )
+if test "x$XMLLINT" = "x"; then
+ AC_MSG_WARN([xmllint not installed, unable to (re-)build manual pages])
+ exit 1
+fi
+AC_SUBST(XMLLINT)
+
+AC_PATH_PROGS(XSLTPROC, xsltproc)
+AM_CONDITIONAL(BUILD_DOC, test "x$XSLTPROC" != "x" )
+if test "x$XSLTPROC" = "x"; then
+ AC_MSG_WARN([xsltproc not installed, unable to (re-)build manual pages])
+ exit 1
+fi
+AC_SUBST(XSLTPROC)
+
+AM_PATH_PYTHON
+if test -z "$PYTHON"; then
+ echo "*** Essential program python not found" 1>&2
+ exit 1
+fi
+
+dnl Ensure PYTHON is an absolute path
+AC_PATH_PROG([PYTHON], [$PYTHON])
+
+AC_PYTHON_MODULE(pexpect, 1)
+AC_PYTHON_MODULE(pycurl, 1)
+AC_PYTHON_MODULE(requests, 1)
+
+if echo "$AGENTS_LIST" | grep -q amt_ws; then
+ AC_PYTHON_MODULE(pywsman)
+ if test "x${HAVE_PYMOD_PYWSMAN}" != xyes; then
+ AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s#amt_ws/fence_amt_ws.py( |$)##")
+ AC_MSG_WARN("Not building fence_amt_ws")
+ fi
+fi
+if echo "$AGENTS_LIST" | grep -q -E "ovh|vmware_soap"; then
+ AC_PYTHON_MODULE(suds)
+ if test "x${HAVE_PYMOD_SUDS}" != xyes; then
+ AGENTS_LIST=$(echo "$AGENTS_LIST" | sed -E "s#(ovh/fence_ovh|vmware_soap/fence_vmware_soap).py( |$)##g")
+ AC_MSG_WARN("Not building fence_ovh and fence_vmware_soap")
+ fi
+fi
+if echo "$AGENTS_LIST" | grep -q gce; then
+ AC_PYTHON_MODULE(google.auth)
+fi
+
+## path to 3rd-party binaries
+AC_PATH_PROG([IPMITOOL_PATH], [ipmitool], [/usr/bin/ipmitool])
+AC_PATH_PROG([OPENSTACK_PATH], [openstack], [/usr/bin/openstack])
+AC_PATH_PROG([AMTTOOL_PATH], [amttool], [/usr/bin/amttool])
+AC_PATH_PROG([GNUTLSCLI_PATH], [gnutlscli], [/usr/bin/gnutls-cli])
+AC_PATH_PROG([COROSYNC_CMAPCTL_PATH], [corosync-cmapctl], [/usr/sbin/corosync-cmapctl])
+AC_PATH_PROG([SG_PERSIST_PATH], [sg_persist], [/usr/bin/sg_persist])
+AC_PATH_PROG([SG_TURS_PATH], [sg_turs], [/usr/bin/sg_turs])
+AC_PATH_PROG([VGS_PATH], [vgs], [/usr/sbin/vgs])
+AC_PATH_PROG([SUDO_PATH], [sudo], [/usr/bin/sudo])
+AC_PATH_PROG([SSH_PATH], [ssh], [/usr/bin/ssh])
+AC_PATH_PROG([TELNET_PATH], [telnet], [/usr/bin/telnet])
+AC_PATH_PROG([MPATH_PATH], [mpathpersist], [/usr/sbin/mpathpersist])
+AC_PATH_PROG([SBD_PATH], [sbd], [/sbin/sbd])
+AC_PATH_PROG([SUDO_PATH], [sudo], [/usr/bin/sudo])
+AC_PATH_PROG([SNMPWALK_PATH], [snmpwalk], [/usr/bin/snmpwalk])
+AC_PATH_PROG([SNMPSET_PATH], [snmpset], [/usr/bin/snmpset])
+AC_PATH_PROG([SNMPGET_PATH], [snmpget], [/usr/bin/snmpget])
+AC_PATH_PROG([NOVA_PATH], [nova], [/usr/bin/nova])
+AC_PATH_PROG([POWERMAN_PATH], [powerman], [/usr/bin/powerman])
+
+AC_PATH_PROG([PING_CMD], [ping])
+AC_PATH_PROG([PING6_CMD], [ping6])
+AC_PATH_PROG([PING4_CMD], [ping4])
+
+if test "x${ac_cv_path_PING_CMD}" = x; then
+ # assume multicall-ping just not available in build-environment
+ PING_CMD="/bin/ping"
+ PING4_CMD="/bin/ping -4"
+ PING6_CMD="/bin/ping -6"
+elif test "x${ac_cv_path_PING6_CMD}" = x; then
+ # just IPv4
+ PING4_CMD="${ac_cv_path_PING_CMD}"
+elif test -L ${ac_cv_path_PING6_CMD}; then
+ # assume multicall-ping
+ PING4_CMD="${ac_cv_path_PING_CMD} -4"
+else
+ # ping is just IPv4
+ PING4_CMD="${ac_cv_path_PING_CMD}"
+fi
+
+
+## do subst
+
+AC_SUBST([LOGDIR])
+AC_SUBST([CLUSTERVARRUN])
+AC_SUBST([CLUSTERDATA])
+AC_SUBST([FENCEAGENTSLIBDIR])
+AC_SUBST([SNMPBIN])
+AC_SUBST([AGENTS_LIST])
+AM_CONDITIONAL(BUILD_FENCE_KDUMP, test $FENCE_KDUMP -eq 1)
+AM_CONDITIONAL(BUILD_FENCE_MANUAL, test $FENCE_MANUAL -eq 1)
+AM_CONDITIONAL(BUILD_FENCE_MPATH, test $FENCE_MPATH -eq 1)
+AM_CONDITIONAL(BUILD_FENCE_SCSI, test $FENCE_SCSI -eq 1)
+AM_CONDITIONAL(BUILD_FENCE_ZVM, test $FENCE_ZVM -eq 1)
+AM_CONDITIONAL(BUILD_FENCE_VIRT, test $FENCE_VIRT -eq 1)
+AM_CONDITIONAL(BUILD_XENAPILIB, test $XENAPILIB -eq 1)
+
+AC_SUBST([IPMITOOL_PATH])
+AC_SUBST([OPENSTACK_PATH])
+AC_SUBST([AMTTOOL_PATH])
+AC_SUBST([COROSYNC_CMAPCTL_PATH])
+AC_SUBST([SG_PERSIST_PATH])
+AC_SUBST([SG_TURS_PATH])
+AC_SUBST([VGS_PATH])
+AC_SUBST([POWERMAN_PATH])
+
+## fence-virt stuff
+
+if test "x$FENCE_VIRT" = "x1"; then
+ sysconf=$(eval echo $sysconfdir)
+ AC_DEFINE_UNQUOTED([SYSCONFDIR], ["$sysconf"], [Default config dir])
+fi
+
+### The following options only are used when $modules="yes" ###
+
+# libvirt plugin: Enabled by default
+AC_ARG_ENABLE(libvirt-plugin,
+[AS_HELP_STRING([--disable-libvirt-plugin],
+ [Disable local-mode libvirt backend plugin])],
+[ modlibvirt=$enableval ], [ modlibvirt=yes ])
+
+AM_CONDITIONAL([modlibvirt], [test "x$modlibvirt" == "xyes"])
+if test "x$modlibvirt" == "xyes" && test "x$FENCE_VIRT" = "x1"; then
+ PKG_CHECK_MODULES([virt], [libvirt])
+fi
+
+# cpg plugin: Disabled by default
+AC_ARG_ENABLE(cpg-plugin,
+[AS_HELP_STRING([--disable-cpg-plugin],
+ [Enable CPG/libvirt backend plugin])],
+[ modcpg=$enableval ], [ modcpg=yes ])
+
+AM_CONDITIONAL([modcpg], [test "x$modcpg" == "xyes"])
+
+if test "x$modcpg" == "xyes" && test "x$FENCE_VIRT" = "x1"; then
+ PKG_CHECK_MODULES([cpg], [libcpg])
+fi
+
+# multicast plugin: Enabled by default
+AC_ARG_ENABLE(multicast-plugin,
+[AS_HELP_STRING([--disable-multicast-plugin],
+ [Disable multicast listener plugin])],
+[ modmulticast=$enableval ], [ modmulticast=yes ])
+
+AM_CONDITIONAL([modmulticast], [test "x$modmulticast" == "xyes"])
+
+# tcp plugin: Enabled by default
+AC_ARG_ENABLE(tcp-plugin,
+[AS_HELP_STRING([--disable-tcp-plugin],
+ [Disable TCP listener plugin])],
+[ modtcp=$enableval ], [ modtcp=yes ])
+
+AM_CONDITIONAL([modtcp], [test "x$modtcp" == "xyes"])
+
+# serial/libvirt plugin: Enabled by default
+AC_ARG_ENABLE(serial-plugin,
+[AS_HELP_STRING([--disable-serial-plugin],
+ [Disable serial listener plugin])],
+[ modserial=$enableval ], [ modserial=yes ])
+
+AM_CONDITIONAL([modserial], [test "x$modserial" == "xyes"])
+
+# vsock plugin: Enabled by default
+AC_ARG_ENABLE(vsock-plugin,
+[AS_HELP_STRING([--disable-vsock-plugin],
+ [Disable TCP listener plugin])],
+[ modvsock=$enableval ], [ modvsock=yes ])
+
+AM_CONDITIONAL([modvsock], [test "x$modvsock" == "xyes"])
+
+#
+# Compatibility symlink: enabled by default
+#
+AC_ARG_ENABLE(xvm-compat,
+[AS_HELP_STRING([--disable-xvm-compat],
+ [Disable fence_xvm symlink compatibility])],
+[ xvmcompat=$enableval ], [ xvmcompat=yes ])
+
+AM_CONDITIONAL([xvmcompat], [test "x$xvmcompat" == "xyes"])
+
+# Try to detect the appropriate conf dir. Several systems have both /etc/default
+# and /etc/sysconfig but latter is always primary.
+AC_ARG_VAR(initconfdir, [directory for initscripts configuration])
+if test "x$initconfdir" = x && test "x$FENCE_VIRT" = "x1"; then
+ AC_CHECK_FILE(/etc/conf.d, [initconfdir='$(sysconfdir)/conf.d}'], [# Gentoo/Arch
+ AC_CHECK_FILE(/etc/sysconfig, [initconfdir='$(sysconfdir)/sysconfig'], [# RedHat/Fedora/Slax/Mandriva/S
+ AC_CHECK_FILE(/etc/default, [initconfdir='$(sysconfdir)/default'], [# Debian/Ubuntu
+ AC_MSG_ERROR([could not determine system initscripts config dir; please set initconfdir manually.])])])])
+fi
+
+## *FLAGS handling
+
+ENV_CFLAGS="$CFLAGS"
+ENV_CPPFLAGS="$CPPFLAGS"
+ENV_LDFLAGS="$LDFLAGS"
+
+# debug build stuff
+if test "x${enable_debug}" = xyes; then
+ AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code])
+ OPT_CFLAGS="-O0"
+else
+ OPT_CFLAGS="-O2"
+fi
+
+# gdb flags
+if test "x${GCC}" = xyes; then
+ GDB_FLAGS="-ggdb3"
+else
+ GDB_FLAGS="-g"
+fi
+
+# extra warnings
+EXTRA_WARNINGS=""
+
+WARNLIST="
+ error
+ all
+ shadow
+ missing-prototypes
+ missing-declarations
+ strict-prototypes
+ declaration-after-statement
+ pointer-arith
+ write-strings
+ cast-align
+ bad-function-cast
+ missing-format-attribute
+ format=2
+ format-security
+ format-nonliteral
+ no-long-long
+ unsigned-char
+ gnu89-inline
+ no-strict-aliasing
+ "
+
+for j in $WARNLIST; do
+ if cc_supports_flag -W$j; then
+ EXTRA_WARNINGS="$EXTRA_WARNINGS -W$j";
+ fi
+done
+
+AM_CFLAGS="$ENV_CFLAGS $OPT_CFLAGS $GDB_FLAGS $EXTRA_WARNINGS"
+
+AC_SUBST([AM_CFLAGS])
+
+CPPFLAGS="-I\$(top_builddir)/make -I\$(top_srcdir)/make -I. $ENV_CPPFLAGS"
+LDFLAGS="$ENV_LDFLAGS"
+
+AM_EXTRA_RECURSIVE_TARGETS([delay-check xml-check xml-upload])
+
+AX_PROG_DATE
+AS_IF([test "$ax_cv_prog_date_gnu_date:$ax_cv_prog_date_gnu_utc" = yes:yes],
+ [UTC_DATE_AT="date -u -d@"],
+ [AS_IF([test "x$ax_cv_prog_date_bsd_date" = xyes],
+ [UTC_DATE_AT="date -u -r"],
+ [AC_MSG_ERROR([date utility unable to convert epoch to UTC])])])
+AC_SUBST([UTC_DATE_AT])
+
+AC_ARG_VAR([SOURCE_EPOCH],[last modification date of the source])
+AC_MSG_NOTICE([trying to determine source epoch])
+AC_MSG_CHECKING([for source epoch in \$SOURCE_EPOCH])
+AS_IF([test -n "$SOURCE_EPOCH"],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([for source epoch in source_epoch file])
+ AS_IF([test -e "$srcdir/source_epoch"],
+ [read SOURCE_EPOCH <"$srcdir/source_epoch"
+ AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([for source epoch baked in by gitattributes export-subst])
+ SOURCE_EPOCH='$Format:%at$' # template for rewriting by git-archive
+ AS_CASE([$SOURCE_EPOCH],
+ [?Format:*], # was not rewritten
+ [AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([for source epoch in \$SOURCE_DATE_EPOCH])
+ AS_IF([test "x$SOURCE_DATE_EPOCH" != x],
+ [SOURCE_EPOCH="$SOURCE_DATE_EPOCH"
+ AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_CHECKING([whether git log can provide a source epoch])
+ SOURCE_EPOCH=f${SOURCE_EPOCH#\$F} # convert into git log --pretty format
+ SOURCE_EPOCH=$(cd "$srcdir" && git log -1 --pretty=${SOURCE_EPOCH%$} 2>/dev/null)
+ AS_IF([test -n "$SOURCE_EPOCH"],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no, using current time and breaking reproducibility])
+ SOURCE_EPOCH=$(date +%s)])])],
+ [AC_MSG_RESULT([yes])]
+ )])
+ ])
+AC_MSG_NOTICE([using source epoch $($UTC_DATE_AT$SOURCE_EPOCH +'%F %T %Z')])
+
+if test "x$VERSION" = "xUNKNOWN"; then
+ AC_MSG_ERROR([m4_text_wrap([
+ configure was unable to determine the source tree's current version. This
+ generally happens when using git archive (or the github download button)
+ generated tarball/zip file. In order to workaround this issue, either use git
+ clone https://github.com/ClusterLabs/fence-virt.git or use an official release
+ tarball. Alternatively you can add a compatible version in a .tarball-version
+ file at the top of the source tree, wipe your autom4te.cache dir and generated
+ configure, and rerun autogen.sh.
+ ], [ ], [ ], [76])])
+fi
+
+
+AC_CONFIG_FILES([Makefile
+ fence-agents.pc
+ agents/Makefile
+ lib/Makefile
+ doc/Makefile
+ systemd/Makefile
+ systemd/fence-agents.conf
+ agents/virt/Makefile
+ agents/virt/config/Makefile
+ agents/virt/common/Makefile
+ agents/virt/client/Makefile
+ agents/virt/server/Makefile
+ agents/virt/man/Makefile
+ ])
+
+AC_OUTPUT
diff --git a/doc/COPYING.applications b/doc/COPYING.applications
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/doc/COPYING.applications
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/doc/COPYING.libraries b/doc/COPYING.libraries
new file mode 100644
index 0000000..2d2d780
--- /dev/null
+++ b/doc/COPYING.libraries
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/doc/COPYRIGHT b/doc/COPYRIGHT
new file mode 100644
index 0000000..4594455
--- /dev/null
+++ b/doc/COPYRIGHT
@@ -0,0 +1,86 @@
+Unless specified otherwise in the "exceptions section" below:
+
+Copyright (C) 1997-2003 Sistina Software, Inc. All rights reserved.
+Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
+
+Exceptions:
+
+agents/raritan_px3/*:
+ Copyright (c) 2021 SUSE LLC
+ Contributed by Thomas Renninger <trenn@suse.de>
+
+agents/ibmz/*:
+ Copyright (c) 2020 IBM Corp.
+ Contributed by Paulo de Rezende Pinatti <ppinatti at linux.ibm.com>
+
+agents/hds_cb/*:
+ Copyright (C) 2012 Matthew Clark.
+ Author: Matthew Clark <mattjclark0407 at hotmail.com>
+
+agents/xenapi/*:
+ Copyright (C) 2011 Matthew Clark.
+ Author: Matthew Clark <mattjclark0407 at hotmail.com>
+
+agents/apc_snmp/powernet369.mib:
+ Copyright (c) 2005 American Power Conversion, Inc.
+ PowerNet is a Trademark of American Power Conversion Corp.
+
+agents/eaton_snmp/fence_eaton_snmp.py:
+ Copyright (c) 2011 eaton.com
+ Author: Arnaud Quette <ArnaudQuette at Eaton.com>
+
+agents/ifmib/fence_ifmib.py:
+ Copyright (C) 2008-2011 Ross Vandegrift.
+ Written by Ross Vandegrift <ross at kallisti.us>
+
+agents/intelmodular/fence_intelmodular.pl:
+ Contributed by Matthew Kent <matt at bravenet.com>
+
+agents/ipmilan/expect.{c,h}:
+ Copyright (C) 2000 Alan Robertson <alanr at unix.sh>
+
+agents/node_assassin/*
+ Copyright (C) 2009-2011 Madison Kelly/Alteeve's Niche!
+ Author: Digimer <digimer at alteeve.com>
+
+agents/ecloud/fence_ecloud.py:
+ Copyright (C) 2022 ANS Group Limited
+ Author: Dane Elwell <dane.elwell@ans.co.uk>
+
+man/fence_ifmib.8:
+ Copyright (C) 2008-2011 Ross Vandegrift.
+ Written by Ross Vandegrift <ross at kallisti.us>
+
+Authors as known by current RCS as of the time of writing:
+
+Abhijith Das <adas at redhat.com>
+Adam Manthei <amanthei at redhat.com>
+A. J. Lewis <alewis at redhat.com>
+Alasdair G. Kergon <agk at redhat.com>
+Andrew Price <andy at andrewprice.me.uk>
+Benjamin Marzinski <bmarzins at redhat.com>
+Bob Peterson <rpeterso at redhat.com>
+Chris Feist <cfeist at redhat.com>
+Christine Caulfield <ccaulfie at redhat.com>
+Daniel Phillips <phillips at redhat.com>
+David Teigland <teigland at redhat.com>
+Fabio M. Di Nitto <fdinitto at redhat.com>
+James Parsons <jparsons at redhat.com>
+Joel Becker <joel.becker at oracle.com>
+Jonathan Brassow <jbrassow at redhat.com>
+jparsons <jparsons at redhat.com>
+Ken Preslan <kpreslan at redhat.com>
+Klaus Wenninger <kwenning at redhat.com>
+Lon Hohberger <lhh at redhat.com>
+Marc - A. Dahlhaus <mad at wol.de>
+Marek 'marx' Grac <mgrac at redhat.com>
+Mark Hlawatschek <hlawatschek at atix.de>
+Michael Conrad Tadpol Tilstra <mtilstra at redhat.com>
+Patrick Caulfield <pcaulfie at redhat.com>
+Robert Peterson <rpeterso at redhat.com>
+Ross Vandegrift <ross at kallisti.us>
+Ryan McCabe <rmccabe at redhat.com>
+Ryan O'Hara <rohara at redhat.com>
+Stanko Kupcevic <kupcevic at redhat.com>
+Steven Whitehouse <swhiteho at redhat.com>
+Wendy Cheng <wcheng at redhat.com>
diff --git a/doc/FenceAgentAPI.md b/doc/FenceAgentAPI.md
new file mode 100644
index 0000000..21956c6
--- /dev/null
+++ b/doc/FenceAgentAPI.md
@@ -0,0 +1,196 @@
+This page describes how to implement a fencing agent, and how agents are
+called from the cluster software.
+
+Fencing, generally, is a way to prevent an ill-behaved cluster member
+from accessing shared data in a way which would cause data or file
+system corruption. The canonical case where fencing is required is
+something like this: Node1 live-hangs with a lock on a GFS file system.
+Node2 thinks node1 is dead, takes a lock, and begins accessing the same
+data. Node1 wakes up and continues what it was doing. Because we can not
+predict when node1 would wake up or prevent it from issuing I/Os
+immediately after waking up, we need a way to prevent its I/Os from
+completing even if it does wake up.
+
+## Definitions
+
+- **I/O Fencing** is, in short, the act of preventing a node from
+ issuing I/Os (usually to shared storage). It is also known as
+ **STOMITH** or **STONITH**.
+- **Fencing devices** are hardware components used to prevent a node
+ from issuing I/Os.
+- **Fencing agents** are software components used to communicate with
+ **fencing devices** in order to perform **I/O Fencing**. In the
+ context of this project, they are standalone applications which are
+ spawned by the cluster software (compared to, for example, Linux-HA
+ which uses dynamically-loaded modules).
+- **Power fencing** is when a node is power-cycled, reset, or turned
+ off to prevent it from issuing I/Os
+- **Fabric fencing** is when a node's access to the shared data is cut
+ off at the device-level. Disabling a port on a fibre channel switch
+ (zoning), revoking a SCSI3 group reservation, or disabling access at
+ the SAN itself from a given initiator's GUID are all examples of
+ **fabric fencing**.
+- **Manual fencing** or **meatware** is when an administrator must
+ manually power-cycle a machine (or unplug its storage cables) and
+ follow up with the cluster, notifying the cluster that the machine
+ has been fenced. This is never recommended.
+
+## What is given to fencing agents by fenced & stonithd
+
+When the cluster decides a node must be fenced, a node is chosen to
+perform the task. The fence daemon ("fenced") is responsible for
+performing the request, and it spawns agents listed for a given node as
+noted in cluster.conf. When called by other pieces of software (fenced,
+fence\_node), fencing agents take arguments from standard input (as
+opposed to the command line) in the following format:
+
+ argument=value
+ #this line is ignored
+ argument2=value2
+
+- Lines beginning with a **\#** should be ignored
+- One line per argument
+- Argument and value are separated by an equals sign
+- If argument is specified several times only last value is used
+
+The following things are *not allowed* in this input:
+
+- Spaces in the argument (or anything else which isn't allowed by XML
+ standards for an attribute name)
+- Spaces between the argument and the equals sign (=)
+- Newlines in the value (or anything else which isn't allowed by XML
+ standards for an attribute value)
+
+The following are guidelines for parsing the arguments:
+
+- Quotation marks around the value is not necessary, and are not
+ provided by the fencing system. Simply parse from the equals sign to
+ the newline.
+- Equals signs are allowed in the argument, but it is not recommended.
+- Arguments which are not recognized *should be ignored* by the
+ fencing agent.
+
+### Example cluster.conf
+
+ <clusternodes>
+ <clusternode name="red.lab.boston.redhat.com" nodeid="1" votes="1">
+ <fence>
+ <method name="1">
+ <device name="ips-rack9" port="1" action="reboot"/>
+ </method>
+ </fence>
+ </clusternode>
+ ...
+ </clusternodes>
+ <fencedevices>
+ <fencedevice agent="fence_wti" name="ips-rack9" passwd="wti" ipaddr="ips-rack9"/>
+ </fencedevices>
+
+### Example input given to a fence\_agent
+
+Given the previous cluster.conf example, the following is sent to the
+agent named **fence\_wti** when the cluster decides to fence
+red.lab.boston.redhat.com:
+
+ agent=fence_wti
+ name=ips-rack9
+ passwd=wti
+ ipaddr=ips-rack9
+ port=1
+ action=reboot
+ nodename=red.lab.boston.redhat.com
+
+Note that fenced always passes the name of the node to be fenced via the
+nodename argument.
+
+## Agent Operations and Return Values
+
+- *off* - fence / turn off / etc. **This operation is required.**
+ Return values:
+ - 0 if the operation was successful, or
+ - 1 if not successful or verification could not be performed. This
+ includes inability to contact the fence device at any point.
+- *on* - un-fence / turn on / etc. Return values:
+ - 0 if the operation was successful, or
+ - 1 if not successful or verification could not be performed. This
+ includes inability to contact the fence device at any point.
+- *reboot* - this is normally an *off* followed by an *on*, but
+ not always. It is important to note that in some cases, this
+ operation is not verifiable. For example, if you use an integrated
+ power management feature like iLO or IPMI to reset the node, there
+ is no point at which the node has lost power. Return values:
+ - 0 if the *off* portion was successful (the *on* portion failing
+ is a don't-care case for the cluster, as it can recover safely)
+ - 1 if the *off* portion was unsuccessful (see above for reasons).
+- *status* - this is used by pacemaker to verify that the agent
+ is working. It is not required by 'fenced'. Use is encouraged.
+ Return values:
+ - 0 if the fence device is reachable and the port is in the *on*
+ state
+ - 1 if the fence device could not be contacted
+ - 2 if the fence device is reachable but is in the *off* state
+- *monitor* - Attempt to contact the fencing device. Typically,
+ 'status' for one-port hardware, and 'list' for multi-port hardware.
+ Return values:
+ - 0 if the fence device is reachable and working properly
+ - 1 if the fence device could not be contacted
+ - 2 if the fence device is reachable but is in the *off* state
+ (single-port hardware only)
+- *list* - Multi-port fencing devices only. Prints a list of port
+ names and assignments Return values:
+ - 0 if the fence device is reachable and working properly
+ - 1 if the fence device could not be contacted
+
+## Attribute Specifications
+
+These attributes *should* be used when implementing new agents, but this
+is not an exhaustive list. Some agents may have other arguments which
+are not covered here.
+
+- **action** - the operation (noted previously) to perform. This is
+ one of the following (case insensitive): on, off, reboot, monitor,
+ list, or status
+- **option** - (DEPRECATED; use action) - same as **action**
+- **ipaddr** - for a hostname or IP address
+- **login** - for a username or login name
+- **passwd** - for a password
+- **passwd\_script** - if your agent supports storing passwords
+ outside of cluster.conf, this is a script used to retrieve your
+ password (details on how this works will be added later). Generally,
+ this script simply echoes the password to standard output (and is
+ read in by the agent at run-time).
+- **port** - if you have to specify a plug or port (for example, on a
+ network-enabled PDU with 8 ports)
+- **nodename** - if the agent fences by node name, this is the
+ parameter to use (e.g. instead of port). In the event that both
+ *nodename* and *port* are specified, the preference is given to
+ *port*.
+
+## Implementation Best-Practices
+
+Currently, this project has a number of requirements which should be
+common to all agents (even if not currently):
+
+- **Verifiable operation** - When a node has been fenced by a
+ particular device, the agent *should* query the device to ensure the
+ new state has taken effect. For example, if you turn the a power
+ plug "off", the agent should, after doing this, query the device and
+ verify that the plug is in the "off" state. This is not necessary
+ for the "on" case or when you "un-fence" a node.
+- **Timeout is a failure, not success** - A timeout is an assumption,
+ and we want a guarantee, which is why we generally verify operations
+ from within the agents after performing them.
+- **Fabric fencing must never have a reboot operation** - Don't waste
+ time implementing one.
+- **There should be a command line mode, too** - for debugging, your
+ agent should be able to operate using arguments passed in via the
+ command line as well. How the mapping is done between the command
+ line arguments and stdin arguments is implementation dependent,
+ i.e., it's up to you ;)
+- **Whitespace in stdin** - existing agents tend to strip leading
+ whitespace (before the argument) when processing arguments from
+ standard input, but this is not a requirement. Whether whitespace is
+ stripped between the equals sign and newline in the value is
+ implementation dependent.
+- Output of **fence\_agent -o metadata** should validate against
+ RelaxNG schema available at [lib/metadata.rng](https://raw.githubusercontent.com/ClusterLabs/fence-agents/master/lib/metadata.rng)
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..13035fc
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,6 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+dist_doc_DATA = COPYING.applications \
+ COPYING.libraries \
+ COPYRIGHT \
+ README.licence
diff --git a/doc/README.licence b/doc/README.licence
new file mode 100644
index 0000000..075aa77
--- /dev/null
+++ b/doc/README.licence
@@ -0,0 +1,33 @@
+The Red Hat Cluster is a collection of free software built on top of different
+libraries and applications.
+
+For a detailed list of authors and copyright holders, please check the
+included COPYRIGHT file.
+
+Libraries:
+
+You can redistribute them and/or modify them under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+The libraries are distributed in the hope that they will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details.
+
+Applications:
+
+You can redistribute them and/or modify them 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.
+
+The applications are distributed in the hope that they 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.
+
+A copy of each license is included for your convenience in COPYING.applications
+and COPYING.libraries.
+
+If missing, write to the Free Software Foundation, Inc., 51 Franklin St,
+Fifth Floor, Boston, MA 02110-1301 USA.
diff --git a/fence-agents.pc.in b/fence-agents.pc.in
new file mode 100644
index 0000000..8695822
--- /dev/null
+++ b/fence-agents.pc.in
@@ -0,0 +1,7 @@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+Name: @PACKAGE_NAME@
+Description: fence agents for use with Pacemaker
+URL: https://github.com/ClusterLabs/fence-agents/
+Version: @PACKAGE_VERSION@
diff --git a/fence-agents.spec.in b/fence-agents.spec.in
new file mode 100644
index 0000000..3829693
--- /dev/null
+++ b/fence-agents.spec.in
@@ -0,0 +1,1445 @@
+###############################################################################
+###############################################################################
+##
+## Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
+##
+## This copyrighted material is made available to anyone wishing to use,
+## modify, copy, or redistribute it subject to the terms and conditions
+## of the GNU General Public License v.2.
+##
+###############################################################################
+###############################################################################
+
+%global rcver @rcver@
+%global alphatag @alphatag@
+%global numcomm @numcomm@
+%global dirty @dirty@
+
+Name: fence-agents
+Summary: Set of unified programs capable of host isolation ("fencing")
+Version: @version@
+Release: @specver@%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}
+License: GPLv2+ and LGPLv2+
+Group: System Environment/Base
+URL: https://github.com/ClusterLabs/fence-agents
+Source0: %{name}-%{version}%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}.tar.bz2
+
+%if 0%{?rhel} == 7
+%ifarch s390x
+%define rhel7_s390x 1
+%endif
+%endif
+
+%if 0%{?rhel} == 9
+%ifarch ppc64le s390x
+%define rhel9_ppc64le_s390x 1
+%endif
+%endif
+
+# skipped: pve, raritan, rcd-serial, virsh
+%global allfenceagents %(cat <<EOF
+fence-agents-alom \\
+fence-agents-amt \\
+fence-agents-amt-ws \\
+fence-agents-apc \\
+fence-agents-apc-snmp \\
+fence-agents-aws \\
+fence-agents-azure-arm \\
+fence-agents-bladecenter \\
+fence-agents-brocade \\
+fence-agents-cdu \\
+fence-agents-cisco-mds \\
+fence-agents-cisco-ucs \\
+fence-agents-cyberpower-ssh \\
+fence-agents-docker \\
+fence-agents-drac \\
+fence-agents-drac5 \\
+fence-agents-eaton-snmp \\
+fence-agents-ecloud \\
+fence-agents-emerson \\
+fence-agents-eps \\
+fence-agents-gce \\
+fence-agents-hds-cb \\
+fence-agents-heuristics-ping \\
+fence-agents-hpblade \\
+fence-agents-ibmblade \\
+fence-agents-ibmz \\
+fence-agents-ibm-powervs \\
+fence-agents-ibm-vpc \\
+fence-agents-ifmib \\
+fence-agents-ilo-moonshot \\
+fence-agents-ilo-mp \\
+fence-agents-ilo-ssh \\
+fence-agents-ilo2 \\
+fence-agents-intelmodular \\
+fence-agents-ipdu \\
+fence-agents-ipmilan \\
+fence-agents-kdump \\
+fence-agents-ldom \\
+fence-agents-lpar \\
+fence-agents-mpath \\
+fence-agents-netio \\
+fence-agents-ovh \\
+fence-agents-redfish \\
+fence-agents-rhevm \\
+fence-agents-rsa \\
+fence-agents-rsb \\
+fence-agents-sanbox2 \\
+fence-agents-sbd \\
+fence-agents-scsi \\
+fence-agents-vbox \\
+fence-virt \\
+fence-agents-vmware \\
+fence-agents-vmware-rest \\
+fence-agents-vmware-soap \\
+fence-agents-vmware-vcloud \\
+fence-agents-wti \\
+fence-agents-xenapi \\
+fence-agents-zvm \\
+
+EOF)
+
+%ifarch x86_64 ppc64le
+%global allfenceagents %(cat <<EOF
+%{allfenceagents} \\
+fence-agents-compute \\
+fence-agents-ironic \\
+fence-agents-openstack
+
+EOF)
+%endif
+
+%if ! %{defined rhel7_s390x}
+%global allfenceagents %(cat <<EOF
+%{allfenceagents} \\
+fence-agents-aws \\
+fence-agents-gce
+
+EOF)
+%endif
+
+# Build dependencies
+## general
+BuildRequires: autoconf automake libtool make
+## compiled code (-kdump)
+BuildRequires: gcc
+## man pages generating
+BuildRequires: libxslt
+## Python dependencies
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+BuildRequires: python3-devel
+BuildRequires: python3-httplib2 python3-pexpect python3-pycurl python3-requests
+%if 0%{?suse_version} > 1500
+BuildRequires: python3-suds-community
+%else
+BuildRequires: python3-suds
+%endif
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7
+BuildRequires: openwsman-python3
+%if ! %{defined rhel9_ppc64le_s390x}
+BuildRequires: python3-boto3
+%endif
+%endif
+%if 0%{?suse_version}
+BuildRequires: python3-openwsman python3-boto3
+%endif
+%else
+BuildRequires: python-devel
+BuildRequires: pexpect python-pycurl python-requests
+BuildRequires: python-suds openwsman-python
+%if ! %{defined rhel7_s390x}
+BuildRequires: python-boto3 python-httplib2
+%endif
+# (-openstack)
+%ifarch x86_64 ppc64le
+BuildRequires: python-novaclient python-keystoneclient
+%endif
+%endif
+
+# fence-virt
+%if 0%{?suse_version}
+%define nss_devel mozilla-nss-devel
+%define nspr_devel mozilla-nspr-devel
+%define systemd_units systemd
+%else
+%define nss_devel nss-devel
+%define nspr_devel nspr-devel
+%define systemd_units systemd-units
+%endif
+
+BuildRequires: corosynclib-devel libvirt-devel
+BuildRequires: libxml2-devel %{nss_devel} %{nspr_devel}
+BuildRequires: flex bison libuuid-devel
+BuildRequires: %{systemd_units}
+
+
+# turn off the brp-python-bytecompile script
+# (for F28+ or equivalent, the latter is the preferred form)
+%global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompilespace:.*$!!g')
+#undefine __brp_python_bytecompile
+
+%prep
+%setup -q -n %{name}-%{version}%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}
+%autopatch -p1
+# prevent compilation of something that won't get used anyway
+sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac
+
+%build
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+ export PYTHON="%{__python3}"
+%endif
+
+./autogen.sh
+%{configure} \
+%if %{defined _tmpfilesdir}
+ SYSTEMD_TMPFILES_DIR=%{_tmpfilesdir} \
+ --with-fencetmpdir=/run/fence-agents
+%endif
+
+CFLAGS="$(echo '%{optflags}')" make %{_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+make install DESTDIR=%{buildroot}
+mkdir -p %{buildroot}/%{_unitdir}/
+install -m 0644 agents/virt/fence_virtd.service %{buildroot}/%{_unitdir}/
+# bytecompile Python source code in a non-standard location
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7
+%py_byte_compile %{__python3} %{buildroot}%{_datadir}/fence
+%endif
+# XXX unsure if /usr/sbin/fence_* should be compiled as well
+
+## tree fix up
+# fix libfence permissions
+chmod 0755 %{buildroot}%{_datadir}/fence/*.py
+# remove docs
+rm -rf %{buildroot}/usr/share/doc/fence-agents
+# remove .a files
+rm -f %{buildroot}/%{_libdir}/%{name}/*.*a
+rm -f %{buildroot}/%{_libdir}/fence-virt/*.*a
+
+%post
+ccs_update_schema > /dev/null 2>&1 ||:
+# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd
+if [ $1 -eq 1 ] ; then
+ # Initial installation
+ /bin/systemctl daemon-reload >/dev/null 2>&1 || :
+fi
+
+%preun
+# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd
+if [ $1 -eq 0 ] ; then
+ # Package removal, not upgrade
+ /bin/systemctl --no-reload disable fence_virtd.service &> /dev/null || :
+ /bin/systemctl stop fence_virtd.service &> /dev/null || :
+fi
+
+%postun
+# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd
+/bin/systemctl daemon-reload &> /dev/null || :
+if [ $1 -ge 1 ] ; then
+ # Package upgrade, not uninstall
+ /bin/systemctl try-restart fence_virtd.service &> /dev/null || :
+fi
+
+%triggerun -- fence_virtd < 0.3.0-1
+# https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Packages_migrating_to_a_systemd_unit_file_from_a_SysV_initscript
+/usr/bin/systemd-sysv-convert --save fence_virtd &> /dev/null || :
+/sbin/chkconfig --del fence_virtd &> /dev/null || :
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+/bin/systemctl try-restart fence_virtd.service &> /dev/null || :
+
+%description
+A collection of executables to handle isolation ("fencing") of possibly
+misbehaving hosts by the means of remote power management, blocking
+network, storage, or similar. They operate through a unified interface
+(calling conventions) devised for the original Red Hat clustering solution.
+
+%package common
+License: GPLv2+ and LGPLv2+
+Summary: Common base for Fence Agents
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-pexpect python3-pycurl
+%else
+Requires: pexpect python-pycurl
+%endif
+BuildArch: noarch
+%description common
+A collection of executables to handle isolation ("fencing") of possibly
+misbehaving hosts by the means of remote power management, blocking
+network, storage, or similar.
+
+This package contains support files including the Python fencing library.
+%files common
+%doc doc/COPYING.* doc/COPYRIGHT doc/README.licence
+%{_datadir}/fence
+%exclude %{_datadir}/fence/azure_fence.*
+%exclude %{_datadir}/fence/__pycache__/azure_fence.*
+%exclude %{_datadir}/fence/XenAPI.*
+%exclude %{_datadir}/fence/__pycache__/XenAPI.*
+%{_datadir}/cluster
+%exclude %{_datadir}/cluster/fence_mpath_check*
+%exclude %{_datadir}/cluster/fence_scsi_check*
+%{_datadir}/pkgconfig/%{name}.pc
+%exclude %{_sbindir}/*
+%exclude %{_mandir}/man8/*
+%if %{defined _tmpfilesdir}
+%{_tmpfilesdir}/%{name}.conf
+%endif
+%if %{defined _tmpfilesdir}
+%dir %attr (1755, root, root) /run/%{name}
+%else
+%dir %attr (1755, root, root) %{_var}/run/%{name}
+%endif
+
+%package all
+License: GPLv2+ and LGPLv2+ and ASL 2.0
+Summary: Set of unified programs capable of host isolation ("fencing")
+Requires: %{allfenceagents}
+Provides: fence-agents = %{version}-%{release}
+Obsoletes: fence-agents < 3.1.13
+%description all
+A collection of executables to handle isolation ("fencing") of possibly
+misbehaving hosts by the means of remote power management, blocking
+network, storage, or similar.
+
+This package serves as a catch-all for all supported fence agents.
+%files all
+
+%ifarch x86_64
+%package aliyun
+License: GPLv2+ and LGPLv2+ and ASL 2.0 and BSD and MIT
+Group: System Environment/Base
+Summary: Fence agent for Alibaba Cloud (Aliyun)
+Requires: fence-agents-common >= %{version}-%{release}
+Requires: python3-jmespath >= 0.9.0
+Obsoletes: %{name} < %{version}-%{release}
+%description aliyun
+The fence-agents-aliyun package contains a fence agent for Alibaba Cloud (Aliyun) instances.
+%files aliyun
+%defattr(-,root,root,-)
+%{_sbindir}/fence_aliyun
+%{_mandir}/man8/fence_aliyun.8*
+%endif
+
+%package alom
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for SUN ALOM
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description alom
+Fence agent for SUN ALOM.
+%files alom
+%{_sbindir}/fence_alom
+%{_mandir}/man8/fence_alom.8*
+
+%package amt
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Intel AMT devices
+Requires: amtterm
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description amt
+Fence agent for AMT compatibile devices that are accessed via
+3rd party software.
+%files amt
+%{_sbindir}/fence_amt
+%{_mandir}/man8/fence_amt.8*
+
+%package amt-ws
+License: ASL 2.0
+Summary: Fence agent for Intel AMT (WS-Man) devices
+Requires: fence-agents-common = %{version}-%{release}
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7
+Requires: openwsman-python3
+%endif
+%if 0%{?suse_version}
+Requires: python3-openwsman
+%endif
+%else
+Requires: openwsman-python
+%endif
+BuildArch: noarch
+%description amt-ws
+Fence agent for AMT (WS-Man) devices.
+%files amt-ws
+%{_sbindir}/fence_amt_ws
+%{_mandir}/man8/fence_amt_ws.8*
+
+%package apc
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for APC devices
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description apc
+Fence agent for APC devices that are accessed via telnet or SSH.
+%files apc
+%{_sbindir}/fence_apc
+%{_mandir}/man8/fence_apc.8*
+
+%package apc-snmp
+License: GPLv2+ and LGPLv2+
+Summary: Fence agents for APC devices (SNMP)
+Requires: net-snmp-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description apc-snmp
+Fence agents for APC devices that are accessed via the SNMP protocol.
+%files apc-snmp
+%{_sbindir}/fence_apc_snmp
+%{_mandir}/man8/fence_apc_snmp.8*
+%{_sbindir}/fence_tripplite_snmp
+%{_mandir}/man8/fence_tripplite_snmp.8*
+
+%if ! %{defined rhel7_s390x}
+%package aws
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Amazon AWS
+Requires: fence-agents-common = %{version}-%{release}
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-boto3
+%else
+Requires: python-boto3
+%endif
+BuildArch: noarch
+Obsoletes: fence-agents < 3.1.13
+%description aws
+Fence agent for Amazon AWS instances.
+%files aws
+%{_sbindir}/fence_aws
+%{_mandir}/man8/fence_aws.8*
+%endif
+
+%package azure-arm
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Azure Resource Manager
+Requires: fence-agents-common = %{version}-%{release}
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+%if 0%{?fedora} > 34
+Requires: python3-azure-common
+Requires: python3-azure-identity
+Requires: python3-azure-mgmt-compute
+Requires: python3-azure-mgmt-network
+Requires: python3-msrestazure
+%else
+Requires: python3-azure-sdk
+%endif
+%else
+Requires: python-azure-sdk
+%endif
+BuildArch: noarch
+Obsoletes: fence-agents < 3.1.13
+%description azure-arm
+Fence agent for Azure Resource Manager instances.
+%files azure-arm
+%{_sbindir}/fence_azure_arm
+%{_datadir}/fence/azure_fence.py*
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7
+%{_datadir}/fence/__pycache__/azure_fence.*
+%endif
+%{_mandir}/man8/fence_azure_arm.8*
+
+%package bladecenter
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM BladeCenter
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description bladecenter
+Fence agent for IBM BladeCenter devices that are accessed
+via telnet or SSH.
+%files bladecenter
+%{_sbindir}/fence_bladecenter
+%{_mandir}/man8/fence_bladecenter.8*
+
+%package brocade
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Brocade switches
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description brocade
+Fence agent for Brocade devices that are accessed via telnet or SSH.
+%files brocade
+%{_sbindir}/fence_brocade
+%{_mandir}/man8/fence_brocade.8*
+
+%package cdu
+License: GPLv3-only
+Summary: Fence agent for a Sentry Switch CDU
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description cdu
+Fence agent for Sentry Switch CDU power switch.
+%files cdu
+%{_sbindir}/fence_cdu
+%{_mandir}/man8/fence_cdu.8*
+
+%package cisco-mds
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Cisco MDS 9000 series
+Requires: net-snmp-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description cisco-mds
+Fence agent for Cisco MDS 9000 series devices that are accessed
+via the SNMP protocol.
+%files cisco-mds
+%{_sbindir}/fence_cisco_mds
+%{_mandir}/man8/fence_cisco_mds.8*
+
+%package cisco-ucs
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Cisco UCS series
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-pycurl
+%else
+Requires: python-pycurl
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description cisco-ucs
+Fence agent for Cisco UCS series devices that are accessed
+via the SNMP protocol.
+%files cisco-ucs
+%{_sbindir}/fence_cisco_ucs
+%{_mandir}/man8/fence_cisco_ucs.8*
+
+%ifarch x86_64 ppc64le
+%package compute
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Nova compute nodes
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-requests
+Requires: python3-novaclient
+%else
+Requires: python-requests
+Requires: python2-novaclient
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description compute
+Fence agent for Nova compute nodes.
+%files compute
+%{_sbindir}/fence_compute
+%{_sbindir}/fence_evacuate
+%{_mandir}/man8/fence_compute.8*
+%{_mandir}/man8/fence_evacuate.8*
+%endif
+
+%package cyberpower-ssh
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for CyberPower network PDUs
+Requires: openssh-clients
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description cyberpower-ssh
+%files cyberpower-ssh
+%{_sbindir}/fence_cyberpower_ssh
+%{_mandir}/man8/fence_cyberpower_ssh.8*
+
+%package docker
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Docker
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-pycurl
+%else
+Requires: python-pycurl
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description docker
+Fence agent for Docker images that are accessed over HTTP.
+%files docker
+%{_sbindir}/fence_docker
+%{_mandir}/man8/fence_docker.8*
+
+%package drac
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Dell DRAC
+Requires: telnet
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description drac
+Fence agent for Dell DRAC IV series devices that are accessed
+via telnet.
+%files drac
+%{_sbindir}/fence_drac
+%{_mandir}/man8/fence_drac.8*
+
+%package drac5
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Dell DRAC 5
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description drac5
+Fence agent for Dell DRAC 5 series devices that are accessed
+via telnet or SSH.
+%files drac5
+%{_sbindir}/fence_drac5
+%{_mandir}/man8/fence_drac5.8*
+
+%package eaton-snmp
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Eaton network power switches
+Requires: net-snmp-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description eaton-snmp
+Fence agent for Eaton network power switches that are accessed
+via the SNMP protocol.
+%files eaton-snmp
+%{_sbindir}/fence_eaton_snmp
+%{_mandir}/man8/fence_eaton_snmp.8*
+
+%package ecloud
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for eCloud and eCloud VPC
+Requires: python3-requests
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-requests
+%else
+Requires: python-requests
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ecloud
+Fence agent for eCloud and eCloud VPC from ANS Group Limited
+%files ecloud
+%{_sbindir}/fence_ecloud
+%{_mandir}/man8/fence_ecloud.8*
+
+%package emerson
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Emerson devices (SNMP)
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description emerson
+Fence agent for Emerson devices that are accessed via
+the SNMP protocol.
+%files emerson
+%{_sbindir}/fence_emerson
+%{_mandir}/man8/fence_emerson.8*
+
+%package eps
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for ePowerSwitch 8M+ power switches
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description eps
+Fence agent for ePowerSwitch 8M+ power switches that are accessed
+via the HTTP(s) protocol.
+%files eps
+%{_sbindir}/fence_eps
+%{_mandir}/man8/fence_eps.8*
+
+%if ! %{defined rhel7_s390x}
+%package gce
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for GCE (Google Cloud Engine)
+Requires: fence-agents-common = %{version}-%{release}
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7
+Requires: python3-google-api-client
+%endif
+%if 0%{?suse_version}
+Requires: python3-google-api-python-client
+%endif
+%else
+Requires: python-google-api-client
+%endif
+BuildArch: noarch
+Obsoletes: fence-agents < 3.1.13
+%description gce
+Fence agent for GCE (Google Cloud Engine) instances.
+%files gce
+%{_sbindir}/fence_gce
+%{_mandir}/man8/fence_gce.8*
+%endif
+
+%package hds-cb
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Hitachi Compute Blade systems
+Requires: telnet
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description hds-cb
+Fence agent for Hitachi Compute Blades that are accessed via telnet.
+%files hds-cb
+%{_sbindir}/fence_hds_cb
+%{_mandir}/man8/fence_hds_cb.8*
+
+%package heuristics-ping
+License: GPLv2+ and LGPLv2+
+Summary: Pseudo fence agent to affect other agents based on ping-heuristics
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+Obsoletes: fence-agents < 3.1.13
+%description heuristics-ping
+Fence pseudo agent used to affect other agents based on
+ping-heuristics.
+%files heuristics-ping
+%{_sbindir}/fence_heuristics_ping
+%{_mandir}/man8/fence_heuristics_ping.8*
+
+%package hpblade
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for HP BladeSystem devices
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description hpblade
+Fence agent for HP BladeSystem devices that are accessed via telnet
+or SSH.
+%files hpblade
+%{_sbindir}/fence_hpblade
+%{_mandir}/man8/fence_hpblade.8*
+
+%package ibmblade
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM BladeCenter
+Requires: net-snmp-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ibmblade
+Fence agent for IBM BladeCenter devices that are accessed
+via the SNMP protocol.
+%files ibmblade
+%{_sbindir}/fence_ibmblade
+%{_mandir}/man8/fence_ibmblade.8*
+
+%package ibmz
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM z LPARs
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-requests
+%else
+Requires: python-requests
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ibmz
+Fence agent for IBM z LPARs that are accessed via the HMC
+Web Services REST API.
+%files ibmz
+%{_sbindir}/fence_ibmz
+%{_mandir}/man8/fence_ibmz.8*
+
+%package ibm-powervs
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM PowerVS
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ibm-powervs
+Fence agent for IBM PowerVS that are accessed via REST API.
+%files ibm-powervs
+%{_sbindir}/fence_ibm_powervs
+%{_mandir}/man8/fence_ibm_powervs.8*
+
+%package ibm-vpc
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM Cloud VPC
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ibm-vpc
+Fence agent for IBM Cloud VPC that are accessed via REST API.
+%files ibm-vpc
+%{_sbindir}/fence_ibm_vpc
+%{_mandir}/man8/fence_ibm_vpc.8*
+
+%package ifmib
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for devices with IF-MIB interfaces
+Requires: net-snmp-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ifmib
+Fence agent for IF-MIB interfaces that are accessed via
+the SNMP protocol.
+%files ifmib
+%{_sbindir}/fence_ifmib
+%{_mandir}/man8/fence_ifmib.8*
+
+%package ilo2
+License: GPLv2+ and LGPLv2+
+Summary: Fence agents for HP iLO2 devices
+Requires: gnutls-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ilo2
+Fence agents for HP iLO2 devices that are accessed via
+the HTTP(s) protocol.
+%files ilo2
+%{_sbindir}/fence_ilo
+%{_sbindir}/fence_ilo2
+%{_mandir}/man8/fence_ilo.8*
+%{_mandir}/man8/fence_ilo2.8*
+
+%package ilo-moonshot
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for HP iLO Moonshot devices
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ilo-moonshot
+Fence agent for HP iLO Moonshot devices that are accessed
+via telnet or SSH.
+%files ilo-moonshot
+%{_sbindir}/fence_ilo_moonshot
+%{_mandir}/man8/fence_ilo_moonshot.8*
+
+%package ilo-mp
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for HP iLO MP devices
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ilo-mp
+Fence agent for HP iLO MP devices that are accessed via telnet or SSH.
+%files ilo-mp
+%{_sbindir}/fence_ilo_mp
+%{_mandir}/man8/fence_ilo_mp.8*
+
+%package ilo-ssh
+License: GPLv2+ and LGPLv2+
+Summary: Fence agents for HP iLO devices over SSH
+Requires: openssh-clients
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ilo-ssh
+Fence agents for HP iLO devices that are accessed via telnet or SSH.
+%files ilo-ssh
+%{_sbindir}/fence_ilo_ssh
+%{_mandir}/man8/fence_ilo_ssh.8*
+%{_sbindir}/fence_ilo3_ssh
+%{_mandir}/man8/fence_ilo3_ssh.8*
+%{_sbindir}/fence_ilo4_ssh
+%{_mandir}/man8/fence_ilo4_ssh.8*
+%{_sbindir}/fence_ilo5_ssh
+%{_mandir}/man8/fence_ilo5_ssh.8*
+
+%package intelmodular
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for devices with Intel Modular interfaces
+Requires: net-snmp-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description intelmodular
+Fence agent for Intel Modular interfaces that are accessed
+via the SNMP protocol.
+%files intelmodular
+%{_sbindir}/fence_intelmodular
+%{_mandir}/man8/fence_intelmodular.8*
+
+%package ipdu
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM iPDU network power switches
+Requires: net-snmp-utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ipdu
+Fence agent for IBM iPDU network power switches that are accessed
+via the SNMP protocol.
+%files ipdu
+%{_sbindir}/fence_ipdu
+%{_mandir}/man8/fence_ipdu.8*
+
+%package ipmilan
+License: GPLv2+ and LGPLv2+
+Summary: Fence agents for devices with IPMI interface
+Requires: /usr/bin/ipmitool
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ipmilan
+Fence agents for devices with IPMI interface.
+%files ipmilan
+%{_sbindir}/fence_ipmilan
+%{_mandir}/man8/fence_ipmilan.8*
+%{_sbindir}/fence_idrac
+%{_mandir}/man8/fence_idrac.8*
+%{_sbindir}/fence_ilo3
+%{_mandir}/man8/fence_ilo3.8*
+%{_sbindir}/fence_ilo4
+%{_mandir}/man8/fence_ilo4.8*
+%{_sbindir}/fence_ilo5
+%{_mandir}/man8/fence_ilo5.8*
+%{_sbindir}/fence_ipmilanplus
+%{_mandir}/man8/fence_ipmilanplus.8*
+%{_sbindir}/fence_imm
+%{_mandir}/man8/fence_imm.8*
+
+%ifarch x86_64 ppc64le
+%package ironic
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for OpenStack's Ironic (Bare Metal as a service)
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ironic
+Fence agent for OpenStack's Ironic (Bare Metal as a service) service.
+%files ironic
+%{_sbindir}/fence_ironic
+%{_mandir}/man8/fence_ironic.8*
+%endif
+
+%package kdump
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for use with kdump crash recovery service
+Requires: fence-agents-common = %{version}-%{release}
+# this cannot be noarch since it's compiled
+%description kdump
+Fence agent for use with kdump crash recovery service.
+%files kdump
+%{_sbindir}/fence_kdump
+%{_libexecdir}/fence_kdump_send
+%{_mandir}/man8/fence_kdump.8*
+%{_mandir}/man8/fence_kdump_send.8*
+
+%package kubevirt
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for KubeVirt platform
+Requires: python3-openshift >= 0.12.1
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description kubevirt
+Fence agent for KubeVirt platform.
+%files kubevirt
+%{_sbindir}/fence_kubevirt
+%{_mandir}/man8/fence_kubevirt.8*
+
+%package ldom
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Sun LDom virtual machines
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ldom
+Fence agent for APC devices that are accessed via telnet or SSH.
+%files ldom
+%{_sbindir}/fence_ldom
+%{_mandir}/man8/fence_ldom.8*
+
+%package lpar
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM LPAR
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description lpar
+Fence agent for IBM LPAR devices that are accessed via telnet or SSH.
+%files lpar
+%{_sbindir}/fence_lpar
+%{_mandir}/man8/fence_lpar.8*
+
+%package mpath
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for reservations over Device Mapper Multipath
+Requires: device-mapper-multipath
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description mpath
+Fence agent for SCSI persistent reservation over
+Device Mapper Multipath.
+%files mpath
+%{_sbindir}/fence_mpath
+%{_datadir}/cluster/fence_mpath_check*
+%{_mandir}/man8/fence_mpath.8*
+
+%package netio
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Koukaam NETIO devices
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description netio
+Fence agent for Koukaam NETIO devices that are accessed
+via telnet or SSH.
+%files netio
+%{_sbindir}/fence_netio
+%{_mandir}/man8/fence_netio.8*
+
+%ifarch x86_64 ppc64le
+%package openstack
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for OpenStack's Nova service
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-requests
+%else
+Requires: python-requests
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description openstack
+Fence agent for OpenStack's Nova service.
+%files openstack
+%{_sbindir}/fence_openstack
+%{_mandir}/man8/fence_openstack.8*
+%endif
+
+%package ovh
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for OVH provider
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+%if 0%{?suse_version} > 1500
+Requires: python3-suds-community
+%else
+Requires: python3-suds
+%endif
+%else
+Requires: python-suds
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description ovh
+Fence agent for OVH hosting provider.
+%files ovh
+%{_sbindir}/fence_ovh
+%{_mandir}/man8/fence_ovh.8*
+
+# skipped from allfenceagents
+%package pve
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for PVE
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-pycurl
+%else
+Requires: python-pycurl
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description pve
+Fence agent for PVE.
+%files pve
+%{_sbindir}/fence_pve
+%{_mandir}/man8/fence_pve.8*
+
+# skipped from allfenceagents
+%package raritan
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Raritan Dominion PX
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description raritan
+Fence agent for Raritan Dominion PX.
+%files raritan
+%{_sbindir}/fence_raritan
+%{_mandir}/man8/fence_raritan.8*
+
+# skipped from allfenceagents
+%package rcd-serial
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for RCD serial
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description rcd-serial
+Fence agent for RCD serial.
+%files rcd-serial
+%{_sbindir}/fence_rcd_serial
+%{_mandir}/man8/fence_rcd_serial.8*
+
+%package redfish
+License: GPLv2+ and LGPLv2+
+Group: System Environment/Base
+Summary: Fence agent for Redfish
+Requires: fence-agents-common >= %{version}-%{release}
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-requests
+%else
+Requires: python-requests
+%endif
+Obsoletes: fence-agents < 3.1.13
+%description redfish
+The fence-agents-redfish package contains a fence agent for Redfish
+%files redfish
+%defattr(-,root,root,-)
+%{_sbindir}/fence_redfish
+%{_mandir}/man8/fence_redfish.8*
+
+%package rhevm
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for RHEV-M
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description rhevm
+Fence agent for RHEV-M via REST API.
+%files rhevm
+%{_sbindir}/fence_rhevm
+%{_mandir}/man8/fence_rhevm.8*
+
+%package rsa
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM RSA II
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description rsa
+Fence agent for IBM RSA II devices that are accessed
+via telnet or SSH.
+%files rsa
+%{_sbindir}/fence_rsa
+%{_mandir}/man8/fence_rsa.8*
+
+%package rsb
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Fujitsu RSB
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description rsb
+Fence agent for Fujitsu RSB devices that are accessed
+via telnet or SSH.
+%files rsb
+%{_sbindir}/fence_rsb
+%{_mandir}/man8/fence_rsb.8*
+
+%package sanbox2
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for QLogic SANBox2 FC switches
+Requires: telnet
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description sanbox2
+Fence agent for QLogic SANBox2 switches that are accessed via telnet.
+%files sanbox2
+%{_sbindir}/fence_sanbox2
+%{_mandir}/man8/fence_sanbox2.8*
+
+%package sbd
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for SBD (storage-based death)
+Requires: sbd
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description sbd
+Fence agent for SBD (storage-based death).
+%files sbd
+%{_sbindir}/fence_sbd
+%{_mandir}/man8/fence_sbd.8*
+
+%package scsi
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for SCSI persistent reservations
+Requires: sg3_utils
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description scsi
+Fence agent for SCSI persistent reservations.
+%files scsi
+%{_sbindir}/fence_scsi
+%{_datadir}/cluster/fence_scsi_check
+%{_datadir}/cluster/fence_scsi_check_hardreboot
+%{_mandir}/man8/fence_scsi.8*
+
+%package vbox
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for VirtualBox
+Requires: openssh-clients
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description vbox
+Fence agent for VirtualBox dom0 accessed via SSH.
+%files vbox
+%{_sbindir}/fence_vbox
+%{_mandir}/man8/fence_vbox.8*
+
+# skipped from allfenceagents
+%package virsh
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for virtual machines based on libvirt
+Requires: openssh-clients /usr/bin/virsh
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description virsh
+Fence agent for virtual machines that are accessed via SSH.
+%files virsh
+%{_sbindir}/fence_virsh
+%{_mandir}/man8/fence_virsh.8*
+
+%package vmware
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for VMWare with VI Perl Toolkit or vmrun
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-pexpect
+%else
+Requires: pexpect
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description vmware
+Fence agent for VMWare accessed with VI Perl Toolkit or vmrun.
+%files vmware
+%{_sbindir}/fence_vmware
+%{_mandir}/man8/fence_vmware.8*
+
+%package vmware-rest
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for VMWare with REST API
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+Obsoletes: fence-agents < 3.1.13
+%description vmware-rest
+Fence agent for VMWare with REST API.
+%files vmware-rest
+%{_sbindir}/fence_vmware_rest
+%{_mandir}/man8/fence_vmware_rest.8*
+
+%package vmware-soap
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for VMWare with SOAP API v4.1+
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+%if 0%{?suse_version} > 1500
+Requires: python3-suds-community
+%else
+Requires: python3-suds
+%endif
+%else
+Requires: python-suds
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description vmware-soap
+Fence agent for VMWare with SOAP API v4.1+.
+%files vmware-soap
+%{_sbindir}/fence_vmware_soap
+%{_mandir}/man8/fence_vmware_soap.8*
+
+%package vmware-vcloud
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for VMWare vCloud Director
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+Obsoletes: fence-agents < 3.1.13
+%description vmware-vcloud
+Fence agent for VMWare vCloud Director.
+%files vmware-vcloud
+%{_sbindir}/fence_vmware_vcloud
+%{_mandir}/man8/fence_vmware_vcloud.8*
+
+%package wti
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for WTI Network power switches
+Requires: openssh-clients
+%if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version}
+%if (0%{?rhel} && 0%{?rhel} < 8) || (0%{?centos} && 0%{?centos} < 8)
+Requires: telnet
+%else
+Recommends: telnet
+%endif
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description wti
+Fence agent for WTI network power switches that are accessed
+via telnet or SSH.
+%files wti
+%{_sbindir}/fence_wti
+%{_mandir}/man8/fence_wti.8*
+
+%package xenapi
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for Citrix XenServer over XenAPI
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7 || 0%{?suse_version}
+Requires: python3-pexpect
+%else
+Requires: pexpect
+%endif
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description xenapi
+Fence agent for Citrix XenServer accessed over XenAPI.
+%files xenapi
+%{_sbindir}/fence_xenapi
+%{_datadir}/fence/XenAPI.py*
+%if 0%{?fedora} || 0%{?centos} > 7 || 0%{?rhel} > 7
+%{_datadir}/fence/__pycache__/XenAPI.*
+%endif
+%{_mandir}/man8/fence_xenapi.8*
+
+%package zvm
+License: GPLv2+ and LGPLv2+
+Summary: Fence agent for IBM z/VM over IP
+Requires: fence-agents-common = %{version}-%{release}
+BuildArch: noarch
+%description zvm
+Fence agent for IBM z/VM over IP.
+%files zvm
+%{_sbindir}/fence_zvmip
+%{_mandir}/man8/fence_zvmip.8*
+
+# fence-virt
+
+%package -n fence-virt
+Summary: A pluggable fencing framework for virtual machines
+Requires(post): systemd-sysv %{systemd_units}
+Requires(preun): %{systemd_units}
+Requires(postun): %{systemd_units}
+%description -n fence-virt
+Fencing agent for virtual machines.
+%files -n fence-virt
+%doc agents/virt/docs/*
+%{_sbindir}/fence_virt
+%{_sbindir}/fence_xvm
+%{_mandir}/man8/fence_virt.*
+%{_mandir}/man8/fence_xvm.*
+
+%package -n fence-virtd
+Summary: Daemon which handles requests from fence-virt
+%description -n fence-virtd
+This package provides the host server framework, fence_virtd,
+for fence_virt. The fence_virtd host daemon is resposible for
+processing fencing requests from virtual machines and routing
+the requests to the appropriate physical machine for action.
+%files -n fence-virtd
+%{_sbindir}/fence_virtd
+%{_unitdir}/fence_virtd.service
+%config(noreplace) %{_sysconfdir}/fence_virt.conf
+%dir %{_libdir}/fence-virt
+%{_libdir}/fence-virt/vsock.so
+%{_mandir}/man5/fence_virt.conf.*
+%{_mandir}/man8/fence_virtd.*
+
+%package -n fence-virtd-multicast
+Summary: Multicast listener for fence-virtd
+Requires: fence-virtd
+%description -n fence-virtd-multicast
+Provides multicast listener capability for fence-virtd.
+%files -n fence-virtd-multicast
+%{_libdir}/fence-virt/multicast.so
+
+%package -n fence-virtd-serial
+Summary: Serial VMChannel listener for fence-virtd
+Requires: libvirt >= 0.6.2
+Requires: fence-virtd
+%description -n fence-virtd-serial
+Provides serial VMChannel listener capability for fence-virtd.
+%files -n fence-virtd-serial
+%{_libdir}/fence-virt/serial.so
+
+%package -n fence-virtd-tcp
+Summary: TCP listener for fence-virtd
+Requires: fence-virtd
+%description -n fence-virtd-tcp
+Provides TCP listener capability for fence-virtd.
+%files -n fence-virtd-tcp
+%{_libdir}/fence-virt/tcp.so
+
+%package -n fence-virtd-libvirt
+Summary: Libvirt backend for fence-virtd
+Requires: libvirt >= 0.6.0
+Requires: fence-virtd
+%description -n fence-virtd-libvirt
+Provides fence_virtd with a connection to libvirt to fence
+virtual machines. Useful for running a cluster of virtual
+machines on a desktop.
+%files -n fence-virtd-libvirt
+%{_libdir}/fence-virt/virt.so
+
+%package -n fence-virtd-cpg
+Summary: CPG/libvirt backend for fence-virtd
+Requires: corosynclib
+Requires: fence-virtd
+%description -n fence-virtd-cpg
+Provides fence_virtd with a connection to libvirt to fence
+virtual machines. Uses corosync CPG to keep track of VM
+locations to allow for non-local VMs to be fenced when VMs
+are located on corosync cluster nodes.
+%files -n fence-virtd-cpg
+%{_libdir}/fence-virt/cpg.so
+
+%changelog
+* @date@ Autotools generated version <nobody@nowhere.org> - @version@-@specver@-@numcomm@.@alphatag@.@dirty@
+- Autotools generated version
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..0fe7096
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,34 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+TARGET = fencing.py fencing_snmp.py azure_fence.py
+
+if BUILD_XENAPILIB
+TARGET += XenAPI.py
+endif
+
+SRC = fencing.py.py fencing_snmp.py.py XenAPI.py.py azure_fence.py.py check_used_options.py
+
+XSL = fence2man.xsl fence2rng.xsl fence2wiki.xsl
+
+FASRNG = fence.rng.head fence.rng.tail metadata.rng
+
+EXTRA_DIST = $(SRC) $(XSL) $(FASRNG)
+
+fencelibdir = ${FENCEAGENTSLIBDIR}
+
+fencelib_DATA = $(TARGET)
+
+rngdir = ${CLUSTERDATA}/relaxng
+
+rng_DATA = $(XSL) $(FASRNG)
+
+azure_fence.py: fencing.py
+fencing_snmp.py: fencing.py
+check_used_options.py: fencing.py
+
+include $(top_srcdir)/make/fencebuild.mk
+
+xml-check: all
+xml-upload: all
+
+clean-man:
diff --git a/lib/XenAPI.py.py b/lib/XenAPI.py.py
new file mode 100644
index 0000000..6fe11ef
--- /dev/null
+++ b/lib/XenAPI.py.py
@@ -0,0 +1,212 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#============================================================================
+# Copyright (C) 2006 XenSource Inc.
+#============================================================================
+#
+# Parts of this file are based upon xmlrpclib.py, the XML-RPC client
+# interface included in the Python distribution.
+#
+# Copyright (c) 1999-2002 by Secret Labs AB
+# Copyright (c) 1999-2002 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+import sys
+import gettext
+import socket
+import logging
+
+if sys.version_info[0] > 2:
+ import xmlrpc.client as xmlrpclib
+ import http.client as httplib
+else:
+ import xmlrpclib
+ import httplib
+
+translation = gettext.translation('xen-xm', fallback=True)
+
+class Failure(Exception):
+ def __init__(self, details):
+ try:
+ # If this failure is MESSAGE_PARAMETER_COUNT_MISMATCH, then we
+ # correct the return values here, to account for the fact that we
+ # transparently add the session handle as the first argument.
+ if details[0] == 'MESSAGE_PARAMETER_COUNT_MISMATCH':
+ details[2] = str(int(details[2]) - 1)
+ details[3] = str(int(details[3]) - 1)
+
+ self.details = details
+ except Exception as exn:
+ self.details = ['INTERNAL_ERROR', 'Client-side: ' + str(exn)]
+
+ def __str__(self):
+ try:
+ return translation.ugettext(self.details[0]) % self._details_map()
+ except TypeError as exn:
+ return "Message database broken: %s.\nXen-API failure: %s" % \
+ (exn, str(self.details))
+ except Exception as exn:
+ logging.error("%s\n", str(exn))
+ return "Xen-API failure: %s" % str(self.details)
+
+ def _details_map(self):
+ return dict([(str(i), self.details[i])
+ for i in range(len(self.details))])
+
+
+_RECONNECT_AND_RETRY = (lambda _: ())
+
+class UDSHTTPConnection(httplib.HTTPConnection):
+ """ Stupid hacked up HTTPConnection subclass to allow HTTP over Unix domain
+ sockets. """
+ def connect(self):
+ path = self.host.replace("_", "/")
+ self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.sock.connect(path)
+
+class UDSTransport(xmlrpclib.Transport):
+ def make_connection(self, host):
+ return httplib.HTTPConnection(host)
+
+class Session(xmlrpclib.ServerProxy):
+ """A server proxy and session manager for communicating with Xend using
+ the Xen-API.
+
+ Example:
+
+ session = Session('http://localhost:9363/')
+ session.login_with_password('me', 'mypassword')
+ session.xenapi.VM.start(vm_uuid)
+ session.xenapi.session.logout()
+
+ For now, this class also supports the legacy XML-RPC API, using
+ session.xend.domain('Domain-0') and similar. This support will disappear
+ once there is a working Xen-API replacement for every call in the legacy
+ API.
+ """
+
+ def __init__(self, uri, transport=None, encoding=None, verbose=0,
+ allow_none=1):
+ xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding,
+ verbose, allow_none)
+ self._session = None
+ self.last_login_method = None
+ self.last_login_params = None
+
+
+ def xenapi_request(self, methodname, params):
+ if methodname.startswith('login'):
+ self._login(methodname, params)
+ return None
+ else:
+ retry_count = 0
+ while retry_count < 3:
+ full_params = (self._session,) + params
+ result = _parse_result(getattr(self, methodname)(*full_params))
+ if result == _RECONNECT_AND_RETRY:
+ retry_count += 1
+ if self.last_login_method:
+ self._login(self.last_login_method,
+ self.last_login_params)
+ else:
+ raise xmlrpclib.Fault(401, 'You must log in')
+ else:
+ return result
+ raise xmlrpclib.Fault(
+ 500, 'Tried 3 times to get a valid session, but failed')
+
+
+ def _login(self, method, params):
+ result = _parse_result(getattr(self, 'session.%s' % method)(*params))
+ if result == _RECONNECT_AND_RETRY:
+ raise xmlrpclib.Fault(
+ 500, 'Received SESSION_INVALID when logging in')
+ self._session = result
+ self.last_login_method = method
+ self.last_login_params = params
+
+
+ def __getattr__(self, name):
+ if name == 'xenapi':
+ return _Dispatcher(self.xenapi_request, None)
+ elif name.startswith('login'):
+ return lambda *params: self._login(name, params)
+ else:
+ return xmlrpclib.ServerProxy.__getattr__(self, name)
+
+def xapi_local():
+ return Session("http://_var_xapi_xapi/", transport=UDSTransport())
+
+def _parse_result(result):
+ if type(result) != dict or 'Status' not in result:
+ raise xmlrpclib.Fault(500, 'Missing Status in response from server' + result)
+ if result['Status'] == 'Success':
+ if 'Value' in result:
+ return result['Value']
+ else:
+ raise xmlrpclib.Fault(500,
+ 'Missing Value in response from server')
+ else:
+ if 'ErrorDescription' in result:
+ if result['ErrorDescription'][0] == 'SESSION_INVALID':
+ return _RECONNECT_AND_RETRY
+ else:
+ raise Failure(result['ErrorDescription'])
+ else:
+ raise xmlrpclib.Fault(
+ 500, 'Missing ErrorDescription in response from server')
+
+
+# Based upon _Method from xmlrpclib.
+class _Dispatcher:
+ def __init__(self, send, name):
+ self.__send = send
+ self.__name = name
+
+ def __repr__(self):
+ if self.__name:
+ return '<XenAPI._Dispatcher for %s>' % self.__name
+ else:
+ return '<XenAPI._Dispatcher>'
+
+ def __getattr__(self, name):
+ if self.__name is None:
+ return _Dispatcher(self.__send, name)
+ else:
+ return _Dispatcher(self.__send, "%s.%s" % (self.__name, name))
+
+ def __call__(self, *args):
+ return self.__send(self.__name, args)
diff --git a/lib/azure_fence.py.py b/lib/azure_fence.py.py
new file mode 100644
index 0000000..5ca71eb
--- /dev/null
+++ b/lib/azure_fence.py.py
@@ -0,0 +1,393 @@
+import logging, re, time
+from fencing import fail_usage
+
+FENCE_SUBNET_NAME = "fence-subnet"
+FENCE_INBOUND_RULE_NAME = "FENCE_DENY_ALL_INBOUND"
+FENCE_INBOUND_RULE_DIRECTION = "Inbound"
+FENCE_OUTBOUND_RULE_NAME = "FENCE_DENY_ALL_OUTBOUND"
+FENCE_OUTBOUND_RULE_DIRECTION = "Outbound"
+FENCE_STATE_OFF = "off"
+FENCE_STATE_ON = "on"
+FENCE_TAG_SUBNET_ID = "FENCE_TAG_SUBNET_ID"
+FENCE_TAG_IP_TYPE = "FENCE_TAG_IP_TYPE"
+FENCE_TAG_IP = "FENCE_TAG_IP"
+IP_TYPE_DYNAMIC = "Dynamic"
+MAX_RETRY = 10
+RETRY_WAIT = 5
+
+class AzureSubResource:
+ Type = None
+ Name = None
+
+class AzureResource:
+ Id = None
+ SubscriptionId = None
+ ResourceGroupName = None
+ ResourceName = None
+ SubResources = []
+
+class AzureConfiguration:
+ RGName = None
+ VMName = None
+ SubscriptionId = None
+ Cloud = None
+ UseMSI = None
+ Tenantid = None
+ ApplicationId = None
+ ApplicationKey = None
+ Verbose = None
+
+def get_from_metadata(parameter):
+ import requests
+ try:
+ r = requests.get('http://169.254.169.254/metadata/instance?api-version=2017-08-01', headers = {"Metadata":"true"})
+ logging.debug("metadata: " + str(r.json()))
+ return str(r.json()["compute"][parameter])
+ except:
+ logging.warning("Not able to use metadata service. Am I running in Azure?")
+
+ return None
+
+def get_azure_resource(id):
+ match = re.match('(/subscriptions/([^/]*)/resourceGroups/([^/]*))(/providers/([^/]*/[^/]*)/([^/]*))?((/([^/]*)/([^/]*))*)', id)
+ if not match:
+ fail_usage("{get_azure_resource} cannot parse resource id %s" % id)
+
+ logging.debug("{get_azure_resource} found %s matches for %s" % (len(match.groups()), id))
+ iGroup = 0
+ while iGroup < len(match.groups()):
+ logging.debug("{get_azure_resource} group %s: %s" %(iGroup, match.group(iGroup)))
+ iGroup += 1
+
+ resource = AzureResource()
+ resource.Id = id
+ resource.SubscriptionId = match.group(2)
+ resource.SubResources = []
+
+ if len(match.groups()) > 3:
+ resource.ResourceGroupName = match.group(3)
+ logging.debug("{get_azure_resource} resource group %s" % resource.ResourceGroupName)
+
+ if len(match.groups()) > 6:
+ resource.ResourceName = match.group(6)
+ logging.debug("{get_azure_resource} resource name %s" % resource.ResourceName)
+
+ if len(match.groups()) > 7 and match.group(7):
+ splits = match.group(7).split("/")
+ logging.debug("{get_azure_resource} splitting subtypes '%s' (%s)" % (match.group(7), len(splits)))
+ i = 1 # the string starts with / so the first split is empty
+ while i < len(splits) - 1:
+ logging.debug("{get_azure_resource} creating subresource with type %s and name %s" % (splits[i], splits[i+1]))
+ subRes = AzureSubResource()
+ subRes.Type = splits[i]
+ subRes.Name = splits[i+1]
+ resource.SubResources.append(subRes)
+ i += 2
+
+ return resource
+
+def get_fence_subnet_for_config(ipConfig, network_client):
+ subnetResource = get_azure_resource(ipConfig.subnet.id)
+ logging.debug("{get_fence_subnet_for_config} testing virtual network %s in resource group %s for a fence subnet" %(subnetResource.ResourceName, subnetResource.ResourceGroupName))
+ vnet = network_client.virtual_networks.get(subnetResource.ResourceGroupName, subnetResource.ResourceName)
+ return get_subnet(vnet, FENCE_SUBNET_NAME)
+
+def get_subnet(vnet, subnetName):
+ for avSubnet in vnet.subnets:
+ logging.debug("{get_subnet} searching subnet %s testing subnet %s" % (subnetName, avSubnet.name))
+ if (avSubnet.name.lower() == subnetName.lower()):
+ logging.debug("{get_subnet} subnet found %s" % avSubnet)
+ return avSubnet
+
+def test_fence_subnet(fenceSubnet, nic, network_client):
+ logging.info("{test_fence_subnet}")
+ testOk = True
+ if not fenceSubnet:
+ testOk = False
+ logging.info("{test_fence_subnet} No fence subnet found for virtual network of network interface %s" % nic.id)
+ else:
+ if not fenceSubnet.network_security_group:
+ testOk = False
+ logging.info("{test_fence_subnet} Fence subnet %s has not network security group" % fenceSubnet.id)
+ else:
+ nsgResource = get_azure_resource(fenceSubnet.network_security_group.id)
+ logging.info("{test_fence_subnet} Getting network security group %s in resource group %s" % (nsgResource.ResourceName, nsgResource.ResourceGroupName))
+ nsg = network_client.network_security_groups.get(nsgResource.ResourceGroupName, nsgResource.ResourceName)
+ inboundRule = get_inbound_rule_for_nsg(nsg)
+ outboundRule = get_outbound_rule_for_nsg(nsg)
+ if not outboundRule:
+ testOk = False
+ logging.info("{test_fence_subnet} Network Securiy Group %s of fence subnet %s has no outbound security rule that blocks all traffic" % (nsgResource.ResourceName, fenceSubnet.id))
+ elif not inboundRule:
+ testOk = False
+ logging.info("{test_fence_subnet} Network Securiy Group %s of fence subnet %s has no inbound security rule that blocks all traffic" % (nsgResource.ResourceName, fenceSubnet.id))
+
+ return testOk
+
+def get_inbound_rule_for_nsg(nsg):
+ return get_rule_for_nsg(nsg, FENCE_INBOUND_RULE_NAME, FENCE_INBOUND_RULE_DIRECTION)
+
+def get_outbound_rule_for_nsg(nsg):
+ return get_rule_for_nsg(nsg, FENCE_OUTBOUND_RULE_NAME, FENCE_OUTBOUND_RULE_DIRECTION)
+
+def get_rule_for_nsg(nsg, ruleName, direction):
+ logging.info("{get_rule_for_nsg} Looking for security rule %s with direction %s" % (ruleName, direction))
+ if not nsg:
+ logging.info("{get_rule_for_nsg} Network security group not set")
+ return None
+
+ for rule in nsg.security_rules:
+ logging.info("{get_rule_for_nsg} Testing a %s securiy rule %s" % (rule.direction, rule.name))
+ if (rule.access == "Deny") and (rule.direction == direction) \
+ and (rule.source_port_range == "*") and (rule.destination_port_range == "*") \
+ and (rule.protocol == "*") and (rule.destination_address_prefix == "*") \
+ and (rule.source_address_prefix == "*") and (rule.provisioning_state == "Succeeded") \
+ and (rule.priority == 100) and (rule.name == ruleName):
+ logging.info("{get_rule_for_nsg} %s rule found" % direction)
+ return rule
+
+ return None
+
+def get_network_state(compute_client, network_client, rgName, vmName):
+ result = FENCE_STATE_ON
+
+ try:
+ vm = compute_client.virtual_machines.get(rgName, vmName, "instanceView")
+
+ allNICOK = True
+ for nicRef in vm.network_profile.network_interfaces:
+ nicresource = get_azure_resource(nicRef.id)
+ nic = network_client.network_interfaces.get(nicresource.ResourceGroupName, nicresource.ResourceName)
+ for ipConfig in nic.ip_configurations:
+ logging.info("{get_network_state} Testing ip configuration %s" % ipConfig.name)
+ fenceSubnet = get_fence_subnet_for_config(ipConfig, network_client)
+ testOk = test_fence_subnet(fenceSubnet, nic, network_client)
+ if not testOk:
+ allNICOK = False
+ elif fenceSubnet.id.lower() != ipConfig.subnet.id.lower():
+ logging.info("{get_network_state} IP configuration %s is not in fence subnet (ip subnet: %s, fence subnet: %s)" % (ipConfig.name, ipConfig.subnet.id.lower(), fenceSubnet.id.lower()))
+ allNICOK = False
+ if allNICOK:
+ logging.info("{get_network_state} All IP configurations of all network interfaces are in the fence subnet. Declaring VM as off")
+ result = FENCE_STATE_OFF
+ except Exception as e:
+ fail_usage("{get_network_state} Failed: %s" % e)
+
+ return result
+
+def set_network_state(compute_client, network_client, rgName, vmName, operation):
+ import msrestazure.azure_exceptions
+ logging.info("{set_network_state} Setting state %s for %s in resource group %s" % (operation, vmName, rgName))
+
+ vm = compute_client.virtual_machines.get(rgName, vmName, "instanceView")
+
+ operations = []
+ for nicRef in vm.network_profile.network_interfaces:
+ for attempt in range(0, MAX_RETRY):
+ try:
+ nicresource = get_azure_resource(nicRef.id)
+ nic = network_client.network_interfaces.get(nicresource.ResourceGroupName, nicresource.ResourceName)
+
+ if not nic.tags and operation == "block":
+ nic.tags = {}
+
+ logging.info("{set_network_state} Searching for tags required to unfence this virtual machine")
+ for ipConfig in nic.ip_configurations:
+ if operation == "block":
+ fenceSubnet = get_fence_subnet_for_config(ipConfig, network_client)
+ testOk = test_fence_subnet(fenceSubnet, nic, network_client)
+ if testOk:
+ logging.info("{set_network_state} Changing subnet of ip config of nic %s" % nic.id)
+ nic.tags[("%s_%s" % (FENCE_TAG_SUBNET_ID, ipConfig.name))] = ipConfig.subnet.id
+ nic.tags[("%s_%s" % (FENCE_TAG_IP_TYPE, ipConfig.name))] = ipConfig.private_ip_allocation_method
+ nic.tags[("%s_%s" % (FENCE_TAG_IP, ipConfig.name))] = ipConfig.private_ip_address
+ ipConfig.subnet = fenceSubnet
+ ipConfig.private_ip_allocation_method = IP_TYPE_DYNAMIC
+ else:
+ fail_usage("{set_network_state} Network interface id %s does not have a network security group." % nic.id)
+ elif operation == "unblock":
+ if not nic.tags:
+ fail_usage("{set_network_state} IP configuration %s is missing the required resource tags (empty)" % ipConfig.name)
+
+ subnetId = nic.tags.pop("%s_%s" % (FENCE_TAG_SUBNET_ID, ipConfig.name))
+ ipType = nic.tags.pop("%s_%s" % (FENCE_TAG_IP_TYPE, ipConfig.name))
+ ipAddress = nic.tags.pop("%s_%s" % (FENCE_TAG_IP, ipConfig.name))
+
+ if (subnetId and ipType and (ipAddress or (ipType.lower() == IP_TYPE_DYNAMIC.lower()))):
+ logging.info("{set_network_state} tags found (subnetId: %s, ipType: %s, ipAddress: %s)" % (subnetId, ipType, ipAddress))
+
+ subnetResource = get_azure_resource(subnetId)
+ vnet = network_client.virtual_networks.get(subnetResource.ResourceGroupName, subnetResource.ResourceName)
+ logging.info("{set_network_state} looking for subnet %s" % len(subnetResource.SubResources))
+ oldSubnet = get_subnet(vnet, subnetResource.SubResources[0].Name)
+ if not oldSubnet:
+ fail_usage("{set_network_state} subnet %s not found" % subnetId)
+
+ ipConfig.subnet = oldSubnet
+ ipConfig.private_ip_allocation_method = ipType
+ if ipAddress:
+ ipConfig.private_ip_address = ipAddress
+ else:
+ fail_usage("{set_network_state} IP configuration %s is missing the required resource tags(subnetId: %s, ipType: %s, ipAddress: %s)" % (ipConfig.name, subnetId, ipType, ipAddress))
+
+ logging.info("{set_network_state} updating nic %s" % (nic.id))
+ op = network_client.network_interfaces.create_or_update(nicresource.ResourceGroupName, nicresource.ResourceName, nic)
+ operations.append(op)
+ break
+ except msrestazure.azure_exceptions.CloudError as cex:
+ logging.error("{set_network_state} CloudError in attempt %s '%s'" % (attempt, cex))
+ if cex.error and cex.error.error and cex.error.error.lower() == "PrivateIPAddressIsBeingCleanedUp":
+ logging.error("{set_network_state} PrivateIPAddressIsBeingCleanedUp")
+ time.sleep(RETRY_WAIT)
+
+ except Exception as ex:
+ logging.error("{set_network_state} Exception of type %s: %s" % (type(ex).__name__, ex))
+ break
+
+def get_azure_config(options):
+ config = AzureConfiguration()
+
+ config.RGName = options.get("--resourceGroup")
+ config.VMName = options.get("--plug")
+ config.SubscriptionId = options.get("--subscriptionId")
+ config.Cloud = options.get("--cloud")
+ config.UseMSI = "--msi" in options
+ config.Tenantid = options.get("--tenantId")
+ config.ApplicationId = options.get("--username")
+ config.ApplicationKey = options.get("--password")
+ config.Verbose = options.get("--verbose")
+
+ if not config.RGName:
+ logging.info("resourceGroup not provided. Using metadata service")
+ config.RGName = get_from_metadata("resourceGroupName")
+
+ if not config.SubscriptionId:
+ logging.info("subscriptionId not provided. Using metadata service")
+ config.SubscriptionId = get_from_metadata("subscriptionId")
+
+ return config
+
+def get_azure_cloud_environment(config):
+ cloud_environment = None
+ if config.Cloud:
+ if (config.Cloud.lower() == "china"):
+ from msrestazure.azure_cloud import AZURE_CHINA_CLOUD
+ cloud_environment = AZURE_CHINA_CLOUD
+ elif (config.Cloud.lower() == "germany"):
+ from msrestazure.azure_cloud import AZURE_GERMAN_CLOUD
+ cloud_environment = AZURE_GERMAN_CLOUD
+ elif (config.Cloud.lower() == "usgov"):
+ from msrestazure.azure_cloud import AZURE_US_GOV_CLOUD
+ cloud_environment = AZURE_US_GOV_CLOUD
+
+ return cloud_environment
+
+def get_azure_credentials(config):
+ credentials = None
+ cloud_environment = get_azure_cloud_environment(config)
+ if config.UseMSI and cloud_environment:
+ try:
+ from azure.identity import ManagedIdentityCredential
+ credentials = ManagedIdentityCredential(cloud_environment=cloud_environment)
+ except ImportError:
+ from msrestazure.azure_active_directory import MSIAuthentication
+ credentials = MSIAuthentication(cloud_environment=cloud_environment)
+ elif config.UseMSI:
+ try:
+ from azure.identity import ManagedIdentityCredential
+ credentials = ManagedIdentityCredential()
+ except ImportError:
+ from msrestazure.azure_active_directory import MSIAuthentication
+ credentials = MSIAuthentication()
+ elif cloud_environment:
+ try:
+ # try to use new libraries ClientSecretCredential (azure.identity, based on azure.core)
+ from azure.identity import ClientSecretCredential
+ credentials = ClientSecretCredential(
+ client_id = config.ApplicationId,
+ client_secret = config.ApplicationKey,
+ tenant_id = config.Tenantid,
+ cloud_environment=cloud_environment
+ )
+ except ImportError:
+ # use old libraries ServicePrincipalCredentials (azure.common) if new one is not available
+ from azure.common.credentials import ServicePrincipalCredentials
+ credentials = ServicePrincipalCredentials(
+ client_id = config.ApplicationId,
+ secret = config.ApplicationKey,
+ tenant = config.Tenantid,
+ cloud_environment=cloud_environment
+ )
+ else:
+ try:
+ # try to use new libraries ClientSecretCredential (azure.identity, based on azure.core)
+ from azure.identity import ClientSecretCredential
+ credentials = ClientSecretCredential(
+ client_id = config.ApplicationId,
+ client_secret = config.ApplicationKey,
+ tenant_id = config.Tenantid
+ )
+ except ImportError:
+ # use old libraries ServicePrincipalCredentials (azure.common) if new one is not available
+ from azure.common.credentials import ServicePrincipalCredentials
+ credentials = ServicePrincipalCredentials(
+ client_id = config.ApplicationId,
+ secret = config.ApplicationKey,
+ tenant = config.Tenantid
+ )
+
+ return credentials
+
+def get_azure_compute_client(config):
+ from azure.mgmt.compute import ComputeManagementClient
+
+ cloud_environment = get_azure_cloud_environment(config)
+ credentials = get_azure_credentials(config)
+
+ if cloud_environment:
+ try:
+ compute_client = ComputeManagementClient(
+ credentials,
+ config.SubscriptionId,
+ base_url=cloud_environment.endpoints.resource_manager,
+ credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"]
+ )
+ except TypeError:
+ compute_client = ComputeManagementClient(
+ credentials,
+ config.SubscriptionId,
+ base_url=cloud_environment.endpoints.resource_manager
+ )
+ else:
+ compute_client = ComputeManagementClient(
+ credentials,
+ config.SubscriptionId
+ )
+ return compute_client
+
+def get_azure_network_client(config):
+ from azure.mgmt.network import NetworkManagementClient
+
+ cloud_environment = get_azure_cloud_environment(config)
+ credentials = get_azure_credentials(config)
+
+ if cloud_environment:
+ try:
+ network_client = NetworkManagementClient(
+ credentials,
+ config.SubscriptionId,
+ base_url=cloud_environment.endpoints.resource_manager,
+ credential_scopes=[cloud_environment.endpoints.resource_manager + "/.default"]
+ )
+ except TypeError:
+ network_client = NetworkManagementClient(
+ credentials,
+ config.SubscriptionId,
+ base_url=cloud_environment.endpoints.resource_manager
+ )
+ else:
+ network_client = NetworkManagementClient(
+ credentials,
+ config.SubscriptionId
+ )
+ return network_client
diff --git a/lib/check_used_options.py b/lib/check_used_options.py
new file mode 100644
index 0000000..ad4a387
--- /dev/null
+++ b/lib/check_used_options.py
@@ -0,0 +1,68 @@
+## Check if fence agent uses only options["--??"] which are defined in fencing library or
+## fence agent itself
+##
+## Usage: ./check_used_options.py fence-agent (e.g. lpar/fence_lpar.py)
+##
+
+import sys, re
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import all_opt
+
+def main():
+ agent = sys.argv[1]
+
+ available = {}
+
+ ## all_opt from fencing library are imported
+ for k in list(all_opt.keys()):
+ if "longopt" in all_opt[k]:
+ available["--" + all_opt[k]["longopt"]] = True
+
+ ## add UUID which is derived automatically from --plug if possible
+ available["--uuid"] = True
+
+ ## all_opt defined in fence agent are found
+ agent_file = open(agent)
+ opt_re = re.compile(r"\s*all_opt\[\"([^\"]*)\"\] = {")
+ opt_longopt_re = re.compile(r"\"longopt\"\s*:\s*\"([^\"]*)\"")
+
+ in_opt = False
+ for line in agent_file:
+ if opt_re.search(line) != None:
+ in_opt = True
+ if in_opt and opt_longopt_re.search(line) != None:
+ available["--" + opt_longopt_re.search(line).group(1)] = True
+ in_opt = False
+
+ ## check if all options are defined
+ agent_file = open(agent)
+ option_use_re = re.compile(r"options\[\"(-[^\"]*)\"\]")
+ option_in_re = re.compile(r"\"(-[^\"]*)\" in options")
+ option_has_re = re.compile(r"options.has_key\(\"(-[^\"]*)\"\)")
+
+ counter = 0
+ without_errors = True
+ for line in agent_file:
+ counter += 1
+
+ for option in option_use_re.findall(line):
+ if option not in available:
+ print("ERROR on line %d in %s: option %s is not defined" % (counter, agent, option_use_re.search(line).group(1)))
+ without_errors = False
+
+ for option in option_in_re.findall(line):
+ if option not in available:
+ print("ERROR on line %d in %s: option %s is not defined" % (counter, agent, option_has_re.search(line).group(1)))
+ without_errors = False
+
+ for option in option_has_re.findall(line):
+ print("ERROR on line %d in %s: option %s: has_key() not supported in Python 3" % (counter, agent, option_has_re.search(line).group(1)))
+ without_errors = False
+
+ if without_errors:
+ sys.exit(0)
+ else:
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/fence.rng.head b/lib/fence.rng.head
new file mode 100644
index 0000000..22f4452
--- /dev/null
+++ b/lib/fence.rng.head
@@ -0,0 +1,7 @@
+<!-- Autogenerated fence definitions -->
+ <define name="FENCEDEVICEOPTIONS">
+ <optional>
+ <choice>
+ <!-- begin specific fence devices -->
+
+ <!-- begin auto-generated device definitions -->
diff --git a/lib/fence.rng.tail b/lib/fence.rng.tail
new file mode 100644
index 0000000..2feab91
--- /dev/null
+++ b/lib/fence.rng.tail
@@ -0,0 +1,13 @@
+ <!-- end auto-generated device definitions -->
+
+ <group>
+ <optional>
+ <empty/>
+ </optional>
+ </group>
+
+ <!-- end specific fence devices -->
+ </choice>
+ </optional>
+ </define>
+<!-- end fence attribute group definitions -->
diff --git a/lib/fence2man.xsl b/lib/fence2man.xsl
new file mode 100644
index 0000000..3dc0b39
--- /dev/null
+++ b/lib/fence2man.xsl
@@ -0,0 +1,78 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text" indent="no"/>
+<xsl:template match="parameter">
+<xsl:param name="show" />
+<xsl:if test="not(@deprecated)">
+.TP
+<xsl:if test="$show = 'getopt'">.B <xsl:value-of select="getopt/@mixed" /></xsl:if>
+<xsl:if test="$show = 'stdin'">.B <xsl:value-of select="@name"/></xsl:if>
+.
+<xsl:value-of select="normalize-space(shortdesc)"/>
+<xsl:if test="count(content/option) > 1">
+ <xsl:text> (</xsl:text>
+ <xsl:for-each select="content/option">
+ <xsl:value-of select="@value" />
+ <xsl:if test="position() &lt; last()">
+ <xsl:text>|</xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+</xsl:if>
+<xsl:if test="not(content/@default)"><xsl:if test="@required = 1"> This parameter is always required.</xsl:if></xsl:if>
+<xsl:if test="content/@default"> (Default Value: <xsl:value-of select="content/@default"/>)</xsl:if>
+<xsl:if test="$show = 'stdin'">
+<xsl:if test="@obsoletes"> Obsoletes: <xsl:value-of select="@obsoletes" /></xsl:if>
+</xsl:if>
+
+</xsl:if>
+</xsl:template>
+
+<xsl:template match="action">
+.TP
+\fB<xsl:value-of select="@name"/> \fP
+<xsl:choose>
+<xsl:when test="@name = 'on'">Power on machine.</xsl:when>
+<xsl:when test="@name = 'off'">Power off machine.</xsl:when>
+<xsl:when test="@name = 'enable'">Enable fabric access.</xsl:when>
+<xsl:when test="@name = 'disable'">Disable fabric access.</xsl:when>
+<xsl:when test="@name = 'reboot'">Reboot machine.</xsl:when>
+<xsl:when test="@name = 'diag'">Pulse a diagnostic interrupt to the processor(s).</xsl:when>
+<xsl:when test="@name = 'monitor'">Check the health of fence device</xsl:when>
+<xsl:when test="@name = 'metadata'">Display the XML metadata describing this resource.</xsl:when>
+<xsl:when test="@name = 'list'">List available plugs with aliases/virtual machines if there is support for more then one device. Returns N/A otherwise.</xsl:when>
+<xsl:when test="@name = 'list-status'">List available plugs with aliases/virtual machines and their power state if it can be obtained without additional commands.</xsl:when>
+<xsl:when test="@name = 'status'">This returns the status of the plug/virtual machine.</xsl:when>
+<xsl:when test="@name = 'validate-all'">Validate if all required parameters are entered.</xsl:when>
+<!-- Ehhh -->
+<xsl:otherwise> The operational behavior of this is not known.</xsl:otherwise>
+</xsl:choose>
+</xsl:template>
+
+<xsl:template match="/resource-agent">
+.TH FENCE_AGENT 8 2009-10-20 "<xsl:value-of select="@name"/> (Fence Agent)"
+.SH NAME
+<xsl:value-of select="@name" /> - <xsl:value-of select="@shortdesc" />
+<xsl:for-each select="symlink">
+.P
+<xsl:value-of select="@name" /> - <xsl:value-of select="@shortdesc" /> (symlink)
+</xsl:for-each>
+.SH DESCRIPTION
+.P
+<xsl:value-of select="longdesc"/>
+.P
+<xsl:value-of select="@name" /> accepts options on the command line as well
+as from stdin. Fenced sends parameters through stdin when it execs the
+agent. <xsl:value-of select="@name" /> can be run by itself with command
+line options. This is useful for testing and for turning outlets on or off
+from scripts.
+<xsl:if test="vendor-url">
+Vendor URL: <xsl:value-of select="vendor-url" />
+</xsl:if>
+.SH PARAMETERS
+<xsl:apply-templates select="parameters"><xsl:with-param name="show">getopt</xsl:with-param></xsl:apply-templates>
+.SH ACTIONS
+<xsl:apply-templates select="actions"/>
+.SH STDIN PARAMETERS
+<xsl:apply-templates select="parameters"><xsl:with-param name="show">stdin</xsl:with-param></xsl:apply-templates>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/lib/fence2rng.xsl b/lib/fence2rng.xsl
new file mode 100644
index 0000000..f6d465e
--- /dev/null
+++ b/lib/fence2rng.xsl
@@ -0,0 +1,184 @@
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="text" indent="no"/>
+
+<xsl:param name="init-indent" select="' '"/>
+<xsl:param name="indent" select="' '"/>
+
+
+<!--
+ helpers
+ -->
+
+<xsl:variable name="SP" select="' '"/>
+<xsl:variable name="NL" select="'&#xA;'"/>
+<xsl:variable name="Q" select="'&quot;'"/>
+<xsl:variable name="TS" select="'&lt;'"/>
+<xsl:variable name="TSc" select="'&lt;/'"/>
+<xsl:variable name="TE" select="'&gt;'"/>
+<xsl:variable name="TEc" select="'/&gt;'"/>
+
+<xsl:template name="comment">
+ <xsl:param name="text" select="''"/>
+ <xsl:param name="indent" select="''"/>
+ <xsl:if test="$indent != 'none'">
+ <xsl:value-of select="concat($init-indent, $indent)"/>
+ </xsl:if>
+ <xsl:value-of select="concat($TS, '!-- ', $text, ' --',$TE)"/>
+</xsl:template>
+
+<xsl:template name="tag-start">
+ <xsl:param name="name"/>
+ <xsl:param name="attrs" select="''"/>
+ <xsl:param name="indent" select="''"/>
+ <xsl:if test="$indent != 'none'">
+ <xsl:value-of select="concat($init-indent, $indent)"/>
+ </xsl:if>
+ <xsl:value-of select="concat($TS, $name)"/>
+ <xsl:if test="$attrs != ''">
+ <xsl:value-of select="concat($SP, $attrs)"/>
+ </xsl:if>
+ <xsl:value-of select="$TE"/>
+</xsl:template>
+
+<xsl:template name="tag-end">
+ <xsl:param name="name"/>
+ <xsl:param name="attrs" select="''"/>
+ <xsl:param name="indent" select="''"/>
+ <xsl:if test="$indent != 'none'">
+ <xsl:value-of select="concat($init-indent, $indent)"/>
+ </xsl:if>
+ <xsl:value-of select="concat($TSc, $name)"/>
+ <xsl:if test="$attrs != ''">
+ <xsl:value-of select="concat($SP, $attrs)"/>
+ </xsl:if>
+ <xsl:value-of select="$TE"/>
+</xsl:template>
+
+<xsl:template name="tag-self">
+ <xsl:param name="name"/>
+ <xsl:param name="attrs" select="''"/>
+ <xsl:param name="indent" select="''"/>
+ <xsl:if test="$indent != 'none'">
+ <xsl:value-of select="concat($init-indent, $indent)"/>
+ </xsl:if>
+ <xsl:value-of select="concat($TS, $name)"/>
+ <xsl:if test="$attrs != ''">
+ <xsl:value-of select="concat($SP, $attrs)"/>
+ </xsl:if>
+ <xsl:value-of select="$TEc"/>
+</xsl:template>
+
+
+<!--
+ proceed
+ -->
+
+<xsl:template match="/resource-agent">
+ <xsl:value-of select="$NL"/>
+
+ <!-- (comment denoting the fence agent name) -->
+ <xsl:call-template name="comment">
+ <xsl:with-param name="text" select="@name"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <!-- group rha:name=... rha:description=... (start) -->
+ <xsl:call-template name="tag-start">
+ <xsl:with-param name="name" select="'group'"/>
+ <xsl:with-param name="attrs" select="concat(
+ 'rha:name=', $Q, @name, $Q, $SP,
+ 'rha:description=', $Q, @shortdesc, $Q)"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <!-- optional (start) -->
+ <xsl:call-template name="tag-start">
+ <xsl:with-param name="name" select="'optional'"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <!-- attribute name="option" -->
+ <xsl:call-template name="tag-self">
+ <xsl:with-param name="name" select="'attribute'"/>
+ <xsl:with-param name="attrs" select="concat(
+ 'name=', $Q, 'option', $Q)"/>
+ <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+ </xsl:call-template>
+ <xsl:value-of select="$SP"/>
+ <!-- (comment mentioning that "option" is deprecated) -->
+ <xsl:call-template name="comment">
+ <xsl:with-param name="text">
+ <xsl:text>deprecated; for compatibility. use "action"</xsl:text>
+ </xsl:with-param>
+ <xsl:with-param name="indent" select="'none'"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <!-- optional (end) -->
+ <xsl:call-template name="tag-end">
+ <xsl:with-param name="name" select="'optional'"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <xsl:for-each select="parameters/parameter">
+ <xsl:variable name="escapeddesc">
+ <xsl:call-template name="escape_quot">
+ <xsl:with-param name="replace" select="shortdesc"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- optional (start) -->
+ <xsl:call-template name="tag-start">
+ <xsl:with-param name="name" select="'optional'"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <!-- attribute name=... rha:description=... -->
+ <xsl:call-template name="tag-self">
+ <xsl:with-param name="name" select="'attribute'"/>
+ <xsl:with-param name="attrs" select="concat(
+ 'name=', $Q, @name, $Q, $SP,
+ 'rha:description=', $Q, normalize-space($escapeddesc), $Q, $SP)"/>
+ <xsl:with-param name="indent" select="concat($indent, $indent)"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <!-- optional (end) -->
+ <xsl:call-template name="tag-end">
+ <xsl:with-param name="name" select="'optional'"/>
+ <xsl:with-param name="indent" select="$indent"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+ </xsl:for-each>
+
+ <!-- group rha:name=... rha:description=... (end) -->
+ <xsl:call-template name="tag-end">
+ <xsl:with-param name="name" select="'group'"/>
+ </xsl:call-template>
+ <xsl:value-of select="$NL"/>
+
+ <xsl:value-of select="$NL"/>
+</xsl:template>
+
+<xsl:template name="escape_quot">
+ <xsl:param name="replace"/>
+ <xsl:choose>
+ <xsl:when test="contains($replace,'&quot;')">
+ <xsl:value-of select="substring-before($replace,'&quot;')"/>
+ <!-- escape quot-->
+ <xsl:text>&amp;quot;</xsl:text>
+ <xsl:call-template name="escape_quot">
+ <xsl:with-param name="replace" select="substring-after($replace,'&quot;')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$replace"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/lib/fence2wiki.xsl b/lib/fence2wiki.xsl
new file mode 100644
index 0000000..8112169
--- /dev/null
+++ b/lib/fence2wiki.xsl
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version='1.0' xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:template match="/resource-agent">
+[=#<xsl:value-of select="@name" />]
+||='''<xsl:value-of select="@shortdesc" />''' =||='''<xsl:value-of select="@name" />''' =||
+|| '''Name Of The Argument For STDIN''' || '''Name Of The Argument For Command-Line''' || '''Default Value''' ||'''Description''' ||
+<xsl:apply-templates select="parameters/parameter" />
+</xsl:template>
+
+<xsl:template match="parameters/parameter">|| <xsl:value-of select="@name" /> || <xsl:value-of select="getopt/@mixed" /> || {{{<xsl:value-of select="content/@default" disable-output-escaping="yes"/>}}} || <xsl:value-of select="shortdesc" /> ||
+</xsl:template>
+
+</xsl:stylesheet> \ No newline at end of file
diff --git a/lib/fencing.py.py b/lib/fencing.py.py
new file mode 100644
index 0000000..c5b5e94
--- /dev/null
+++ b/lib/fencing.py.py
@@ -0,0 +1,1748 @@
+#!@PYTHON@ -tt
+
+import sys, getopt, time, os, uuid, pycurl, stat
+import pexpect, re, syslog
+import logging
+import subprocess
+import threading
+import shlex
+import socket
+import textwrap
+import __main__
+
+import itertools
+
+RELEASE_VERSION = "@RELEASE_VERSION@"
+
+__all__ = ['atexit_handler', 'check_input', 'process_input', 'all_opt', 'show_docs',
+ 'fence_login', 'fence_action', 'fence_logout']
+
+EC_OK = 0
+EC_GENERIC_ERROR = 1
+EC_BAD_ARGS = 2
+EC_LOGIN_DENIED = 3
+EC_CONNECTION_LOST = 4
+EC_TIMED_OUT = 5
+EC_WAITING_ON = 6
+EC_WAITING_OFF = 7
+EC_STATUS = 8
+EC_STATUS_HMC = 9
+EC_PASSWORD_MISSING = 10
+EC_INVALID_PRIVILEGES = 11
+EC_FETCH_VM_UUID = 12
+
+LOG_FORMAT = "%(asctime)-15s %(levelname)s: %(message)s"
+
+all_opt = {
+ "help" : {
+ "getopt" : "h",
+ "longopt" : "help",
+ "help" : "-h, --help Display this help and exit",
+ "required" : "0",
+ "shortdesc" : "Display help and exit",
+ "order" : 55},
+ "version" : {
+ "getopt" : "V",
+ "longopt" : "version",
+ "help" : "-V, --version Display version information and exit",
+ "required" : "0",
+ "shortdesc" : "Display version information and exit",
+ "order" : 54},
+ "verbose" : {
+ "getopt" : "v",
+ "longopt" : "verbose",
+ "help" : "-v, --verbose Verbose mode. "
+ "Multiple -v flags can be stacked on the command line "
+ "(e.g., -vvv) to increase verbosity.",
+ "required" : "0",
+ "order" : 51},
+ "verbose_level" : {
+ "getopt" : ":",
+ "longopt" : "verbose-level",
+ "type" : "integer",
+ "help" : "--verbose-level "
+ "Level of debugging detail in output. Defaults to the "
+ "number of --verbose flags specified on the command "
+ "line, or to 1 if verbose=1 in a stonith device "
+ "configuration (i.e., on stdin).",
+ "required" : "0",
+ "order" : 52},
+ "debug" : {
+ "getopt" : "D:",
+ "longopt" : "debug-file",
+ "help" : "-D, --debug-file=[debugfile] Debugging to output file",
+ "required" : "0",
+ "shortdesc" : "Write debug information to given file",
+ "order" : 53},
+ "delay" : {
+ "getopt" : ":",
+ "longopt" : "delay",
+ "type" : "second",
+ "help" : "--delay=[seconds] Wait X seconds before fencing is started",
+ "required" : "0",
+ "default" : "0",
+ "order" : 200},
+ "agent" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "web" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "force_on" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "action" : {
+ "getopt" : "o:",
+ "longopt" : "action",
+ "help" : "-o, --action=[action] Action: status, reboot (default), off or on",
+ "required" : "1",
+ "shortdesc" : "Fencing action",
+ "default" : "reboot",
+ "order" : 1},
+ "fabric_fencing" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "ipaddr" : {
+ "getopt" : "a:",
+ "longopt" : "ip",
+ "help" : "-a, --ip=[ip] IP address or hostname of fencing device",
+ "required" : "1",
+ "order" : 1},
+ "ipport" : {
+ "getopt" : "u:",
+ "longopt" : "ipport",
+ "type" : "integer",
+ "help" : "-u, --ipport=[port] TCP/UDP port to use for connection",
+ "required" : "0",
+ "shortdesc" : "TCP/UDP port to use for connection with device",
+ "order" : 1},
+ "login" : {
+ "getopt" : "l:",
+ "longopt" : "username",
+ "help" : "-l, --username=[name] Login name",
+ "required" : "?",
+ "order" : 1},
+ "no_login" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_password" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_port" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_status" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_on" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "no_off" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "telnet" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "diag" : {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "passwd" : {
+ "getopt" : "p:",
+ "longopt" : "password",
+ "help" : "-p, --password=[password] Login password or passphrase",
+ "required" : "0",
+ "order" : 1},
+ "passwd_script" : {
+ "getopt" : "S:",
+ "longopt" : "password-script",
+ "help" : "-S, --password-script=[script] Script to run to retrieve password",
+ "required" : "0",
+ "order" : 1},
+ "identity_file" : {
+ "getopt" : "k:",
+ "longopt" : "identity-file",
+ "help" : "-k, --identity-file=[filename] Identity file (private key) for SSH",
+ "required" : "0",
+ "order" : 1},
+ "cmd_prompt" : {
+ "getopt" : "c:",
+ "longopt" : "command-prompt",
+ "help" : "-c, --command-prompt=[prompt] Force Python regex for command prompt",
+ "required" : "0",
+ "order" : 1},
+ "secure" : {
+ "getopt" : "x",
+ "longopt" : "ssh",
+ "help" : "-x, --ssh Use SSH connection",
+ "required" : "0",
+ "order" : 1},
+ "ssh_options" : {
+ "getopt" : ":",
+ "longopt" : "ssh-options",
+ "help" : "--ssh-options=[options] SSH options to use",
+ "required" : "0",
+ "order" : 1},
+ "ssl" : {
+ "getopt" : "z",
+ "longopt" : "ssl",
+ "help" : "-z, --ssl Use SSL connection with verifying certificate",
+ "required" : "0",
+ "order" : 1},
+ "ssl_insecure" : {
+ "getopt" : "",
+ "longopt" : "ssl-insecure",
+ "help" : "--ssl-insecure Use SSL connection without verifying certificate",
+ "required" : "0",
+ "order" : 1},
+ "ssl_secure" : {
+ "getopt" : "",
+ "longopt" : "ssl-secure",
+ "help" : "--ssl-secure Use SSL connection with verifying certificate",
+ "required" : "0",
+ "order" : 1},
+ "notls" : {
+ "getopt" : "t",
+ "longopt" : "notls",
+ "help" : "-t, --notls "
+ "Disable TLS negotiation and force SSL3.0. "
+ "This should only be used for devices that do not support TLS1.0 and up.",
+ "required" : "0",
+ "order" : 1},
+ "tls1.0" : {
+ "getopt" : "",
+ "longopt" : "tls1.0",
+ "help" : "--tls1.0 "
+ "Disable TLS negotiation and force TLS1.0. "
+ "This should only be used for devices that do not support TLS1.1 and up.",
+ "required" : "0",
+ "order" : 1},
+ "port" : {
+ "getopt" : "n:",
+ "longopt" : "plug",
+ "help" : "-n, --plug=[id] "
+ "Physical plug number on device, UUID or identification of machine",
+ "required" : "1",
+ "order" : 1},
+ "switch" : {
+ "getopt" : "s:",
+ "longopt" : "switch",
+ "help" : "-s, --switch=[id] Physical switch number on device",
+ "required" : "0",
+ "order" : 1},
+ "exec" : {
+ "getopt" : "e:",
+ "longopt" : "exec",
+ "help" : "-e, --exec=[command] Command to execute",
+ "required" : "0",
+ "order" : 1},
+ "vmware_type" : {
+ "getopt" : "d:",
+ "longopt" : "vmware_type",
+ "help" : "-d, --vmware_type=[type] Type of VMware to connect",
+ "required" : "0",
+ "order" : 1},
+ "vmware_datacenter" : {
+ "getopt" : "s:",
+ "longopt" : "vmware-datacenter",
+ "help" : "-s, --vmware-datacenter=[dc] VMWare datacenter filter",
+ "required" : "0",
+ "order" : 2},
+ "snmp_version" : {
+ "getopt" : "d:",
+ "longopt" : "snmp-version",
+ "help" : "-d, --snmp-version=[version] Specifies SNMP version to use (1|2c|3)",
+ "required" : "0",
+ "shortdesc" : "Specifies SNMP version to use",
+ "choices" : ["1", "2c", "3"],
+ "order" : 1},
+ "community" : {
+ "getopt" : "c:",
+ "longopt" : "community",
+ "help" : "-c, --community=[community] Set the community string",
+ "required" : "0",
+ "order" : 1},
+ "snmp_auth_prot" : {
+ "getopt" : "b:",
+ "longopt" : "snmp-auth-prot",
+ "help" : "-b, --snmp-auth-prot=[prot] Set authentication protocol (MD5|SHA)",
+ "required" : "0",
+ "shortdesc" : "Set authentication protocol",
+ "choices" : ["MD5", "SHA"],
+ "order" : 1},
+ "snmp_sec_level" : {
+ "getopt" : "E:",
+ "longopt" : "snmp-sec-level",
+ "help" : "-E, --snmp-sec-level=[level] "
+ "Set security level (noAuthNoPriv|authNoPriv|authPriv)",
+ "required" : "0",
+ "shortdesc" : "Set security level",
+ "choices" : ["noAuthNoPriv", "authNoPriv", "authPriv"],
+ "order" : 1},
+ "snmp_priv_prot" : {
+ "getopt" : "B:",
+ "longopt" : "snmp-priv-prot",
+ "help" : "-B, --snmp-priv-prot=[prot] Set privacy protocol (DES|AES)",
+ "required" : "0",
+ "shortdesc" : "Set privacy protocol",
+ "choices" : ["DES", "AES"],
+ "order" : 1},
+ "snmp_priv_passwd" : {
+ "getopt" : "P:",
+ "longopt" : "snmp-priv-passwd",
+ "help" : "-P, --snmp-priv-passwd=[pass] Set privacy protocol password",
+ "required" : "0",
+ "order" : 1},
+ "snmp_priv_passwd_script" : {
+ "getopt" : "R:",
+ "longopt" : "snmp-priv-passwd-script",
+ "help" : "-R, --snmp-priv-passwd-script Script to run to retrieve privacy password",
+ "required" : "0",
+ "order" : 1},
+ "inet4_only" : {
+ "getopt" : "4",
+ "longopt" : "inet4-only",
+ "help" : "-4, --inet4-only Forces agent to use IPv4 addresses only",
+ "required" : "0",
+ "order" : 1},
+ "inet6_only" : {
+ "getopt" : "6",
+ "longopt" : "inet6-only",
+ "help" : "-6, --inet6-only Forces agent to use IPv6 addresses only",
+ "required" : "0",
+ "order" : 1},
+ "plug_separator" : {
+ "getopt" : ":",
+ "longopt" : "plug-separator",
+ "help" : "--plug-separator=[char] Separator for plug parameter when specifying more than 1 plug",
+ "default" : ",",
+ "required" : "0",
+ "order" : 100},
+ "separator" : {
+ "getopt" : "C:",
+ "longopt" : "separator",
+ "help" : "-C, --separator=[char] Separator for CSV created by 'list' operation",
+ "default" : ",",
+ "required" : "0",
+ "order" : 100},
+ "login_timeout" : {
+ "getopt" : ":",
+ "longopt" : "login-timeout",
+ "type" : "second",
+ "help" : "--login-timeout=[seconds] Wait X seconds for cmd prompt after login",
+ "default" : "5",
+ "required" : "0",
+ "order" : 200},
+ "shell_timeout" : {
+ "getopt" : ":",
+ "longopt" : "shell-timeout",
+ "type" : "second",
+ "help" : "--shell-timeout=[seconds] Wait X seconds for cmd prompt after issuing command",
+ "default" : "3",
+ "required" : "0",
+ "order" : 200},
+ "power_timeout" : {
+ "getopt" : ":",
+ "longopt" : "power-timeout",
+ "type" : "second",
+ "help" : "--power-timeout=[seconds] Test X seconds for status change after ON/OFF",
+ "default" : "20",
+ "required" : "0",
+ "order" : 200},
+ "disable_timeout" : {
+ "getopt" : ":",
+ "longopt" : "disable-timeout",
+ "help" : "--disable-timeout=[true/false] Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)",
+ "required" : "0",
+ "order" : 200},
+ "power_wait" : {
+ "getopt" : ":",
+ "longopt" : "power-wait",
+ "type" : "second",
+ "help" : "--power-wait=[seconds] Wait X seconds after issuing ON/OFF",
+ "default" : "0",
+ "required" : "0",
+ "order" : 200},
+ "stonith_status_sleep" : {
+ "getopt" : ":",
+ "longopt" : "stonith-status-sleep",
+ "type" : "second",
+ "help" : "--stonith-status-sleep=[seconds] Sleep X seconds between status calls during a STONITH action",
+ "default" : "1",
+ "required" : "0",
+ "order" : 200},
+ "missing_as_off" : {
+ "getopt" : "",
+ "longopt" : "missing-as-off",
+ "help" : "--missing-as-off Missing port returns OFF instead of failure",
+ "required" : "0",
+ "order" : 200},
+ "retry_on" : {
+ "getopt" : ":",
+ "longopt" : "retry-on",
+ "type" : "integer",
+ "help" : "--retry-on=[attempts] Count of attempts to retry power on",
+ "default" : "1",
+ "required" : "0",
+ "order" : 201},
+ "session_url" : {
+ "getopt" : "s:",
+ "longopt" : "session-url",
+ "help" : "-s, --session-url URL to connect to XenServer on",
+ "required" : "1",
+ "order" : 1},
+ "sudo" : {
+ "getopt" : "",
+ "longopt" : "use-sudo",
+ "help" : "--use-sudo Use sudo (without password) when calling 3rd party software",
+ "required" : "0",
+ "order" : 205},
+ "method" : {
+ "getopt" : "m:",
+ "longopt" : "method",
+ "help" : "-m, --method=[method] Method to fence (onoff|cycle) (Default: onoff)",
+ "required" : "0",
+ "shortdesc" : "Method to fence",
+ "default" : "onoff",
+ "choices" : ["onoff", "cycle"],
+ "order" : 1},
+ "telnet_path" : {
+ "getopt" : ":",
+ "longopt" : "telnet-path",
+ "help" : "--telnet-path=[path] Path to telnet binary",
+ "required" : "0",
+ "default" : "@TELNET_PATH@",
+ "order": 300},
+ "ssh_path" : {
+ "getopt" : ":",
+ "longopt" : "ssh-path",
+ "help" : "--ssh-path=[path] Path to ssh binary",
+ "required" : "0",
+ "default" : "@SSH_PATH@",
+ "order": 300},
+ "gnutlscli_path" : {
+ "getopt" : ":",
+ "longopt" : "gnutlscli-path",
+ "help" : "--gnutlscli-path=[path] Path to gnutls-cli binary",
+ "required" : "0",
+ "default" : "@GNUTLSCLI_PATH@",
+ "order": 300},
+ "sudo_path" : {
+ "getopt" : ":",
+ "longopt" : "sudo-path",
+ "help" : "--sudo-path=[path] Path to sudo binary",
+ "required" : "0",
+ "default" : "@SUDO_PATH@",
+ "order": 300},
+ "snmpwalk_path" : {
+ "getopt" : ":",
+ "longopt" : "snmpwalk-path",
+ "help" : "--snmpwalk-path=[path] Path to snmpwalk binary",
+ "required" : "0",
+ "default" : "@SNMPWALK_PATH@",
+ "order" : 300},
+ "snmpset_path" : {
+ "getopt" : ":",
+ "longopt" : "snmpset-path",
+ "help" : "--snmpset-path=[path] Path to snmpset binary",
+ "required" : "0",
+ "default" : "@SNMPSET_PATH@",
+ "order" : 300},
+ "snmpget_path" : {
+ "getopt" : ":",
+ "longopt" : "snmpget-path",
+ "help" : "--snmpget-path=[path] Path to snmpget binary",
+ "required" : "0",
+ "default" : "@SNMPGET_PATH@",
+ "order" : 300},
+ "snmp": {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "port_as_ip": {
+ "getopt" : "",
+ "longopt" : "port-as-ip",
+ "help" : "--port-as-ip Make \"port/plug\" to be an alias to IP address",
+ "required" : "0",
+ "order" : 200},
+ "on_target": {
+ "getopt" : "",
+ "help" : "",
+ "order" : 1},
+ "quiet": {
+ "getopt" : "q",
+ "longopt": "quiet",
+ "help" : "-q, --quiet Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.",
+ "required" : "0",
+ "order" : 50}
+}
+
+# options which are added automatically if 'key' is encountered ("default" is always added)
+DEPENDENCY_OPT = {
+ "default" : ["help", "debug", "verbose", "verbose_level",
+ "version", "action", "agent", "power_timeout",
+ "shell_timeout", "login_timeout", "disable_timeout",
+ "power_wait", "stonith_status_sleep", "retry_on", "delay",
+ "plug_separator", "quiet"],
+ "passwd" : ["passwd_script"],
+ "sudo" : ["sudo_path"],
+ "secure" : ["identity_file", "ssh_options", "ssh_path", "inet4_only", "inet6_only"],
+ "telnet" : ["telnet_path"],
+ "ipaddr" : ["ipport"],
+ "port" : ["separator"],
+ "ssl" : ["ssl_secure", "ssl_insecure", "gnutlscli_path"],
+ "snmp" : ["snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", \
+ "snmp_priv_passwd", "snmp_priv_passwd_script", "community", \
+ "snmpset_path", "snmpget_path", "snmpwalk_path"]
+ }
+
+class fspawn(pexpect.spawn):
+ def __init__(self, options, command, **kwargs):
+ if sys.version_info[0] > 2:
+ kwargs.setdefault('encoding', 'utf-8')
+ logging.info("Running command: %s", command)
+ pexpect.spawn.__init__(self, command, **kwargs)
+ self.opt = options
+
+ def log_expect(self, pattern, timeout):
+ result = self.expect(pattern, timeout if timeout != 0 else None)
+ logging.debug("Received: %s", self.before + self.after)
+ return result
+
+ def read_nonblocking(self, size, timeout):
+ return pexpect.spawn.read_nonblocking(self, size=100, timeout=timeout if timeout != 0 else None)
+
+ def send(self, message):
+ logging.debug("Sent: %s", message)
+ return pexpect.spawn.send(self, message)
+
+ # send EOL according to what was detected in login process (telnet)
+ def send_eol(self, message):
+ return self.send(message + self.opt["eol"])
+
+def frun(command, timeout=30, withexitstatus=False, events=None,
+ extra_args=None, logfile=None, cwd=None, env=None, **kwargs):
+ if sys.version_info[0] > 2:
+ kwargs.setdefault('encoding', 'utf-8')
+ return pexpect.run(command, timeout=timeout if timeout != 0 else None,
+ withexitstatus=withexitstatus, events=events,
+ extra_args=extra_args, logfile=logfile, cwd=cwd,
+ env=env, **kwargs)
+
+def atexit_handler():
+ try:
+ sys.stdout.close()
+ os.close(1)
+ except IOError:
+ logging.error("%s failed to close standard output\n", sys.argv[0])
+ sys.exit(EC_GENERIC_ERROR)
+
+def _add_dependency_options(options):
+ ## Add also options which are available for every fence agent
+ added_opt = []
+ for opt in options + ["default"]:
+ if opt in DEPENDENCY_OPT:
+ added_opt.extend([y for y in DEPENDENCY_OPT[opt] if options.count(y) == 0])
+
+ if not "port" in (options + added_opt) and \
+ not "nodename" in (options + added_opt) and \
+ "ipaddr" in (options + added_opt):
+ added_opt.append("port_as_ip")
+ all_opt["port"]["help"] = "-n, --plug=[ip] IP address or hostname of fencing device " \
+ "(together with --port-as-ip)"
+
+ return added_opt
+
+def fail_usage(message="", stop=True):
+ if len(message) > 0:
+ logging.error("%s\n", message)
+ if stop:
+ logging.error("Please use '-h' for usage\n")
+ sys.exit(EC_GENERIC_ERROR)
+
+def fail(error_code, stop=True):
+ message = {
+ EC_LOGIN_DENIED : "Unable to connect/login to fencing device",
+ EC_CONNECTION_LOST : "Connection lost",
+ EC_TIMED_OUT : "Connection timed out",
+ EC_WAITING_ON : "Failed: Timed out waiting to power ON",
+ EC_WAITING_OFF : "Failed: Timed out waiting to power OFF",
+ EC_STATUS : "Failed: Unable to obtain correct plug status or plug is not available",
+ EC_STATUS_HMC : "Failed: Either unable to obtain correct plug status, "
+ "partition is not available or incorrect HMC version used",
+ EC_PASSWORD_MISSING : "Failed: You have to set login password",
+ EC_INVALID_PRIVILEGES : "Failed: The user does not have the correct privileges to do the requested action.",
+ EC_FETCH_VM_UUID : "Failed: Can not find VM UUID by its VM name given in the <plug> parameter."
+
+ }[error_code] + "\n"
+ logging.error("%s\n", message)
+ if stop:
+ sys.exit(EC_GENERIC_ERROR)
+
+def usage(avail_opt):
+ print("Usage:")
+ print("\t" + os.path.basename(sys.argv[0]) + " [options]")
+ print("Options:")
+
+ sorted_list = [(key, all_opt[key]) for key in avail_opt]
+ sorted_list.sort(key=lambda x: x[1]["order"])
+
+ for key, value in sorted_list:
+ if len(value["help"]) != 0:
+ print(" " + _join_wrap([value["help"]], first_indent=3))
+
+def metadata(options, avail_opt, docs):
+ # avail_opt has to be unique, if there are duplicities then they should be removed
+ sorted_list = [(key, all_opt[key]) for key in list(set(avail_opt)) if "longopt" in all_opt[key]]
+ # Find keys that are going to replace inconsistent names
+ mapping = dict([(opt["longopt"].replace("-", "_"), key) for (key, opt) in sorted_list if (key != opt["longopt"].replace("-", "_"))])
+ new_options = [(key, all_opt[mapping[key]]) for key in mapping]
+ sorted_list.extend(new_options)
+
+ sorted_list.sort(key=lambda x: (x[1]["order"], x[0]))
+
+ if options["--action"] == "metadata":
+ docs["longdesc"] = re.sub("\\\\f[BPIR]|\.P|\.TP|\.br\n", "", docs["longdesc"])
+
+ print("<?xml version=\"1.0\" ?>")
+ print("<resource-agent name=\"" + os.path.basename(sys.argv[0]) + \
+ "\" shortdesc=\"" + docs["shortdesc"] + "\" >")
+ for (symlink, desc) in docs.get("symlink", []):
+ print("<symlink name=\"" + symlink + "\" shortdesc=\"" + desc + "\"/>")
+ print("<longdesc>" + docs["longdesc"] + "</longdesc>")
+ print("<vendor-url>" + docs["vendorurl"] + "</vendor-url>")
+ print("<parameters>")
+ for (key, opt) in sorted_list:
+ info = ""
+ if key in all_opt:
+ if key != all_opt[key].get('longopt', key).replace("-", "_"):
+ info = "deprecated=\"1\""
+ else:
+ info = "obsoletes=\"%s\"" % (mapping.get(key))
+
+ if "help" in opt and len(opt["help"]) > 0:
+ if info != "":
+ info = " " + info
+ print("\t<parameter name=\"" + key + "\" unique=\"0\" required=\"" + opt["required"] + "\"" + info + ">")
+
+ default = ""
+ if "default" in opt:
+ default = "default=\"" + _encode_html_entities(str(opt["default"])) + "\" "
+
+ mixed = opt["help"]
+ ## split it between option and help text
+ res = re.compile(r"^(.*?--\S+)\s+", re.IGNORECASE | re.S).search(mixed)
+ if None != res:
+ mixed = res.group(1)
+ mixed = _encode_html_entities(mixed)
+
+ if not "shortdesc" in opt:
+ shortdesc = re.sub(".*\s\s+", "", opt["help"][31:])
+ else:
+ shortdesc = opt["shortdesc"]
+
+ print("\t\t<getopt mixed=\"" + mixed + "\" />")
+ if "choices" in opt:
+ print("\t\t<content type=\"select\" "+default+" >")
+ for choice in opt["choices"]:
+ print("\t\t\t<option value=\"%s\" />" % (choice))
+ print("\t\t</content>")
+ elif opt["getopt"].count(":") > 0:
+ t = opt.get("type", "string")
+ print("\t\t<content type=\"%s\" " % (t) +default+" />")
+ else:
+ print("\t\t<content type=\"boolean\" "+default+" />")
+ print("\t\t<shortdesc lang=\"en\">" + shortdesc + "</shortdesc>")
+ print("\t</parameter>")
+ print("</parameters>")
+ print("<actions>")
+
+ (available_actions, _) = _get_available_actions(avail_opt)
+
+ if "on" in available_actions:
+ available_actions.remove("on")
+ on_target = ' on_target="1"' if avail_opt.count("on_target") else ''
+ print("\t<action name=\"on\"%s automatic=\"%d\"/>" % (on_target, avail_opt.count("fabric_fencing")))
+
+ for action in available_actions:
+ print("\t<action name=\"%s\" />" % (action))
+ print("</actions>")
+ print("</resource-agent>")
+
+def process_input(avail_opt):
+ avail_opt.extend(_add_dependency_options(avail_opt))
+
+ # @todo: this should be put elsewhere?
+ os.putenv("LANG", "C")
+ os.putenv("LC_ALL", "C")
+
+ if "port_as_ip" in avail_opt:
+ avail_opt.append("port")
+
+ if len(sys.argv) > 1:
+ opt = _parse_input_cmdline(avail_opt)
+ else:
+ opt = _parse_input_stdin(avail_opt)
+
+ if "--port-as-ip" in opt and "--plug" in opt:
+ opt["--ip"] = opt["--plug"]
+
+ return opt
+
+##
+## This function checks input and answers if we want to have same answers
+## in each of the fencing agents. It looks for possible errors and run
+## password script to set a correct password
+######
+def check_input(device_opt, opt, other_conditions = False):
+ device_opt.extend(_add_dependency_options(device_opt))
+
+ options = dict(opt)
+ options["device_opt"] = device_opt
+
+ _update_metadata(options)
+ options = _set_default_values(options)
+ options["--action"] = options["--action"].lower()
+
+ ## In special cases (show help, metadata or version) we don't need to check anything
+ #####
+ # OCF compatibility
+ if options["--action"] == "meta-data":
+ options["--action"] = "metadata"
+
+ if options["--action"] in ["metadata", "manpage"] or any(k in options for k in ("--help", "--version")):
+ return options
+
+ try:
+ options["--verbose-level"] = int(options["--verbose-level"])
+ except ValueError:
+ options["--verbose-level"] = -1
+
+ if options["--verbose-level"] < 0:
+ logging.warning("Parse error: Option 'verbose_level' must "
+ "be an integer greater than or equal to 0. "
+ "Setting verbose_level to 0.")
+ options["--verbose-level"] = 0
+
+ if options["--verbose-level"] == 0 and "--verbose" in options:
+ logging.warning("Parse error: Ignoring option 'verbose' "
+ "because it conflicts with verbose_level=0")
+ del options["--verbose"]
+
+ if options["--verbose-level"] > 0:
+ # Ensure verbose key exists
+ options["--verbose"] = 1
+
+ if "--verbose" in options:
+ logging.getLogger().setLevel(logging.DEBUG)
+
+ formatter = logging.Formatter(LOG_FORMAT)
+
+ ## add logging to syslog
+ logging.getLogger().addHandler(SyslogLibHandler())
+ if "--quiet" not in options:
+ ## add logging to stderr
+ stderrHandler = logging.StreamHandler(sys.stderr)
+ stderrHandler.setFormatter(formatter)
+ logging.getLogger().addHandler(stderrHandler)
+
+ (acceptable_actions, _) = _get_available_actions(device_opt)
+
+ if 1 == device_opt.count("fabric_fencing"):
+ acceptable_actions.extend(["enable", "disable"])
+
+ if 0 == acceptable_actions.count(options["--action"]):
+ fail_usage("Failed: Unrecognised action '" + options["--action"] + "'")
+
+ ## Compatibility layer
+ #####
+ if options["--action"] == "enable":
+ options["--action"] = "on"
+ if options["--action"] == "disable":
+ options["--action"] = "off"
+
+
+ if options["--action"] == "validate-all" and not other_conditions:
+ if not _validate_input(options, False):
+ fail_usage("validate-all failed")
+ sys.exit(EC_OK)
+ else:
+ _validate_input(options, True)
+
+ if "--debug-file" in options:
+ try:
+ debug_file = logging.FileHandler(options["--debug-file"])
+ debug_file.setLevel(logging.DEBUG)
+ debug_file.setFormatter(formatter)
+ logging.getLogger().addHandler(debug_file)
+ except IOError:
+ logging.error("Unable to create file %s", options["--debug-file"])
+ fail_usage("Failed: Unable to create file " + options["--debug-file"])
+
+ if "--snmp-priv-passwd-script" in options:
+ options["--snmp-priv-passwd"] = os.popen(options["--snmp-priv-passwd-script"]).read().rstrip()
+
+ if "--password-script" in options:
+ options["--password"] = os.popen(options["--password-script"]).read().rstrip()
+
+ if "--ssl-secure" in options or "--ssl-insecure" in options:
+ options["--ssl"] = ""
+
+ if "--ssl" in options and "--ssl-insecure" not in options:
+ options["--ssl-secure"] = ""
+
+ if os.environ.get("PCMK_service") == "pacemaker-fenced" and "--disable-timeout" not in options:
+ options["--disable-timeout"] = "1"
+
+ if options.get("--disable-timeout", "").lower() in ["1", "yes", "on", "true"]:
+ options["--power-timeout"] = options["--shell-timeout"] = options["--login-timeout"] = 0
+
+ return options
+
+## Obtain a power status from possibly more than one plug
+## "on" is returned if at least one plug is ON
+######
+def get_multi_power_fn(connection, options, get_power_fn):
+ status = "off"
+ plugs = options["--plugs"] if "--plugs" in options else [""]
+
+ for plug in plugs:
+ try:
+ options["--uuid"] = str(uuid.UUID(plug))
+ except ValueError:
+ pass
+ except KeyError:
+ pass
+
+ options["--plug"] = plug
+ plug_status = get_power_fn(connection, options)
+ if plug_status != "off":
+ status = plug_status
+
+ return status
+
+def async_set_multi_power_fn(connection, options, set_power_fn, get_power_fn, retry_attempts):
+ plugs = options["--plugs"] if "--plugs" in options else [""]
+
+ for _ in range(retry_attempts):
+ for plug in plugs:
+ try:
+ options["--uuid"] = str(uuid.UUID(plug))
+ except ValueError:
+ pass
+ except KeyError:
+ pass
+
+ options["--plug"] = plug
+ set_power_fn(connection, options)
+ time.sleep(int(options["--power-wait"]))
+
+ for _ in itertools.count(1):
+ if get_multi_power_fn(connection, options, get_power_fn) != options["--action"]:
+ time.sleep(int(options["--stonith-status-sleep"]))
+ else:
+ return True
+
+ if int(options["--power-timeout"]) > 0 and _ >= int(options["--power-timeout"]):
+ break
+
+ return False
+
+def sync_set_multi_power_fn(connection, options, sync_set_power_fn, retry_attempts):
+ success = True
+ plugs = options["--plugs"] if "--plugs" in options else [""]
+
+ for plug in plugs:
+ try:
+ options["--uuid"] = str(uuid.UUID(plug))
+ except ValueError:
+ pass
+ except KeyError:
+ pass
+
+ options["--plug"] = plug
+ for retry in range(retry_attempts):
+ if sync_set_power_fn(connection, options):
+ break
+ if retry == retry_attempts-1:
+ success = False
+ time.sleep(int(options["--power-wait"]))
+
+ return success
+
+
+def set_multi_power_fn(connection, options, set_power_fn, get_power_fn, sync_set_power_fn, retry_attempts=1):
+
+ if set_power_fn != None:
+ if get_power_fn != None:
+ return async_set_multi_power_fn(connection, options, set_power_fn, get_power_fn, retry_attempts)
+ elif sync_set_power_fn != None:
+ return sync_set_multi_power_fn(connection, options, sync_set_power_fn, retry_attempts)
+
+ return False
+
+def multi_reboot_cycle_fn(connection, options, reboot_cycle_fn, retry_attempts=1):
+ success = True
+ plugs = options["--plugs"] if "--plugs" in options else [""]
+
+ for plug in plugs:
+ try:
+ options["--uuid"] = str(uuid.UUID(plug))
+ except ValueError:
+ pass
+ except KeyError:
+ pass
+
+ options["--plug"] = plug
+ for retry in range(retry_attempts):
+ if reboot_cycle_fn(connection, options):
+ break
+ if retry == retry_attempts-1:
+ success = False
+ time.sleep(int(options["--power-wait"]))
+
+ return success
+
+def show_docs(options, docs=None):
+ device_opt = options["device_opt"]
+
+ if docs == None:
+ docs = {}
+ docs["shortdesc"] = "Fence agent"
+ docs["longdesc"] = ""
+
+ if "--help" in options:
+ usage(device_opt)
+ sys.exit(0)
+
+ if options.get("--action", "") in ["metadata", "manpage"]:
+ if "port_as_ip" in device_opt:
+ device_opt.remove("separator")
+ metadata(options, device_opt, docs)
+ sys.exit(0)
+
+ if "--version" in options:
+ print(RELEASE_VERSION)
+ sys.exit(0)
+
+def fence_action(connection, options, set_power_fn, get_power_fn, get_outlet_list=None, reboot_cycle_fn=None, sync_set_power_fn=None):
+ result = 0
+
+ try:
+ if "--plug" in options:
+ options["--plugs"] = options["--plug"].split(options["--plug-separator"])
+
+ ## Process options that manipulate fencing device
+ #####
+ if (options["--action"] in ["list", "list-status"]) or \
+ ((options["--action"] == "monitor") and 1 == options["device_opt"].count("port") and \
+ 0 == options["device_opt"].count("port_as_ip")):
+
+ if 0 == options["device_opt"].count("port"):
+ print("N/A")
+ elif get_outlet_list == None:
+ ## @todo: exception?
+ ## This is just temporal solution, we will remove default value
+ ## None as soon as all existing agent will support this operation
+ print("NOTICE: List option is not working on this device yet")
+ else:
+ options["--original-action"] = options["--action"]
+ options["--action"] = "list"
+ outlets = get_outlet_list(connection, options)
+ options["--action"] = options["--original-action"]
+ del options["--original-action"]
+
+ ## keys can be numbers (port numbers) or strings (names of VM, UUID)
+ for outlet_id in list(outlets.keys()):
+ (alias, status) = outlets[outlet_id]
+ if status is None or (not status.upper() in ["ON", "OFF"]):
+ status = "UNKNOWN"
+ status = status.upper()
+
+ if options["--action"] == "list":
+ try:
+ print(outlet_id + options["--separator"] + alias)
+ except UnicodeEncodeError as e:
+ print((outlet_id + options["--separator"] + alias).encode("utf-8"))
+ elif options["--action"] == "list-status":
+ try:
+ print(outlet_id + options["--separator"] + alias + options["--separator"] + status)
+ except UnicodeEncodeError as e:
+ print((outlet_id + options["--separator"] + alias).encode("utf-8") + options["--separator"] + status)
+
+ return
+
+ if options["--action"] == "monitor" and not "port" in options["device_opt"] and "no_status" in options["device_opt"]:
+ # Unable to do standard monitoring because 'status' action is not available
+ return 0
+
+ status = None
+ if not "no_status" in options["device_opt"]:
+ status = get_multi_power_fn(connection, options, get_power_fn)
+ if status != "on" and status != "off":
+ fail(EC_STATUS)
+
+ if options["--action"] == status:
+ if not (status == "on" and "force_on" in options["device_opt"]):
+ print("Success: Already %s" % (status.upper()))
+ return 0
+
+ if options["--action"] == "on":
+ if set_multi_power_fn(connection, options, set_power_fn, get_power_fn, sync_set_power_fn, 1 + int(options["--retry-on"])):
+ print("Success: Powered ON")
+ else:
+ fail(EC_WAITING_ON)
+ elif options["--action"] == "off":
+ if set_multi_power_fn(connection, options, set_power_fn, get_power_fn, sync_set_power_fn):
+ print("Success: Powered OFF")
+ else:
+ fail(EC_WAITING_OFF)
+ elif options["--action"] == "reboot":
+ power_on = False
+ if options.get("--method", "").lower() == "cycle" and reboot_cycle_fn is not None:
+ try:
+ power_on = multi_reboot_cycle_fn(connection, options, reboot_cycle_fn, 1 + int(options["--retry-on"]))
+ except Exception as ex:
+ # an error occured during reboot action
+ logging.warning("%s", str(ex))
+
+ if not power_on:
+ fail(EC_TIMED_OUT)
+
+ else:
+ if status != "off":
+ options["--action"] = "off"
+ if not set_multi_power_fn(connection, options, set_power_fn, get_power_fn, sync_set_power_fn):
+ fail(EC_WAITING_OFF)
+
+ options["--action"] = "on"
+
+ try:
+ power_on = set_multi_power_fn(connection, options, set_power_fn, get_power_fn, sync_set_power_fn, int(options["--retry-on"]))
+ except Exception as ex:
+ # an error occured during power ON phase in reboot
+ # fence action was completed succesfully even in that case
+ logging.warning("%s", str(ex))
+
+ # switch back to original action for the case it is used lateron
+ options["--action"] = "reboot"
+
+ if power_on == False:
+ # this should not fail as node was fenced succesfully
+ logging.error('Timed out waiting to power ON\n')
+
+ print("Success: Rebooted")
+ elif options["--action"] == "status":
+ print("Status: " + status.upper())
+ if status.upper() == "OFF":
+ result = 2
+ elif options["--action"] == "monitor":
+ pass
+ except pexpect.EOF:
+ fail(EC_CONNECTION_LOST)
+ except pexpect.TIMEOUT:
+ fail(EC_TIMED_OUT)
+ except pycurl.error as ex:
+ logging.error("%s\n", str(ex))
+ fail(EC_TIMED_OUT)
+ except socket.timeout as ex:
+ logging.error("%s\n", str(ex))
+ fail(EC_TIMED_OUT)
+
+ return result
+
+def fence_login(options, re_login_string=r"(login\s*: )|((?!Last )Login Name: )|(username: )|(User Name :)"):
+ run_delay(options)
+
+ if "eol" not in options:
+ options["eol"] = "\r\n"
+
+ if "--command-prompt" in options and type(options["--command-prompt"]) is not list:
+ options["--command-prompt"] = [options["--command-prompt"]]
+
+ try:
+ if "--ssl" in options:
+ conn = _open_ssl_connection(options)
+ elif "--ssh" in options and "--identity-file" not in options:
+ conn = _login_ssh_with_password(options, re_login_string)
+ elif "--ssh" in options and "--identity-file" in options:
+ conn = _login_ssh_with_identity_file(options)
+ else:
+ conn = _login_telnet(options, re_login_string)
+ except pexpect.EOF as exception:
+ logging.debug("%s", str(exception))
+ fail(EC_LOGIN_DENIED)
+ except pexpect.TIMEOUT as exception:
+ logging.debug("%s", str(exception))
+ fail(EC_LOGIN_DENIED)
+ return conn
+
+def is_executable(path):
+ if os.path.exists(path):
+ stats = os.stat(path)
+ if stat.S_ISREG(stats.st_mode) and os.access(path, os.X_OK):
+ return True
+ return False
+
+def run_commands(options, commands, timeout=None, env=None, log_command=None):
+ # inspired by psutils.wait_procs (BSD License)
+ def check_gone(proc, timeout):
+ try:
+ returncode = proc.wait(timeout=timeout)
+ except subprocess.TimeoutExpired:
+ pass
+ else:
+ if returncode is not None or not proc.is_running():
+ proc.returncode = returncode
+ gone.add(proc)
+
+ if timeout is None and "--power-timeout" in options:
+ timeout = options["--power-timeout"]
+ if timeout == 0:
+ timeout = None
+ if timeout is not None:
+ timeout = float(timeout)
+
+ time_start = time.time()
+ procs = []
+ status = None
+ pipe_stdout = ""
+ pipe_stderr = ""
+
+ for command in commands:
+ logging.info("Executing: %s\n", log_command or command)
+
+ try:
+ process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env,
+ # decodes newlines and in python3 also converts bytes to str
+ universal_newlines=(sys.version_info[0] > 2))
+ except OSError:
+ fail_usage("Unable to run %s\n" % command)
+
+ procs.append(process)
+
+ gone = set()
+ alive = set(procs)
+
+ while True:
+ if alive:
+ max_timeout = 2.0 / len(alive)
+ for proc in alive:
+ if timeout is not None:
+ if time.time()-time_start >= timeout:
+ # quickly go over the rest
+ max_timeout = 0
+ check_gone(proc, max_timeout)
+ alive = alive - gone
+
+ if not alive:
+ break
+
+ if time.time()-time_start < 5.0:
+ # give it at least 5s to get a complete answer
+ # afterwards we're OK with a quorate answer
+ continue
+
+ if len(gone) > len(alive):
+ good_cnt = 0
+ for proc in gone:
+ if proc.returncode == 0:
+ good_cnt += 1
+ # a positive result from more than half is fine
+ if good_cnt > len(procs)/2:
+ break
+
+ if timeout is not None:
+ if time.time() - time_start >= timeout:
+ logging.debug("Stop waiting after %s\n", str(timeout))
+ break
+
+ logging.debug("Done: %d gone, %d alive\n", len(gone), len(alive))
+
+ for proc in gone:
+ if (status != 0):
+ status = proc.returncode
+ # hand over the best status we have
+ # but still collect as much stdout/stderr feedback
+ # avoid communicate as we know already process
+ # is gone and it seems to block when there
+ # are D state children we don't get rid off
+ os.set_blocking(proc.stdout.fileno(), False)
+ os.set_blocking(proc.stderr.fileno(), False)
+ try:
+ pipe_stdout += proc.stdout.read()
+ except:
+ pass
+ try:
+ pipe_stderr += proc.stderr.read()
+ except:
+ pass
+ proc.stdout.close()
+ proc.stderr.close()
+
+ for proc in alive:
+ proc.kill()
+
+ if status is None:
+ fail(EC_TIMED_OUT, stop=(int(options.get("retry", 0)) < 1))
+ status = EC_TIMED_OUT
+ pipe_stdout = ""
+ pipe_stderr = "timed out"
+
+ logging.debug("%s %s %s\n", str(status), str(pipe_stdout), str(pipe_stderr))
+
+ return (status, pipe_stdout, pipe_stderr)
+
+def run_command(options, command, timeout=None, env=None, log_command=None):
+ if timeout is None and "--power-timeout" in options:
+ timeout = options["--power-timeout"]
+ if timeout is not None:
+ timeout = float(timeout)
+
+ logging.info("Executing: %s\n", log_command or command)
+
+ try:
+ process = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env,
+ # decodes newlines and in python3 also converts bytes to str
+ universal_newlines=(sys.version_info[0] > 2))
+ except OSError:
+ fail_usage("Unable to run %s\n" % command)
+
+ thread = threading.Thread(target=process.wait)
+ thread.start()
+ thread.join(timeout if timeout else None)
+ if thread.is_alive():
+ process.kill()
+ fail(EC_TIMED_OUT, stop=(int(options.get("retry", 0)) < 1))
+
+ status = process.wait()
+
+ (pipe_stdout, pipe_stderr) = process.communicate()
+ process.stdout.close()
+ process.stderr.close()
+
+ logging.debug("%s %s %s\n", str(status), str(pipe_stdout), str(pipe_stderr))
+
+ return (status, pipe_stdout, pipe_stderr)
+
+def run_delay(options, reserve=0, result=0):
+ ## Delay is important for two-node clusters fencing
+ ## but we do not need to delay 'status' operations
+ ## and get us out quickly if we already know that we are gonna fail
+ ## still wanna do something right before fencing? - reserve some time
+ if options["--action"] in ["off", "reboot"] \
+ and options["--delay"] != "0" \
+ and result == 0 \
+ and reserve >= 0:
+ time_left = 1 + int(options["--delay"]) - (time.time() - run_delay.time_start) - reserve
+ if time_left > 0:
+ logging.info("Delay %d second(s) before logging in to the fence device", time_left)
+ time.sleep(time_left)
+# mark time when fence-agent is started
+run_delay.time_start = time.time()
+
+def fence_logout(conn, logout_string, sleep=0):
+ # Logout is not required part of fencing but we should attempt to do it properly
+ # In some cases our 'exit' command is faster and we can not close connection as it
+ # was already closed by fencing device
+ try:
+ conn.send_eol(logout_string)
+ time.sleep(sleep)
+ conn.close()
+ except OSError:
+ pass
+ except pexpect.ExceptionPexpect:
+ pass
+
+def source_env(env_file):
+ # POSIX: name shall not contain '=', value doesn't contain '\0'
+ output = subprocess.check_output("source {} && env -0".format(env_file), shell=True,
+ executable="/bin/sh")
+ # replace env
+ os.environ.clear()
+ os.environ.update(line.partition('=')[::2] for line in output.decode("utf-8").split('\0') if not re.match("^\s*$", line))
+
+# Convert array of format [[key1, value1], [key2, value2], ... [keyN, valueN]] to dict, where key is
+# in format a.b.c.d...z and returned dict has key only z
+def array_to_dict(array):
+ return dict([[x[0].split(".")[-1], x[1]] for x in array])
+
+## Own logger handler that uses old-style syslog handler as otherwise everything is sourced
+## from /dev/syslog
+class SyslogLibHandler(logging.StreamHandler):
+ """
+ A handler class that correctly push messages into syslog
+ """
+ def emit(self, record):
+ syslog_level = {
+ logging.CRITICAL:syslog.LOG_CRIT,
+ logging.ERROR:syslog.LOG_ERR,
+ logging.WARNING:syslog.LOG_WARNING,
+ logging.INFO:syslog.LOG_INFO,
+ logging.DEBUG:syslog.LOG_DEBUG,
+ logging.NOTSET:syslog.LOG_DEBUG,
+ }[record.levelno]
+
+ msg = self.format(record)
+
+ # syslos.syslog can not have 0x00 character inside or exception is thrown
+ syslog.syslog(syslog_level, msg.replace("\x00", "\n"))
+ return
+
+def _open_ssl_connection(options):
+ gnutls_opts = ""
+ ssl_opts = ""
+
+ if "--notls" in options:
+ gnutls_opts = "--priority \"NORMAL:-VERS-TLS1.2:-VERS-TLS1.1:-VERS-TLS1.0:+VERS-SSL3.0\""
+ elif "--tls1.0" in options:
+ gnutls_opts = "--priority \"NORMAL:-VERS-TLS1.2:-VERS-TLS1.1:+VERS-TLS1.0:%LATEST_RECORD_VERSION\""
+
+ # --ssl is same as the --ssl-secure; it means we want to verify certificate in these cases
+ if "--ssl-insecure" in options:
+ ssl_opts = "--insecure"
+
+ command = '%s %s %s --crlf -p %s %s' % \
+ (options["--gnutlscli-path"], gnutls_opts, ssl_opts, options["--ipport"], options["--ip"])
+ try:
+ conn = fspawn(options, command)
+ except pexpect.ExceptionPexpect as ex:
+ logging.error("%s\n", str(ex))
+ sys.exit(EC_GENERIC_ERROR)
+
+ return conn
+
+def _login_ssh_with_identity_file(options):
+ if "--inet6-only" in options:
+ force_ipvx = "-6 "
+ elif "--inet4-only" in options:
+ force_ipvx = "-4 "
+ else:
+ force_ipvx = ""
+
+ command = '%s %s %s@%s -i %s -p %s' % \
+ (options["--ssh-path"], force_ipvx, options["--username"], options["--ip"], \
+ options["--identity-file"], options["--ipport"])
+ if "--ssh-options" in options:
+ command += ' ' + options["--ssh-options"]
+
+ conn = fspawn(options, command)
+
+ result = conn.log_expect(["Enter passphrase for key '" + options["--identity-file"] + "':", \
+ "Are you sure you want to continue connecting (yes/no)?"] + \
+ options["--command-prompt"], int(options["--login-timeout"]))
+ if result == 1:
+ conn.sendline("yes")
+ result = conn.log_expect(
+ ["Enter passphrase for key '" + options["--identity-file"]+"':"] + \
+ options["--command-prompt"], int(options["--login-timeout"]))
+ if result == 0:
+ if "--password" in options:
+ conn.sendline(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--login-timeout"]))
+ else:
+ fail_usage("Failed: You have to enter passphrase (-p) for identity file")
+
+ return conn
+
+def _login_telnet(options, re_login_string):
+ re_login = re.compile(re_login_string, re.IGNORECASE)
+ re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
+
+ conn = fspawn(options, options["--telnet-path"])
+ conn.send("set binary\n")
+ conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
+
+ conn.log_expect(re_login, int(options["--login-timeout"]))
+ conn.send_eol(options["--username"])
+
+ ## automatically change end of line separator
+ screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ if re_login.search(screen) != None:
+ options["eol"] = "\n"
+ conn.send_eol(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ elif re_pass.search(screen) == None:
+ conn.log_expect(re_pass, int(options["--shell-timeout"]))
+
+ try:
+ conn.send_eol(options["--password"])
+ valid_password = conn.log_expect([re_login] + \
+ options["--command-prompt"], int(options["--shell-timeout"]))
+ if valid_password == 0:
+ ## password is invalid or we have to change EOL separator
+ options["eol"] = "\r"
+ conn.send_eol("")
+ screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"]))
+ ## after sending EOL the fence device can either show 'Login' or 'Password'
+ if re_login.search(conn.after + screen) != None:
+ conn.send_eol("")
+ conn.send_eol(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ conn.send_eol(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--login-timeout"]))
+ except KeyError:
+ fail(EC_PASSWORD_MISSING)
+
+ return conn
+
+def _login_ssh_with_password(options, re_login_string):
+ re_login = re.compile(re_login_string, re.IGNORECASE)
+ re_pass = re.compile("(password)|(pass phrase)", re.IGNORECASE)
+
+ if "--inet6-only" in options:
+ force_ipvx = "-6 "
+ elif "--inet4-only" in options:
+ force_ipvx = "-4 "
+ else:
+ force_ipvx = ""
+
+ command = '%s %s %s@%s -p %s -o PubkeyAuthentication=no' % \
+ (options["--ssh-path"], force_ipvx, options["--username"], options["--ip"], options["--ipport"])
+ if "--ssh-options" in options:
+ command += ' ' + options["--ssh-options"]
+
+ conn = fspawn(options, command)
+
+ if "telnet_over_ssh" in options:
+ # This is for stupid ssh servers (like ALOM) which behave more like telnet
+ # (ignore name and display login prompt)
+ result = conn.log_expect( \
+ [re_login, "Are you sure you want to continue connecting (yes/no)?"],
+ int(options["--login-timeout"]))
+ if result == 1:
+ conn.sendline("yes") # Host identity confirm
+ conn.log_expect(re_login, int(options["--login-timeout"]))
+
+ conn.sendline(options["--username"])
+ conn.log_expect(re_pass, int(options["--login-timeout"]))
+ else:
+ result = conn.log_expect( \
+ ["ssword:", "Are you sure you want to continue connecting (yes/no)?"],
+ int(options["--login-timeout"]))
+ if result == 1:
+ conn.sendline("yes")
+ conn.log_expect("ssword:", int(options["--login-timeout"]))
+
+ conn.sendline(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--login-timeout"]))
+
+ return conn
+
+#
+# To update metadata, we change values in all_opt
+def _update_metadata(options):
+ device_opt = options["device_opt"]
+
+ if device_opt.count("login") and device_opt.count("no_login") == 0:
+ all_opt["login"]["required"] = "1"
+ else:
+ all_opt["login"]["required"] = "0"
+
+ if device_opt.count("port_as_ip"):
+ all_opt["ipaddr"]["required"] = "0"
+ all_opt["port"]["required"] = "0"
+
+ (available_actions, default_value) = _get_available_actions(device_opt)
+ all_opt["action"]["default"] = default_value
+
+ actions_with_default = \
+ [x if not x == all_opt["action"]["default"] else x + " (default)" for x in available_actions]
+ all_opt["action"]["help"] = \
+ "-o, --action=[action] Action: %s" % (_join_wrap(actions_with_default, last_separator=" or "))
+
+ if device_opt.count("ipport"):
+ default_value = None
+ default_string = None
+
+ if "default" in all_opt["ipport"]:
+ default_value = all_opt["ipport"]["default"]
+ elif device_opt.count("web") and device_opt.count("ssl"):
+ default_value = "80"
+ default_string = "(default 80, 443 if --ssl option is used)"
+ elif device_opt.count("telnet") and device_opt.count("secure"):
+ default_value = "23"
+ default_string = "(default 23, 22 if --ssh option is used)"
+ else:
+ tcp_ports = {"community" : "161", "secure" : "22", "telnet" : "23", "web" : "80", "ssl" : "443"}
+ # all cases where next command returns multiple results are covered by previous blocks
+ protocol = [x for x in ["community", "secure", "ssl", "web", "telnet"] if device_opt.count(x)][0]
+ default_value = tcp_ports[protocol]
+
+ if default_string is None:
+ all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use (default %s)" % \
+ (default_value)
+ else:
+ all_opt["ipport"]["help"] = "-u, --ipport=[port] TCP/UDP port to use\n" + " "*40 + default_string
+
+def _set_default_values(options):
+ if "ipport" in options["device_opt"]:
+ if not "--ipport" in options:
+ if "default" in all_opt["ipport"]:
+ options["--ipport"] = all_opt["ipport"]["default"]
+ elif "community" in options["device_opt"]:
+ options["--ipport"] = "161"
+ elif "--ssh" in options or all_opt["secure"].get("default", "0") == "1":
+ options["--ipport"] = "22"
+ elif "--ssl" in options or all_opt["ssl"].get("default", "0") == "1":
+ options["--ipport"] = "443"
+ elif "--ssl-secure" in options or all_opt["ssl_secure"].get("default", "0") == "1":
+ options["--ipport"] = "443"
+ elif "--ssl-insecure" in options or all_opt["ssl_insecure"].get("default", "0") == "1":
+ options["--ipport"] = "443"
+ elif "web" in options["device_opt"]:
+ options["--ipport"] = "80"
+ elif "telnet" in options["device_opt"]:
+ options["--ipport"] = "23"
+
+ if "--ipport" in options:
+ all_opt["ipport"]["default"] = options["--ipport"]
+
+ for opt in options["device_opt"]:
+ if "default" in all_opt[opt] and not opt == "ipport":
+ getopt_long = "--" + all_opt[opt]["longopt"]
+ if getopt_long not in options:
+ options[getopt_long] = all_opt[opt]["default"]
+
+ return options
+
+# stop = True/False : exit fence agent when problem is encountered
+def _validate_input(options, stop = True):
+ device_opt = options["device_opt"]
+ valid_input = True
+
+ if "--username" not in options and \
+ device_opt.count("login") and (device_opt.count("no_login") == 0):
+ valid_input = False
+ fail_usage("Failed: You have to set login name", stop)
+
+ if device_opt.count("ipaddr") and "--ip" not in options and "--managed" not in options and "--target" not in options:
+ valid_input = False
+ fail_usage("Failed: You have to enter fence address", stop)
+
+ if device_opt.count("no_password") == 0:
+ if 0 == device_opt.count("identity_file"):
+ if not ("--password" in options or "--password-script" in options):
+ valid_input = False
+ fail_usage("Failed: You have to enter password or password script", stop)
+ else:
+ if not ("--password" in options or \
+ "--password-script" in options or "--identity-file" in options):
+ valid_input = False
+ fail_usage("Failed: You have to enter password, password script or identity file", stop)
+
+ if "--ssh" not in options and "--identity-file" in options:
+ valid_input = False
+ fail_usage("Failed: You have to use identity file together with ssh connection (-x)", stop)
+
+ if "--identity-file" in options and not os.path.isfile(options["--identity-file"]):
+ valid_input = False
+ fail_usage("Failed: Identity file " + options["--identity-file"] + " does not exist", stop)
+
+ if (0 == ["list", "list-status", "monitor"].count(options["--action"])) and \
+ "--plug" not in options and device_opt.count("port") and \
+ device_opt.count("no_port") == 0 and not device_opt.count("port_as_ip"):
+ valid_input = False
+ fail_usage("Failed: You have to enter plug number or machine identification", stop)
+
+ for failed_opt in _get_opts_with_invalid_choices(options):
+ valid_input = False
+ fail_usage("Failed: You have to enter a valid choice for %s from the valid values: %s" % \
+ ("--" + all_opt[failed_opt]["longopt"], str(all_opt[failed_opt]["choices"])), stop)
+
+ for failed_opt in _get_opts_with_invalid_types(options):
+ valid_input = False
+ if all_opt[failed_opt]["type"] == "second":
+ fail_usage("Failed: The value you have entered for %s is not a valid time in seconds" % \
+ ("--" + all_opt[failed_opt]["longopt"]), stop)
+ else:
+ fail_usage("Failed: The value you have entered for %s is not a valid %s" % \
+ ("--" + all_opt[failed_opt]["longopt"], all_opt[failed_opt]["type"]), stop)
+
+ return valid_input
+
+def _encode_html_entities(text):
+ return text.replace("&", "&amp;").replace('"', "&quot;").replace('<', "&lt;"). \
+ replace('>', "&gt;").replace("'", "&apos;")
+
+def _prepare_getopt_args(options):
+ getopt_string = ""
+ longopt_list = []
+ for k in options:
+ if k in all_opt and all_opt[k]["getopt"] != ":":
+ # getopt == ":" means that opt is without short getopt, but has value
+ getopt_string += all_opt[k]["getopt"]
+ elif k not in all_opt:
+ fail_usage("Parse error: unknown option '"+k+"'")
+
+ if k in all_opt and "longopt" in all_opt[k]:
+ if all_opt[k]["getopt"].endswith(":"):
+ longopt_list.append(all_opt[k]["longopt"] + "=")
+ else:
+ longopt_list.append(all_opt[k]["longopt"])
+
+ return (getopt_string, longopt_list)
+
+def _parse_input_stdin(avail_opt):
+ opt = {}
+ name = ""
+
+ mapping_longopt_names = dict([(all_opt[o].get("longopt"), o) for o in avail_opt])
+
+ for line in sys.stdin.readlines():
+ line = line.strip()
+ if (line.startswith("#")) or (len(line) == 0):
+ continue
+
+ (name, value) = (line + "=").split("=", 1)
+ value = value[:-1]
+ value = re.sub("^\"(.*)\"$", "\\1", value)
+
+ if name.replace("-", "_") in mapping_longopt_names:
+ name = mapping_longopt_names[name.replace("-", "_")]
+ elif name.replace("_", "-") in mapping_longopt_names:
+ name = mapping_longopt_names[name.replace("_", "-")]
+
+ if avail_opt.count(name) == 0 and name in ["nodename"]:
+ continue
+ elif avail_opt.count(name) == 0:
+ logging.warning("Parse error: Ignoring unknown option '%s'\n", line)
+ continue
+
+ if all_opt[name]["getopt"].endswith(":"):
+ opt["--"+all_opt[name]["longopt"].rstrip(":")] = value
+ elif value.lower() in ["1", "yes", "on", "true"]:
+ opt["--"+all_opt[name]["longopt"]] = "1"
+ elif value.lower() in ["0", "no", "off", "false"]:
+ opt["--"+all_opt[name]["longopt"]] = "0"
+ else:
+ logging.warning("Parse error: Ignoring option '%s' because it does not have value\n", name)
+
+ opt.setdefault("--verbose-level", opt.get("--verbose", 0))
+
+ return opt
+
+def _parse_input_cmdline(avail_opt):
+ filtered_opts = {}
+ _verify_unique_getopt(avail_opt)
+ (getopt_string, longopt_list) = _prepare_getopt_args(avail_opt)
+
+ try:
+ (entered_opt, left_arg) = getopt.gnu_getopt(sys.argv[1:], getopt_string, longopt_list)
+ if len(left_arg) > 0:
+ logging.warning("Unused arguments on command line: %s" % (str(left_arg)))
+ except getopt.GetoptError as error:
+ fail_usage("Parse error: " + error.msg)
+
+ for opt in avail_opt:
+ filtered_opts.update({opt : all_opt[opt]})
+
+ # Short and long getopt names are changed to consistent "--" + long name (e.g. --username)
+ long_opts = {}
+ verbose_count = 0
+ for arg_name in [k for (k, v) in entered_opt]:
+ all_key = [key for (key, value) in list(filtered_opts.items()) \
+ if "--" + value.get("longopt", "") == arg_name or "-" + value.get("getopt", "").rstrip(":") == arg_name][0]
+ long_opts["--" + filtered_opts[all_key]["longopt"]] = dict(entered_opt)[arg_name]
+ if all_key == "verbose":
+ verbose_count += 1
+
+ long_opts.setdefault("--verbose-level", verbose_count)
+
+ # This test is specific because it does not apply to input on stdin
+ if "port_as_ip" in avail_opt and not "--port-as-ip" in long_opts and "--plug" in long_opts:
+ fail_usage("Parser error: option -n/--plug is not recognized")
+
+ return long_opts
+
+# for ["John", "Mary", "Eli"] returns "John, Mary and Eli"
+def _join2(words, normal_separator=", ", last_separator=" and "):
+ if len(words) <= 1:
+ return "".join(words)
+ else:
+ return last_separator.join([normal_separator.join(words[:-1]), words[-1]])
+
+def _join_wrap(words, normal_separator=", ", last_separator=" and ", first_indent=42):
+ x = _join2(words, normal_separator, last_separator)
+ wrapper = textwrap.TextWrapper()
+ wrapper.initial_indent = " "*first_indent
+ wrapper.subsequent_indent = " "*40
+ wrapper.width = 85
+ wrapper.break_on_hyphens = False
+ wrapper.break_long_words = False
+ wrapped_text = ""
+ for line in wrapper.wrap(x):
+ wrapped_text += line + "\n"
+ return wrapped_text.lstrip().rstrip("\n")
+
+def _get_opts_with_invalid_choices(options):
+ options_failed = []
+ device_opt = options["device_opt"]
+
+ for opt in device_opt:
+ if "choices" in all_opt[opt]:
+ longopt = "--" + all_opt[opt]["longopt"]
+ possible_values_upper = [y.upper() for y in all_opt[opt]["choices"]]
+ if longopt in options:
+ options[longopt] = options[longopt].upper()
+ if not options["--" + all_opt[opt]["longopt"]] in possible_values_upper:
+ options_failed.append(opt)
+ return options_failed
+
+def _get_opts_with_invalid_types(options):
+ options_failed = []
+ device_opt = options["device_opt"]
+
+ for opt in device_opt:
+ if "type" in all_opt[opt]:
+ longopt = "--" + all_opt[opt]["longopt"]
+ if longopt in options:
+ if all_opt[opt]["type"] in ["integer", "second"]:
+ try:
+ number = int(options["--" + all_opt[opt]["longopt"]])
+ except ValueError:
+ options_failed.append(opt)
+ return options_failed
+
+def _verify_unique_getopt(avail_opt):
+ used_getopt = set()
+
+ for opt in avail_opt:
+ getopt_value = all_opt[opt].get("getopt", "").rstrip(":")
+ if getopt_value and getopt_value in used_getopt:
+ fail_usage("Short getopt for %s (-%s) is not unique" % (opt, getopt_value))
+ else:
+ used_getopt.add(getopt_value)
+
+def _get_available_actions(device_opt):
+ available_actions = ["on", "off", "reboot", "status", "list", "list-status", \
+ "monitor", "metadata", "manpage", "validate-all"]
+ default_value = "reboot"
+
+ if device_opt.count("fabric_fencing"):
+ available_actions.remove("reboot")
+ default_value = "off"
+ if device_opt.count("no_status"):
+ available_actions.remove("status")
+ if device_opt.count("no_on"):
+ available_actions.remove("on")
+ if device_opt.count("no_off"):
+ available_actions.remove("off")
+ if not device_opt.count("separator"):
+ available_actions.remove("list")
+ available_actions.remove("list-status")
+ if device_opt.count("diag"):
+ available_actions.append("diag")
+
+ return (available_actions, default_value)
diff --git a/lib/fencing_snmp.py.py b/lib/fencing_snmp.py.py
new file mode 100644
index 0000000..f9e5768
--- /dev/null
+++ b/lib/fencing_snmp.py.py
@@ -0,0 +1,128 @@
+#!@PYTHON@ -tt
+
+# For example of use please see fence_cisco_mds
+
+import re, pexpect
+import logging
+from fencing import *
+from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay, frun
+
+__all__ = ['FencingSnmp']
+
+## do not add code here.
+class FencingSnmp:
+ def __init__(self, options):
+ self.options = options
+ run_delay(options)
+
+ def quote_for_run(self, string):
+ return string.replace(r"'", "'\\''")
+
+ def complete_missed_params(self):
+ mapping = [[
+ ['snmp-priv-passwd', 'password', '!snmp-sec-level'],
+ 'self.options["--snmp-sec-level"]="authPriv"'
+ ], [
+ ['!snmp-version', 'community', '!username', '!snmp-priv-passwd', '!password'],
+ 'self.options["--snmp-version"]="2c"'
+ ]]
+
+ for val in mapping:
+ e = val[0]
+
+ res = True
+
+ for item in e:
+ if item[0] == '!' and "--" + item[1:] in self.options:
+ res = False
+ break
+
+ if item[0] != '!' and "--" + item[0:] not in self.options:
+ res = False
+ break
+
+ if res:
+ exec(val[1])
+
+ def prepare_cmd(self, command):
+ cmd = "%s -m '' -Oeqn "% (command)
+
+ self.complete_missed_params()
+
+ #mapping from our option to snmpcmd option
+ mapping = (('snmp-version', 'v'), ('community', 'c'))
+
+ for item in mapping:
+ if "--" + item[0] in self.options:
+ cmd += " -%s '%s'"% (item[1], self.quote_for_run(self.options["--" + item[0]]))
+
+ # Some options make sense only for v3 (and for v1/2c can cause "problems")
+ if ("--snmp-version" in self.options) and (self.options["--snmp-version"] == "3"):
+ # Mapping from our options to snmpcmd options for v3
+ mapping_v3 = (('snmp-auth-prot', 'a'), ('snmp-sec-level', 'l'), ('snmp-priv-prot', 'x'), \
+ ('snmp-priv-passwd', 'X'), ('password', 'A'), ('username', 'u'))
+ for item in mapping_v3:
+ if "--"+item[0] in self.options:
+ cmd += " -%s '%s'"% (item[1], self.quote_for_run(self.options["--" + item[0]]))
+
+ force_ipvx = ""
+
+ if "--inet6-only" in self.options:
+ force_ipvx = "udp6:"
+
+ if "--inet4-only" in self.options:
+ force_ipvx = "udp:"
+
+ cmd += " '%s%s%s'"% (force_ipvx, self.quote_for_run(self.options["--ip"]),
+ "--ipport" in self.options and self.quote_for_run(":" + str(self.options["--ipport"])) or "")
+ return cmd
+
+ def run_command(self, command, additional_timeout=0):
+ try:
+ logging.debug("%s\n", command)
+
+ (res_output, res_code) = frun(command,
+ int(self.options["--shell-timeout"]) +
+ int(self.options["--login-timeout"]) +
+ additional_timeout, True)
+
+ if res_code == None:
+ fail(EC_TIMED_OUT)
+
+ logging.debug("%s\n", res_output)
+
+ if (res_code != 0) or (re.search("^Error ", res_output, re.MULTILINE) != None):
+ fail_usage("Returned %d: %s"% (res_code, res_output))
+ except pexpect.ExceptionPexpect:
+ fail_usage("Cannot run command %s"%(command))
+
+ return res_output
+
+ def get(self, oid, additional_timeout=0):
+ cmd = "%s '%s'"% (self.prepare_cmd(self.options["--snmpget-path"]), self.quote_for_run(oid))
+
+ output = self.run_command(cmd, additional_timeout).splitlines()
+
+ return output[len(output)-1].split(None, 1)
+
+ def set(self, oid, value, additional_timeout=0):
+ mapping = ((int, 'i'), (str, 's'))
+
+ type_of_value = ''
+
+ for item in mapping:
+ if isinstance(value, item[0]):
+ type_of_value = item[1]
+ break
+
+ cmd = "%s '%s' %s '%s'" % (self.prepare_cmd(self.options["--snmpset-path"]),
+ self.quote_for_run(oid), type_of_value, self.quote_for_run(str(value)))
+
+ self.run_command(cmd, additional_timeout)
+
+ def walk(self, oid, additional_timeout=0):
+ cmd = "%s '%s'"% (self.prepare_cmd(self.options["--snmpwalk-path"]), self.quote_for_run(oid))
+
+ output = self.run_command(cmd, additional_timeout).splitlines()
+
+ return [x.split(None, 1) for x in output if x.startswith(".")]
diff --git a/lib/metadata.rng b/lib/metadata.rng
new file mode 100644
index 0000000..e0cd441
--- /dev/null
+++ b/lib/metadata.rng
@@ -0,0 +1,80 @@
+<grammar xmlns="http://relaxng.org/ns/structure/1.0">
+
+<start><element name="resource-agent">
+ <attribute name="name" />
+ <attribute name="shortdesc" />
+
+ <zeroOrMore>
+ <element name="symlink">
+ <attribute name="name" />
+ <attribute name="shortdesc" />
+ </element>
+ </zeroOrMore>
+
+ <element name="longdesc"> <text /> </element>
+ <element name="vendor-url"> <text /> </element>
+
+ <element name="parameters"> <oneOrMore>
+ <element name="parameter">
+ <attribute name="name" />
+ <attribute name="unique"> <ref name="boolean-values" /> </attribute>
+ <attribute name="required"> <ref name="boolean-values" /> </attribute>
+ <optional><attribute name="deprecated"> <ref name="boolean-values" /></attribute></optional>
+ <optional><attribute name="obsoletes" /> </optional>
+ <element name="getopt">
+ <attribute name="mixed" />
+ </element>
+ <element name="content">
+ <choice>
+ <attribute name="type">
+ <choice>
+ <value>boolean</value>
+ <value>string</value>
+ <value>second</value>
+ <value>integer</value>
+ </choice>
+ </attribute>
+ <group>
+ <attribute name="type">
+ <value>select</value>
+ </attribute>
+ <zeroOrMore>
+ <element name="option">
+ <attribute name="value" />
+ </element>
+ </zeroOrMore>
+ </group>
+ </choice>
+ <optional>
+ <attribute name="default"> <text /> </attribute>
+ </optional>
+ </element>
+
+ <oneOrMore> <element name="shortdesc">
+ <attribute name="lang" />
+ <text />
+ </element> </oneOrMore>
+ </element>
+ </oneOrMore> </element>
+
+ <element name="actions"> <oneOrMore>
+ <element name="action">
+ <attribute name="name" />
+ <optional>
+ <attribute name="on_target"> <ref name="boolean-values" /> </attribute>
+ </optional>
+ <optional>
+ <attribute name="automatic"> <ref name="boolean-values" /> </attribute>
+ </optional>
+ </element>
+ </oneOrMore> </element>
+</element></start>
+
+<define name="boolean-values">
+ <choice>
+ <value>0</value>
+ <value>1</value>
+ </choice>
+</define>
+
+</grammar>
diff --git a/lib/tests/test_fencing.py b/lib/tests/test_fencing.py
new file mode 100644
index 0000000..6ee9385
--- /dev/null
+++ b/lib/tests/test_fencing.py
@@ -0,0 +1,123 @@
+#!/usr/bin/python
+
+import unittest
+import sys
+sys.path.append("..")
+import fencing
+import copy
+
+class Test_join2(unittest.TestCase):
+ def test_single(self):
+ words = ["Mike"]
+ self.assertEqual(fencing._join2(words), "Mike")
+ self.assertEqual(fencing._join2(words, last_separator=" xor "), "Mike")
+ self.assertEqual(fencing._join2(words, normal_separator=" xor "), "Mike")
+
+ def test_double(self):
+ words = ["Mike", "John"]
+ self.assertEqual(fencing._join2(words), "Mike and John")
+ self.assertEqual(fencing._join2(words, last_separator=" xor "), "Mike xor John")
+ self.assertEqual(fencing._join2(words, normal_separator=" xor "), "Mike and John")
+
+ def test_triple(self):
+ words = ["Mike", "John", "Adam"]
+ self.assertEqual(fencing._join2(words), "Mike, John and Adam")
+ self.assertEqual(fencing._join2(words, last_separator=" xor "), "Mike, John xor Adam")
+ self.assertEqual(fencing._join2(words, normal_separator=" xor "), "Mike xor John and Adam")
+
+ def test_quadruple(self):
+ words = ["Eve", "Mike", "John", "Adam"]
+ self.assertEqual(fencing._join2(words), "Eve, Mike, John and Adam")
+ self.assertEqual(fencing._join2(words, last_separator=" xor "), "Eve, Mike, John xor Adam")
+ self.assertEqual(fencing._join2(words, normal_separator=" xor "), "Eve xor Mike xor John and Adam")
+
+class Test_add_dependency_options(unittest.TestCase):
+ basic_set = fencing.DEPENDENCY_OPT["default"]
+
+ def test_add_nothing(self):
+ self.assertEqual(set(fencing._add_dependency_options([])), set(self.basic_set))
+ self.assertEqual(set(fencing._add_dependency_options(["not-exist"])), set(self.basic_set))
+
+ def test_add_single(self):
+ self.assertEqual(set(fencing._add_dependency_options(["passwd"])), set(self.basic_set + ["passwd_script"]))
+
+ def test_add_tuple(self):
+ self.assertEqual(set(fencing._add_dependency_options(["ssl", "passwd"])), \
+ set(self.basic_set + ["passwd_script", "ssl_secure", "ssl_insecure", "gnutlscli_path"]))
+
+class Test_set_default_values(unittest.TestCase):
+ original_all_opt = None
+
+ def setUp(self):
+ # all_opt[*]["default"] can be changed during tests
+ self.original_all_opt = copy.deepcopy(fencing.all_opt)
+
+ def tearDown(self):
+ fencing.all_opt = copy.deepcopy(self.original_all_opt)
+
+ def _prepare_options(self, device_opts, args = {}):
+ device_opts = fencing._add_dependency_options(device_opts) + device_opts
+
+ arg_opts = args
+ options = dict(arg_opts)
+ options["device_opt"] = device_opts
+ fencing._update_metadata(options)
+ return fencing._set_default_values(options)
+
+ def test_status_io(self):
+ options = self._prepare_options([])
+
+ self.assertEqual(options["--action"], "reboot")
+ self.assertIsNone(options.get("--not-exist", None))
+
+ def test_status_fabric(self):
+ options = self._prepare_options(["fabric_fencing"])
+ self.assertEqual(options["--action"], "off")
+
+ def test_ipport_nothing(self):
+ # should fail because connection method (telnet/ssh/...) is not set at all
+ self.assertRaises(IndexError, self._prepare_options, ["ipaddr"])
+
+ def test_ipport_set(self):
+ options = self._prepare_options(["ipaddr", "telnet"], {"--ipport" : "999"})
+ self.assertEqual(options["--ipport"], "999")
+
+ def test_ipport_telnet(self):
+ options = self._prepare_options(["ipaddr", "telnet"])
+ self.assertEqual(options["--ipport"], "23")
+
+ def test_ipport_ssh(self):
+ options = self._prepare_options(["ipaddr", "secure"], {"--ssh" : "1"})
+ self.assertEqual(options["--ipport"], "22")
+
+ def test_ipport_sshtelnet_use_telnet(self):
+ options = self._prepare_options(["ipaddr", "secure", "telnet"])
+ self.assertEqual(options["--ipport"], "23")
+
+ def test_ipport_sshtelnet_use_ssh(self):
+ options = self._prepare_options(["ipaddr", "secure", "telnet"], {"--ssh" : "1"})
+ self.assertEqual(options["--ipport"], "22")
+
+ def test_ipport_ssl(self):
+ options = self._prepare_options(["ipaddr", "ssl"], {"--ssl-secure" : "1"})
+ self.assertEqual(options["--ipport"], "443")
+
+ def test_ipport_ssl_insecure_as_default(self):
+ fencing.all_opt["ssl_insecure"]["default"] = "1"
+ options = self._prepare_options(["ipaddr", "ssl"])
+ self.assertEqual(options["--ipport"], "443")
+
+ def test_ipport_snmp(self):
+ options = self._prepare_options(["ipaddr", "community"])
+ self.assertEqual(options["--ipport"], "161")
+
+ def test_ipport_web(self):
+ options = self._prepare_options(["ipaddr", "web", "ssl"])
+ self.assertEqual(options["--ipport"], "80")
+
+ def test_path_telnet(self):
+ options = self._prepare_options(["ipaddr", "telnet"])
+ self.assertTrue("--telnet-path" in options)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/m4/PKG_CHECK_VAR.m4 b/m4/PKG_CHECK_VAR.m4
new file mode 100644
index 0000000..2221a69
--- /dev/null
+++ b/m4/PKG_CHECK_VAR.m4
@@ -0,0 +1,24 @@
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+dnl
+dnl Origin (declared license: GPLv2+ with less restrictive exception):
+dnl https://cgit.freedesktop.org/pkg-config/tree/pkg.m4.in?h=pkg-config-0.29.1#n261
+dnl (AS_VAR_COPY replaced with backward-compatible equivalent and guard
+dnl to prefer system-wide variant by Jan Pokorny <jpokorny@redhat.com>)
+
+m4_ifndef([PKG_CHECK_VAR],[
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+dnl AS_VAR_COPY([$1], [pkg_cv_][$1])
+$1=AS_VAR_GET([pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+])dnl m4_ifndef
diff --git a/m4/ac_python_module.m4 b/m4/ac_python_module.m4
new file mode 100644
index 0000000..d1c81f6
--- /dev/null
+++ b/m4/ac_python_module.m4
@@ -0,0 +1,30 @@
+dnl @synopsis AC_PYTHON_MODULE(modname[, fatal])
+dnl
+dnl Checks for Python module.
+dnl
+dnl If fatal is non-empty then absence of a module will trigger an
+dnl error.
+dnl
+dnl @category InstalledPackages
+dnl @author Andrew Collier <colliera@nu.ac.za>.
+dnl @version 2004-07-14
+dnl @license AllPermissive
+
+AC_DEFUN([AC_PYTHON_MODULE],[
+ AC_MSG_CHECKING(python module: $1)
+ $PYTHON -c "import $1" 2>/dev/null
+ if test $? -eq 0;
+ then
+ AC_MSG_RESULT(yes)
+ eval AS_TR_CPP(HAVE_PYMOD_$1)=yes
+ else
+ AC_MSG_RESULT(no)
+ eval AS_TR_CPP(HAVE_PYMOD_$1)=no
+ #
+ if test -n "$2"
+ then
+ AC_MSG_ERROR(failed to find required module $1)
+ exit 1
+ fi
+ fi
+])
diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4
new file mode 100644
index 0000000..819409a
--- /dev/null
+++ b/m4/ax_check_link_flag.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the linker or gives an error.
+# (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the linker's default flags
+# when the check is done. The check is thus made with the flags: "LDFLAGS
+# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
+# issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# 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 <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 5
+
+AC_DEFUN([AX_CHECK_LINK_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
+ ax_check_save_flags=$LDFLAGS
+ LDFLAGS="$LDFLAGS $4 $1"
+ AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ LDFLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_LINK_FLAGS
diff --git a/m4/ax_prog_date.m4 b/m4/ax_prog_date.m4
new file mode 100644
index 0000000..c85f0f2
--- /dev/null
+++ b/m4/ax_prog_date.m4
@@ -0,0 +1,137 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_prog_date.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PROG_DATE()
+#
+# DESCRIPTION
+#
+# This macro tries to determine the type of the date (1) command and some
+# of its non-standard capabilities.
+#
+# The type is determined as follow:
+#
+# * If the version string contains "GNU", then:
+# - The variable ax_cv_prog_date_gnu is set to "yes".
+# - The variable ax_cv_prog_date_type is set to "gnu".
+#
+# * If date supports the "-v 1d" option, then:
+# - The variable ax_cv_prog_date_bsd is set to "yes".
+# - The variable ax_cv_prog_date_type is set to "bsd".
+#
+# * If both previous checks fail, then:
+# - The variable ax_cv_prog_date_type is set to "unknown".
+#
+# The following capabilities of GNU date are checked:
+#
+# * If date supports the --date arg option, then:
+# - The variable ax_cv_prog_date_gnu_date is set to "yes".
+#
+# * If date supports the --utc arg option, then:
+# - The variable ax_cv_prog_date_gnu_utc is set to "yes".
+#
+# The following capabilities of BSD date are checked:
+#
+# * If date supports the -v 1d option, then:
+# - The variable ax_cv_prog_date_bsd_adjust is set to "yes".
+#
+# * If date supports the -r arg option, then:
+# - The variable ax_cv_prog_date_bsd_date is set to "yes".
+#
+# All the aforementioned variables are set to "no" before a check is
+# performed.
+#
+# LICENSE
+#
+# Copyright (c) 2017 Enrico M. Crisostomo <enrico.m.crisostomo@gmail.com>
+#
+# 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/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 3
+
+AC_DEFUN([AX_PROG_DATE], [dnl
+ AC_CACHE_CHECK([for GNU date], [ax_cv_prog_date_gnu], [
+ ax_cv_prog_date_gnu=no
+ if date --version 2>/dev/null | head -1 | grep -q GNU
+ then
+ ax_cv_prog_date_gnu=yes
+ fi
+ ])
+ AC_CACHE_CHECK([for BSD date], [ax_cv_prog_date_bsd], [
+ ax_cv_prog_date_bsd=no
+ if date -v 1d > /dev/null 2>&1
+ then
+ ax_cv_prog_date_bsd=yes
+ fi
+ ])
+ AC_CACHE_CHECK([for date type], [ax_cv_prog_date_type], [
+ ax_cv_prog_date_type=unknown
+ if test "x${ax_cv_prog_date_gnu}" = "xyes"
+ then
+ ax_cv_prog_date_type=gnu
+ elif test "x${ax_cv_prog_date_bsd}" = "xyes"
+ then
+ ax_cv_prog_date_type=bsd
+ fi
+ ])
+ AS_VAR_IF([ax_cv_prog_date_gnu], [yes], [
+ AC_CACHE_CHECK([whether GNU date supports --date], [ax_cv_prog_date_gnu_date], [
+ ax_cv_prog_date_gnu_date=no
+ if date --date=@1512031231 > /dev/null 2>&1
+ then
+ ax_cv_prog_date_gnu_date=yes
+ fi
+ ])
+ AC_CACHE_CHECK([whether GNU date supports --utc], [ax_cv_prog_date_gnu_utc], [
+ ax_cv_prog_date_gnu_utc=no
+ if date --utc > /dev/null 2>&1
+ then
+ ax_cv_prog_date_gnu_utc=yes
+ fi
+ ])
+ ])
+ AS_VAR_IF([ax_cv_prog_date_bsd], [yes], [
+ AC_CACHE_CHECK([whether BSD date supports -r], [ax_cv_prog_date_bsd_date], [
+ ax_cv_prog_date_bsd_date=no
+ if date -r 1512031231 > /dev/null 2>&1
+ then
+ ax_cv_prog_date_bsd_date=yes
+ fi
+ ])
+ ])
+ AS_VAR_IF([ax_cv_prog_date_bsd], [yes], [
+ AC_CACHE_CHECK([whether BSD date supports -v], [ax_cv_prog_date_bsd_adjust], [
+ ax_cv_prog_date_bsd_adjust=no
+ if date -v 1d > /dev/null 2>&1
+ then
+ ax_cv_prog_date_bsd_adjust=yes
+ fi
+ ])
+ ])
+])dnl AX_PROG_DATE
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
new file mode 100644
index 0000000..5fbf9fe
--- /dev/null
+++ b/m4/ax_pthread.m4
@@ -0,0 +1,485 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+# This macro figures out how to build C programs using POSIX threads. It
+# sets the PTHREAD_LIBS output variable to the threads library and linker
+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+# flags that are needed. (The user can also force certain compiler
+# flags/libs to be tested by setting these environment variables.)
+#
+# Also sets PTHREAD_CC to any special C compiler that is needed for
+# multi-threaded programs (defaults to the value of CC otherwise). (This
+# is necessary on AIX to use the special cc_r compiler alias.)
+#
+# NOTE: You are assumed to not only compile your program with these flags,
+# but also to link with them as well. For example, you might link with
+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+# If you are only building threaded programs, you may wish to use these
+# variables in your default LIBS, CFLAGS, and CC:
+#
+# LIBS="$PTHREAD_LIBS $LIBS"
+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CC="$PTHREAD_CC"
+#
+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
+# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+# PTHREAD_CFLAGS.
+#
+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+# is not found. If ACTION-IF-FOUND is not specified, the default action
+# will define HAVE_PTHREAD.
+#
+# Please let the authors know if this macro fails on any platform, or if
+# you have any other suggestions or comments. This macro was based on work
+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
+# grateful for the helpful feedback of numerous users.
+#
+# Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
+#
+# 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 <https://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 24
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_PROG_SED])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on Tru64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
+ ax_pthread_save_CC="$CC"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
+ AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
+ AC_MSG_RESULT([$ax_pthread_ok])
+ if test "x$ax_pthread_ok" = "xno"; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ CC="$ax_pthread_save_CC"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
+# (Note: HP C rejects this with "bad form for `-t' option")
+# -pthreads: Solaris/gcc (Note: HP C also rejects)
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads and
+# -D_REENTRANT too), HP C (must be checked before -lpthread, which
+# is present but should not be used directly; and before -mthreads,
+# because the compiler interprets this as "-mt" + "-hreads")
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case $host_os in
+
+ freebsd*)
+
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+
+ ax_pthread_flags="-kthread lthread $ax_pthread_flags"
+ ;;
+
+ hpux*)
+
+ # From the cc(1) man page: "[-mt] Sets various -D flags to enable
+ # multi-threading and also sets -lpthread."
+
+ ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
+ ;;
+
+ openedition*)
+
+ # IBM z/OS requires a feature-test macro to be defined in order to
+ # enable POSIX threads at all, so give the user a hint if this is
+ # not set. (We don't define these ourselves, as they can affect
+ # other portions of the system API in unpredictable ways.)
+
+ AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
+ [
+# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
+ AX_PTHREAD_ZOS_MISSING
+# endif
+ ],
+ [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
+ ;;
+
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (N.B.: The stubs are missing
+ # pthread_cleanup_push, or rather a function called by this macro,
+ # so we could check for that, but who knows whether they'll stub
+ # that too in a future libc.) So we'll check first for the
+ # standard Solaris way of linking pthreads (-mt -lpthread).
+
+ ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
+ ;;
+esac
+
+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+
+AS_IF([test "x$GCC" = "xyes"],
+ [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
+
+# The presence of a feature test macro requesting re-entrant function
+# definitions is, on some systems, a strong hint that pthreads support is
+# correctly enabled
+
+case $host_os in
+ darwin* | hpux* | linux* | osf* | solaris*)
+ ax_pthread_check_macro="_REENTRANT"
+ ;;
+
+ aix*)
+ ax_pthread_check_macro="_THREAD_SAFE"
+ ;;
+
+ *)
+ ax_pthread_check_macro="--"
+ ;;
+esac
+AS_IF([test "x$ax_pthread_check_macro" = "x--"],
+ [ax_pthread_check_cond=0],
+ [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
+
+# Are we compiling with Clang?
+
+AC_CACHE_CHECK([whether $CC is Clang],
+ [ax_cv_PTHREAD_CLANG],
+ [ax_cv_PTHREAD_CLANG=no
+ # Note that Autoconf sets GCC=yes for Clang as well as GCC
+ if test "x$GCC" = "xyes"; then
+ AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
+ [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+# if defined(__clang__) && defined(__llvm__)
+ AX_PTHREAD_CC_IS_CLANG
+# endif
+ ],
+ [ax_cv_PTHREAD_CLANG=yes])
+ fi
+ ])
+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+
+ax_pthread_clang_warning=no
+
+# Clang needs special handling, because older versions handle the -pthread
+# option in a rather... idiosyncratic way
+
+if test "x$ax_pthread_clang" = "xyes"; then
+
+ # Clang takes -pthread; it has never supported any other flag
+
+ # (Note 1: This will need to be revisited if a system that Clang
+ # supports has POSIX threads in a separate library. This tends not
+ # to be the way of modern systems, but it's conceivable.)
+
+ # (Note 2: On some systems, notably Darwin, -pthread is not needed
+ # to get POSIX threads support; the API is always present and
+ # active. We could reasonably leave PTHREAD_CFLAGS empty. But
+ # -pthread does define _REENTRANT, and while the Darwin headers
+ # ignore this macro, third-party headers might not.)
+
+ PTHREAD_CFLAGS="-pthread"
+ PTHREAD_LIBS=
+
+ ax_pthread_ok=yes
+
+ # However, older versions of Clang make a point of warning the user
+ # that, in an invocation where only linking and no compilation is
+ # taking place, the -pthread option has no effect ("argument unused
+ # during compilation"). They expect -pthread to be passed in only
+ # when source code is being compiled.
+ #
+ # Problem is, this is at odds with the way Automake and most other
+ # C build frameworks function, which is that the same flags used in
+ # compilation (CFLAGS) are also used in linking. Many systems
+ # supported by AX_PTHREAD require exactly this for POSIX threads
+ # support, and in fact it is often not straightforward to specify a
+ # flag that is used only in the compilation phase and not in
+ # linking. Such a scenario is extremely rare in practice.
+ #
+ # Even though use of the -pthread flag in linking would only print
+ # a warning, this can be a nuisance for well-run software projects
+ # that build with -Werror. So if the active version of Clang has
+ # this misfeature, we search for an option to squash it.
+
+ AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
+ # Create an alternate version of $ac_link that compiles and
+ # links in two steps (.c -> .o, .o -> exe) instead of one
+ # (.c -> exe), because the warning occurs only in the second
+ # step
+ ax_pthread_save_ac_link="$ac_link"
+ ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
+ ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
+ ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
+ AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
+ CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
+ ac_link="$ax_pthread_save_ac_link"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+ [ac_link="$ax_pthread_2step_ac_link"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+ [break])
+ ])
+ done
+ ac_link="$ax_pthread_save_ac_link"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
+ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
+ ])
+
+ case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
+ no | unknown) ;;
+ *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
+ esac
+
+fi # $ax_pthread_clang = yes
+
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+ case $ax_pthread_try_flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -mt,pthread)
+ AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
+ PTHREAD_CFLAGS="-mt"
+ PTHREAD_LIBS="-lpthread"
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
+ PTHREAD_CFLAGS="$ax_pthread_try_flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+ AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
+ PTHREAD_LIBS="-l$ax_pthread_try_flag"
+ ;;
+ esac
+
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+# if $ax_pthread_check_cond
+# error "$ax_pthread_check_macro must be defined"
+# endif
+ static void routine(void *a) { a = 0; }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ AC_MSG_RESULT([$ax_pthread_ok])
+ AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = "xyes"; then
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_CACHE_CHECK([for joinable pthread attribute],
+ [ax_cv_PTHREAD_JOINABLE_ATTR],
+ [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
+ for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+ [int attr = $ax_pthread_attr; return attr /* ; */])],
+ [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
+ [])
+ done
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
+ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
+ test "x$ax_pthread_joinable_attr_defined" != "xyes"],
+ [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
+ [$ax_cv_PTHREAD_JOINABLE_ATTR],
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ ax_pthread_joinable_attr_defined=yes
+ ])
+
+ AC_CACHE_CHECK([whether more special flags are required for pthreads],
+ [ax_cv_PTHREAD_SPECIAL_FLAGS],
+ [ax_cv_PTHREAD_SPECIAL_FLAGS=no
+ case $host_os in
+ solaris*)
+ ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
+ ;;
+ esac
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
+ test "x$ax_pthread_special_flags_added" != "xyes"],
+ [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
+ ax_pthread_special_flags_added=yes])
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ [ax_cv_PTHREAD_PRIO_INHERIT],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+ [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
+ test "x$ax_pthread_prio_inherit_defined" != "xyes"],
+ [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
+ ax_pthread_prio_inherit_defined=yes
+ ])
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ # More AIX lossage: compile with *_r variant
+ if test "x$GCC" != "xyes"; then
+ case $host_os in
+ aix*)
+ AS_CASE(["x/$CC"],
+ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+ [#handle absolute path differently from PATH based program lookup
+ AS_CASE(["x$CC"],
+ [x/*],
+ [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+ [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+ ;;
+ esac
+ fi
+fi
+
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
+AC_SUBST([PTHREAD_LIBS])
+AC_SUBST([PTHREAD_CFLAGS])
+AC_SUBST([PTHREAD_CC])
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test "x$ax_pthread_ok" = "xyes"; then
+ ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
+ :
+else
+ ax_pthread_ok=no
+ $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
diff --git a/make/agentccheck.mk b/make/agentccheck.mk
new file mode 100644
index 0000000..e524883
--- /dev/null
+++ b/make/agentccheck.mk
@@ -0,0 +1,32 @@
+DATADIR:=$(abs_top_srcdir)/tests/data/metadata
+TEST_TARGET=$(filter-out $(TEST_TARGET_SKIP),$(TARGET))
+
+check: $(TEST_TARGET:%=%.xml-check) $(SYMTARGET:%=%.xml-check) $(TEST_TARGET:%=%.delay-check) $(TEST_TARGET:%=%.rng-check)
+delay-check: $(TEST_TARGET:%=%.delay-check) $(SYMTARGET:%=%.delay-check)
+xml-check: $(TEST_TARGET:%=%.xml-check) $(SYMTARGET:%=%.xml-check)
+xml-upload: $(TEST_TARGET:%=%.xml-upload) $(SYMTARGET:%=%.xml-upload)
+
+%.xml-check: %
+ $(eval INPUT=$(subst .xml-check,,$@))
+ $(eval TEMPFILE = $(shell mktemp))
+ ./$(INPUT) -o metadata > $(TEMPFILE)
+ diff $(TEMPFILE) $(DATADIR)/$(INPUT).xml
+ rm $(TEMPFILE)
+
+%.xml-upload: %
+ $(eval INPUT=$(subst .xml-upload,,$@))
+ ./$(INPUT) -o metadata > $(DATADIR)/$(INPUT).xml
+
+# If test will fail, rerun fence agents to show problems
+%.delay-check: %
+ $(eval INPUT=$(subst .delay-check,,$@))
+ test `/usr/bin/time -p ./$(INPUT) --delay 10 $(FENCE_TEST_ARGS) -- 2>&1 |\
+ awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}' | tail -n 1` -ge 1000 || \
+ /usr/bin/time -p ./$(INPUT) --delay 0 $(FENCE_TEST_ARGS) --
+
+%.rng-check: %
+ $(eval INPUT=$(subst .rng-check,,$@))
+ ./$(INPUT) -o metadata | \
+ xsltproc ${abs_top_srcdir}/lib/fence2rng.xsl - | \
+ sed -e 's/ rha:description=/ description=/g' -e 's/ rha:name=/ name=/g' | \
+ xmllint --nsclean --noout -;
diff --git a/make/agentpycheck.mk b/make/agentpycheck.mk
new file mode 100644
index 0000000..4044dba
--- /dev/null
+++ b/make/agentpycheck.mk
@@ -0,0 +1,44 @@
+DATADIR:=$(abs_top_srcdir)/tests/data/metadata
+AWK_VAL='BEGIN {store=-1} /name=".*_path"/ || /name=".*_file"/ {store=2} {if (store!=0) {print}; store--}'
+
+TEST_TARGET=$(filter-out $(TEST_TARGET_SKIP),$(TARGET))
+
+check: $(TEST_TARGET:%=%.xml-check) $(SYMTARGET:%=%.xml-check) $(TEST_TARGET:%=%.delay-check) $(TEST_TARGET:%=%.rng-check)
+delay-check: $(TEST_TARGET:%=%.delay-check) $(SYMTARGET:%=%.delay-check)
+xml-check: $(TEST_TARGET:%=%.xml-check) $(SYMTARGET:%=%.xml-check)
+xml-upload: $(TEST_TARGET:%=%.xml-upload) $(SYMTARGET:%=%.xml-upload)
+
+%.xml-check: %.8
+ $(eval INPUT=$(subst .xml-check,,$(@F)))
+ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \
+ TEMPFILE=$$(mktemp); \
+ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$$x -o metadata | $(AWK) $(AWK_VAL) > $$TEMPFILE && \
+ diff $$TEMPFILE $(DATADIR)/$$x.xml || exit 1 && \
+ rm $$TEMPFILE; \
+ done
+
+%.xml-upload: %.8
+ $(eval INPUT=$(subst .xml-upload,,$(@F)))
+ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \
+ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$$x -o metadata | $(AWK) $(AWK_VAL) > $(DATADIR)/$$x.xml; \
+ done
+
+# If test will fail, rerun fence agents to show problems
+%.delay-check: %
+ $(eval INPUT=$(subst .delay-check,,$(@F)))
+ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \
+ test `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \
+ sh -c "printf 'delay=10\n $(FENCE_TEST_ARGS)' | $(PYTHON) $(@D)/$$x" 2>&1 |\
+ awk -F"[. ]" -vOFS= '/real/ {print $$2,$$3}'` -ge 1000 || ( \
+ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib /usr/bin/time -p \
+ sh -c "printf 'delay=0\n $(FENCE_TEST_ARGS)' | $(PYTHON) $(@D)/$$x"; false ); \
+ done
+
+%.rng-check: %
+ $(eval INPUT=$(subst .rng-check,,$(@F)))
+ for x in $(INPUT) `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$(INPUT) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \
+ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@D)/$$x -o metadata | \
+ xsltproc ${abs_top_srcdir}/lib/fence2rng.xsl - | \
+ sed -e 's/ rha:description=/ description=/g' -e 's/ rha:name=/ name=/g' | \
+ xmllint --nsclean --noout -; \
+ done
diff --git a/make/fencebuild.mk b/make/fencebuild.mk
new file mode 100644
index 0000000..9a3c6d6
--- /dev/null
+++ b/make/fencebuild.mk
@@ -0,0 +1,84 @@
+define gen_agent_from_py
+ mkdir -p `dirname $@`
+ cat $(abs_srcdir)/$@.py | \
+ sed \
+ -e 's#@''PYTHON@#${PYTHON}#g' \
+ -e 's#@''RELEASE_VERSION@#${VERSION}#g' \
+ -e 's#@''FENCEAGENTSLIBDIR@#${FENCEAGENTSLIBDIR}#g' \
+ -e 's#@''LOGDIR@#${LOGDIR}#g' \
+ -e 's#@''SBINDIR@#${sbindir}#g' \
+ -e 's#@''LIBEXECDIR@#${libexecdir}#g' \
+ -e 's#@''FENCETMPDIR@#${FENCETMPDIR}#g' \
+ -e 's#@''IPMITOOL_PATH@#${IPMITOOL_PATH}#g' \
+ -e 's#@''OPENSTACK_PATH@#${OPENSTACK_PATH}#g' \
+ -e 's#@''AMTTOOL_PATH@#${AMTTOOL_PATH}#g' \
+ -e 's#@''GNUTLSCLI_PATH@#${GNUTLSCLI_PATH}#g' \
+ -e 's#@''COROSYNC_CMAPCTL_PATH@#${COROSYNC_CMAPCTL_PATH}#g' \
+ -e 's#@''SG_PERSIST_PATH@#${SG_PERSIST_PATH}#g' \
+ -e 's#@''SG_TURS_PATH@#${SG_TURS_PATH}#g' \
+ -e 's#@''VGS_PATH@#${VGS_PATH}#g' \
+ -e 's#@''SUDO_PATH@#${SUDO_PATH}#g' \
+ -e 's#@''SSH_PATH@#${SSH_PATH}#g' \
+ -e 's#@''TELNET_PATH@#${TELNET_PATH}#g' \
+ -e 's#@''MPATH_PATH@#${MPATH_PATH}#g' \
+ -e 's#@''SBD_PATH@#${SBD_PATH}#g' \
+ -e 's#@''STORE_PATH@#${CLUSTERVARRUN}#g' \
+ -e 's#@''SUDO_PATH@#${SUDO_PATH}#g' \
+ -e 's#@''SNMPWALK_PATH@#${SNMPWALK_PATH}#g' \
+ -e 's#@''SNMPSET_PATH@#${SNMPSET_PATH}#g' \
+ -e 's#@''SNMPGET_PATH@#${SNMPGET_PATH}#g' \
+ -e 's#@''NOVA_PATH@#${NOVA_PATH}#g' \
+ -e 's#@''POWERMAN_PATH@#${POWERMAN_PATH}#g' \
+ -e 's#@''PING_CMD@#${PING_CMD}#g' \
+ -e 's#@''PING6_CMD@#${PING6_CMD}#g' \
+ -e 's#@''PING4_CMD@#${PING4_CMD}#g' \
+ > $@
+
+ if [ 0 -eq `echo "$(@)" | grep fence_ > /dev/null 2>&1; echo $$?` ]; then \
+ PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(top_srcdir)/lib/check_used_options.py $@; \
+ else true ; fi
+
+ for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $(@) -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \
+ cp -f $(@) $(@D)/$$x; \
+ $(MAKE) $(@D)/$$x.8; \
+ done
+endef
+
+# dependency, one on one
+$(foreach t,$(TARGET),$(eval $(t) : $(t:=.py)))
+
+# rule
+$(TARGET): $(abs_top_builddir)/config.status
+ $(call gen_agent_from_py)
+
+clean-local: clean-man
+ rm -f $(CLEAN_TARGET:%.8=%) $(CLEAN_TARGET_ADDITIONAL) $(mpathdata_SCRIPTS) $(scsidata_SCRIPTS) */*.pyc *.pyc */*.wiki
+
+ if [ "$(abs_builddir)" = "$(abs_top_builddir)/lib" ]; then \
+ rm -rf $(TARGET) __pycache__; \
+ fi
+
+install-exec-hook: $(TARGET)
+ if [ -n "$(man8dir)" ]; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ fi
+ for p in $(TARGET); do \
+ dir=`dirname $$p`; \
+ for x in `PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"`; do \
+ echo " $(INSTALL_SCRIPT) $$dir/$$x '$(DESTDIR)$(sbindir)'"; \
+ $(INSTALL_SCRIPT) $$dir/$$x "$(DESTDIR)$(sbindir)" || exit $$?; \
+ echo " $(INSTALL_DATA) '$$dir/$$x.8' '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) "$$dir/$$x.8" "$(DESTDIR)$(man8dir)" || exit $$?; \
+ done; \
+ done
+
+uninstall-hook: $(TARGET)
+ files=`for p in $(TARGET); do \
+ for x in \`PYTHONPATH=$(abs_top_srcdir)/lib:$(abs_top_builddir)/lib $(PYTHON) $$p -o metadata | grep symlink | sed -e "s/.*\(fence.*\)\" .*/\1/g"\`; do \
+ echo " rm -f '$(DESTDIR)$(sbindir)/$$x'"; \
+ rm -f "$(DESTDIR)$(sbindir)/$$x"; \
+ echo " rm -f '$(DESTDIR)$(man8dir)/$$x.8'"; \
+ rm -f "$(DESTDIR)$(man8dir)/$$x.8"; \
+ done; \
+ done`
diff --git a/make/fenceman.mk b/make/fenceman.mk
new file mode 100644
index 0000000..3997b88
--- /dev/null
+++ b/make/fenceman.mk
@@ -0,0 +1,11 @@
+%.8: % $(top_srcdir)/lib/fence2man.xsl
+ set -e && \
+ PYTHONPATH=$(abs_srcdir)/lib:$(abs_builddir)/../lib:$(abs_builddir)/lib \
+ $(PYTHON) $* -o manpage > $(@D)/.$(@F).tmp && \
+ xmllint --noout --relaxng $(top_srcdir)/lib/metadata.rng $(@D)/.$(@F).tmp && \
+ xsltproc $(top_srcdir)/lib/fence2man.xsl $(@D)/.$(@F).tmp > $@
+ xsltproc $(top_srcdir)/lib/fence2wiki.xsl $(@D)/.$(@F).tmp | grep -v '<?xml' > $(@D)/$(@F:%.8=%.wiki)
+
+clean-man:
+ $(eval CLEAN_TARGET=$(shell find . -name "*.8" | grep -v "kdump/fence_kdump_send.8\|manual/fence_ack_manual.8\|virt/man/fence_xvm.8\|virt/man/fence_virt.8\|virt/man/fence_virtd.8"))
+ rm -f $(CLEAN_TARGET) */.*.8.tmp */*.wiki
diff --git a/make/git-version-gen b/make/git-version-gen
new file mode 100755
index 0000000..795a98b
--- /dev/null
+++ b/make/git-version-gen
@@ -0,0 +1,161 @@
+#!/bin/sh
+# Print a version string.
+scriptversion=2010-10-13.20; # UTC
+
+# Copyright (C) 2007-2010 Free Software Foundation, Inc.
+#
+# 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/>.
+
+# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
+# It may be run two ways:
+# - from a git repository in which the "git describe" command below
+# produces useful output (thus requiring at least one signed tag)
+# - from a non-git-repo directory containing a .tarball-version file, which
+# presumes this script is invoked like "./git-version-gen .tarball-version".
+
+# In order to use intra-version strings in your project, you will need two
+# separate generated version string files:
+#
+# .tarball-version - present only in a distribution tarball, and not in
+# a checked-out repository. Created with contents that were learned at
+# the last time autoconf was run, and used by git-version-gen. Must not
+# be present in either $(srcdir) or $(builddir) for git-version-gen to
+# give accurate answers during normal development with a checked out tree,
+# but must be present in a tarball when there is no version control system.
+# Therefore, it cannot be used in any dependencies. GNUmakefile has
+# hooks to force a reconfigure at distribution time to get the value
+# correct, without penalizing normal development with extra reconfigures.
+#
+# .version - present in a checked-out repository and in a distribution
+# tarball. Usable in dependencies, particularly for files that don't
+# want to depend on config.h but do want to track version changes.
+# Delete this file prior to any autoconf run where you want to rebuild
+# files to pick up a version string change; and leave it stale to
+# minimize rebuild time after unrelated changes to configure sources.
+#
+# It is probably wise to add these two files to .gitignore, so that you
+# don't accidentally commit either generated file.
+#
+# Use the following line in your configure.ac, so that $(VERSION) will
+# automatically be up-to-date each time configure is run (and note that
+# since configure.ac no longer includes a version string, Makefile rules
+# should not depend on configure.ac for version updates).
+#
+# AC_INIT([GNU project],
+# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
+# [bug-project@example])
+#
+# Then use the following lines in your Makefile.am, so that .version
+# will be present for dependencies, and so that .tarball-version will
+# exist in distribution tarballs.
+#
+# BUILT_SOURCES = $(top_srcdir)/.version
+# $(top_srcdir)/.version:
+# echo $(VERSION) > $@-t && mv $@-t $@
+# dist-hook:
+# echo $(VERSION) > $(distdir)/.tarball-version
+
+case $# in
+ 1|2) ;;
+ *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version" \
+ '[TAG-NORMALIZATION-SED-SCRIPT]'
+ exit 1;;
+esac
+
+tarball_version_file=$1
+tag_sed_script="${2:-s/x/x/}"
+nl='
+'
+
+# Avoid meddling by environment variable of the same name.
+v=
+
+# First see if there is a tarball-only version file.
+# then try "git describe", then default.
+if test -f $tarball_version_file
+then
+ v=`cat $tarball_version_file` || exit 1
+ case $v in
+ *$nl*) v= ;; # reject multi-line output
+ [0-9]*) ;;
+ *) v= ;;
+ esac
+ test -z "$v" \
+ && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
+fi
+
+if test -n "$v"
+then
+ : # use $v
+# Otherwise, if there is at least one git commit involving the working
+# directory, and "git describe" output looks sensible, use that to
+# derive a version string.
+elif test "`git log -1 --pretty=format:x . 2>&1`" = x \
+ && v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
+ || git describe --abbrev=4 HEAD 2>/dev/null` \
+ && v=`printf '%s\n' "$v" | sed "$tag_sed_script"` \
+ && case $v in
+ v[0-9]*) ;;
+ *) (exit 1) ;;
+ esac
+then
+ # Is this a new git that lists number of commits since the last
+ # tag or the previous older version that did not?
+ # Newer: v6.10-77-g0f8faeb
+ # Older: v6.10-g0f8faeb
+ case $v in
+ *-*-*) : git describe is okay three part flavor ;;
+ *-*)
+ : git describe is older two part flavor
+ # Recreate the number of commits and rewrite such that the
+ # result is the same as if we were using the newer version
+ # of git describe.
+ vtag=`echo "$v" | sed 's/-.*//'`
+ numcommits=`git rev-list "$vtag"..HEAD | wc -l`
+ v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
+ ;;
+ esac
+
+ # Change the first '-' to a '.', so version-comparing tools work properly.
+ # Remove the "g" in git describe's output string, to save a byte.
+ v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
+else
+ v=UNKNOWN
+fi
+
+v=`echo "$v" |sed 's/^v//'`
+
+# Don't declare a version "dirty" merely because a time stamp has changed.
+git update-index --refresh > /dev/null 2>&1
+
+dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
+case "$dirty" in
+ '') ;;
+ *) # Append the suffix only if there isn't one already.
+ case $v in
+ *-dirty) ;;
+ *) v="$v-dirty" ;;
+ esac ;;
+esac
+
+# Omit the trailing newline, so that m4_esyscmd can use the result directly.
+echo "$v" | tr -d "$nl"
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/make/gitlog-to-changelog b/make/gitlog-to-changelog
new file mode 100755
index 0000000..7660af5
--- /dev/null
+++ b/make/gitlog-to-changelog
@@ -0,0 +1,191 @@
+eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
+ & eval 'exec perl -wS "$0" $argv:q'
+ if 0;
+# Convert git log output to ChangeLog format.
+
+my $VERSION = '2009-10-30 13:46'; # UTC
+# The definition above must lie within the first 8 lines in order
+# for the Emacs time-stamp write hook (at end) to update it.
+# If you change this file with Emacs, please let the write hook
+# do its job. Otherwise, update this string manually.
+
+# Copyright (C) 2008-2010 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Written by Jim Meyering
+
+use strict;
+use warnings;
+use Getopt::Long;
+use POSIX qw(strftime);
+
+(my $ME = $0) =~ s|.*/||;
+
+# use File::Coda; # http://meyering.net/code/Coda/
+END {
+ defined fileno STDOUT or return;
+ close STDOUT and return;
+ warn "$ME: failed to close standard output: $!\n";
+ $? ||= 1;
+}
+
+sub usage ($)
+{
+ my ($exit_code) = @_;
+ my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
+ if ($exit_code != 0)
+ {
+ print $STREAM "Try `$ME --help' for more information.\n";
+ }
+ else
+ {
+ print $STREAM <<EOF;
+Usage: $ME [OPTIONS] [ARGS]
+
+Convert git log output to ChangeLog format. If present, any ARGS
+are passed to "git log". To avoid ARGS being parsed as options to
+$ME, they may be preceded by '--'.
+
+OPTIONS:
+
+ --since=DATE convert only the logs since DATE;
+ the default is to convert all log entries.
+ --format=FMT set format string for commit subject and body;
+ see 'man git-log' for the list of format metacharacters;
+ the default is '%s%n%b%n'
+
+ --help display this help and exit
+ --version output version information and exit
+
+EXAMPLE:
+
+ $ME --since=2008-01-01 > ChangeLog
+ $ME -- -n 5 foo > last-5-commits-to-branch-foo
+
+EOF
+ }
+ exit $exit_code;
+}
+
+# If the string $S is a well-behaved file name, simply return it.
+# If it contains white space, quotes, etc., quote it, and return the new string.
+sub shell_quote($)
+{
+ my ($s) = @_;
+ if ($s =~ m![^\w+/.,-]!)
+ {
+ # Convert each single quote to '\''
+ $s =~ s/\'/\'\\\'\'/g;
+ # Then single quote the string.
+ $s = "'$s'";
+ }
+ return $s;
+}
+
+sub quoted_cmd(@)
+{
+ return join (' ', map {shell_quote $_} @_);
+}
+
+{
+ my $since_date = '1970-01-01 UTC';
+ my $format_string = '%s%n%b%n';
+ GetOptions
+ (
+ help => sub { usage 0 },
+ version => sub { print "$ME version $VERSION\n"; exit },
+ 'since=s' => \$since_date,
+ 'format=s' => \$format_string,
+ ) or usage 1;
+
+ my @cmd = (qw (git log --log-size), "--since=$since_date",
+ '--pretty=format:%ct %an <%ae>%n%n'.$format_string, @ARGV);
+ open PIPE, '-|', @cmd
+ or die ("$ME: failed to run `". quoted_cmd (@cmd) ."': $!\n"
+ . "(Is your Git too old? Version 1.5.1 or later is required.)\n");
+
+ my $prev_date_line = '';
+ while (1)
+ {
+ defined (my $in = <PIPE>)
+ or last;
+ $in =~ /^log size (\d+)$/
+ or die "$ME:$.: Invalid line (expected log size):\n$in";
+ my $log_nbytes = $1;
+
+ my $log;
+ my $n_read = read PIPE, $log, $log_nbytes;
+ $n_read == $log_nbytes
+ or die "$ME:$.: unexpected EOF\n";
+
+ my @line = split "\n", $log;
+ my $author_line = shift @line;
+ defined $author_line
+ or die "$ME:$.: unexpected EOF\n";
+ $author_line =~ /^(\d+) (.*>)$/
+ or die "$ME:$.: Invalid line "
+ . "(expected date/author/email):\n$author_line\n";
+
+ my $date_line = sprintf "%s $2\n", strftime ("%F", localtime ($1));
+ # If this line would be the same as the previous date/name/email
+ # line, then arrange not to print it.
+ if ($date_line ne $prev_date_line)
+ {
+ $prev_date_line eq ''
+ or print "\n";
+ print $date_line;
+ }
+ $prev_date_line = $date_line;
+
+ # Omit "Signed-off-by..." lines.
+ @line = grep !/^Signed-off-by: .*>$/, @line;
+
+ # If there were any lines
+ if (@line == 0)
+ {
+ warn "$ME: warning: empty commit message:\n $date_line\n";
+ }
+ else
+ {
+ # Remove leading and trailing blank lines.
+ while ($line[0] =~ /^\s*$/) { shift @line; }
+ while ($line[$#line] =~ /^\s*$/) { pop @line; }
+
+ # Prefix each non-empty line with a TAB.
+ @line = map { length $_ ? "\t$_" : '' } @line;
+
+ print "\n", join ("\n", @line), "\n";
+ }
+
+ defined ($in = <PIPE>)
+ or last;
+ $in ne "\n"
+ and die "$ME:$.: unexpected line:\n$in";
+ }
+
+ close PIPE
+ or die "$ME: error closing pipe from " . quoted_cmd (@cmd) . "\n";
+ # FIXME-someday: include $PROCESS_STATUS in the diagnostic
+}
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "my $VERSION = '"
+# time-stamp-format: "%:y-%02m-%02d %02H:%02M"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "'; # UTC"
+# End:
diff --git a/make/release.mk b/make/release.mk
new file mode 100644
index 0000000..bf94495
--- /dev/null
+++ b/make/release.mk
@@ -0,0 +1,82 @@
+# to build official release tarballs, handle tagging and publish.
+
+project = fence-agents
+
+deliverables = $(project)-$(version).sha256 \
+ $(project)-$(version).tar.bz2 \
+ $(project)-$(version).tar.gz \
+ $(project)-$(version).tar.xz
+
+
+.PHONY: all
+all: tag tarballs
+
+
+.PHONY: checks
+checks:
+ifeq (,$(version))
+ @echo ERROR: need to define version=
+ @exit 1
+endif
+ @if [ ! -d .git ]; then \
+ echo This script needs to be executed from top level cluster git tree; \
+ exit 1; \
+ fi
+ @if [ -n "$$(git status --untracked-files=no --porcelain 2>/dev/null)" ]; then \
+ echo Stash or rollback the uncommitted changes in git first; \
+ exit 1; \
+ fi
+
+
+.PHONY: setup
+setup: checks
+ ./autogen.sh
+ ./configure
+ $(MAKE) maintainer-clean
+
+
+.PHONY: tag
+tag: setup ./tag-$(version)
+
+tag-$(version):
+ifeq (,$(release))
+ @echo Building test release $(version), no tagging
+ echo '$(version)' > .tarball-version
+else
+ # following will be captured by git-version-gen automatically
+ git tag -a -m "v$(version) release" v$(version) HEAD
+ @touch $@
+endif
+
+
+.PHONY: tarballs
+tarballs: tag
+ ./autogen.sh
+ ./configure
+ $(MAKE) distcheck
+
+
+.PHONY: sha256
+sha256: $(project)-$(version).sha256
+
+$(deliverables): tarballs
+
+$(project)-$(version).sha256:
+ # checksum anything from deliverables except for in-prep checksums file
+ sha256sum $(deliverables:$@=) | sort -k2 > $@
+
+
+.PHONY: publish
+publish:
+ifeq (,$(release))
+ @echo Building test release $(version), no publishing!
+else
+ git push --follow-tags origin
+ @echo Hey you! Yeah you, looking somewhere else!
+ @echo Remember to notify cluster-devel/RH and users/ClusterLabs MLs.
+endif
+
+
+.PHONY: clean
+clean:
+ rm -rf $(project)* tag-* .tarball-version
diff --git a/systemd/Makefile.am b/systemd/Makefile.am
new file mode 100644
index 0000000..aa3a016
--- /dev/null
+++ b/systemd/Makefile.am
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2017 Oyvind Albrigtsen
+#
+# 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
+
+if HAVE_SYSTEMD
+tmpfilesdir = $(SYSTEMD_TMPFILES_DIR)
+tmpfiles_DATA = fence-agents.conf
+endif
diff --git a/systemd/fence-agents.conf.in b/systemd/fence-agents.conf.in
new file mode 100644
index 0000000..4181287
--- /dev/null
+++ b/systemd/fence-agents.conf.in
@@ -0,0 +1 @@
+d @FENCETMPDIR@ 1755 root root
diff --git a/tests/actions.d/list.cfg b/tests/actions.d/list.cfg
new file mode 100644
index 0000000..b7ed552
--- /dev/null
+++ b/tests/actions.d/list.cfg
@@ -0,0 +1,2 @@
+name = "List plugs and check port 6"
+actions = [ { "command" : "list", "return_code" : "^0$" } ]
diff --git a/tests/actions.d/power-on-off.cfg b/tests/actions.d/power-on-off.cfg
new file mode 100644
index 0000000..d9df57a
--- /dev/null
+++ b/tests/actions.d/power-on-off.cfg
@@ -0,0 +1,2 @@
+name = "Power ON & OFF"
+actions = [ { "command" : "on", "return_code" : "^0$" }, { "command" : "status", "return_code" : "^0$" }, { "command" : "off", "return_code" : "^0$" }, { "command" : "status", "return_code" : "^2$" } ]
diff --git a/tests/actions.d/sleep.cfg b/tests/actions.d/sleep.cfg
new file mode 100644
index 0000000..c0fad72
--- /dev/null
+++ b/tests/actions.d/sleep.cfg
@@ -0,0 +1,2 @@
+name = "Pure Sleep"
+actions = [ { "command" : "sleep(1)", "return_code" : "^0$" }, { "command" : "sleep(3)", "return_code" : "^0$" }, { "command" : "sleep(5)", "return_code" : "^0$" } ]
diff --git a/tests/actions.d/status.cfg b/tests/actions.d/status.cfg
new file mode 100644
index 0000000..760f94b
--- /dev/null
+++ b/tests/actions.d/status.cfg
@@ -0,0 +1,2 @@
+name = "Simple Status"
+actions = [ { "command" : "status", "return_code" : "^[02]$" }, { "command" : "sleep(1)", "return_code" : "^0$" } ]
diff --git a/tests/data/metadata/fence_aliyun.xml b/tests/data/metadata/fence_aliyun.xml
new file mode 100644
index 0000000..56d7920
--- /dev/null
+++ b/tests/data/metadata/fence_aliyun.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_aliyun" shortdesc="Fence agent for Aliyun (Aliyun Web Services)" >
+<longdesc>fence_aliyun is an I/O Fencing agent for Aliyun</longdesc>
+<vendor-url>http://www.aliyun.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="region" unique="0" required="0">
+ <getopt mixed="-r, --region=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Region.</shortdesc>
+ </parameter>
+ <parameter name="access_key" unique="0" required="0">
+ <getopt mixed="-a, --access-key=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Access Key.</shortdesc>
+ </parameter>
+ <parameter name="secret_key" unique="0" required="0">
+ <getopt mixed="-s, --secret-key=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Secret Key.</shortdesc>
+ </parameter>
+ <parameter name="ram_role" unique="0" required="0">
+ <getopt mixed="--ram-role=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Ram Role.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="60" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_alom.xml b/tests/data/metadata/fence_alom.xml
new file mode 100644
index 0000000..6532ad6
--- /dev/null
+++ b/tests/data/metadata/fence_alom.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_alom" shortdesc="Fence agent for Sun ALOM" >
+<longdesc>fence_alom is an I/O Fencing agent which can be used with ALOM connected machines.</longdesc>
+<vendor-url>http://www.sun.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;sc\\&gt;\\ &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;sc\\&gt;\\ &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="22" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_amt.xml b/tests/data/metadata/fence_amt.xml
new file mode 100644
index 0000000..809c2df
--- /dev/null
+++ b/tests/data/metadata/fence_amt.xml
@@ -0,0 +1,188 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_amt" shortdesc="Fence agent for AMT" >
+<longdesc>fence_amt is an I/O Fencing agent which can be used with Intel AMT. This agent calls support software amttool(http://www.kraxel.org/cgit/amtterm/).</longdesc>
+<vendor-url>http://www.intel.com/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="boot_option" unique="0" required="0">
+ <getopt mixed="-b, --boot-option=[option]" />
+ <content type="select" >
+ <option value="pxe" />
+ <option value="hd" />
+ <option value="hdsafe" />
+ <option value="cd" />
+ <option value="diag" />
+ </content>
+ <shortdesc lang="en">Change the default boot behavior of the machine.</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="16994" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="amttool_path" unique="0" required="0">
+ <getopt mixed="--amttool-path=[path]" />
+ <shortdesc lang="en">Path to amttool binary</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_amt_ws.xml b/tests/data/metadata/fence_amt_ws.xml
new file mode 100644
index 0000000..97a2225
--- /dev/null
+++ b/tests/data/metadata/fence_amt_ws.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_amt_ws" shortdesc="Fence agent for AMT (WS)" >
+<longdesc>fence_amt_ws is an I/O Fencing agent which can be used with Intel AMT (WS). This agent requires the pywsman Python library which is included in OpenWSMAN. (http://openwsman.github.io/).</longdesc>
+<vendor-url>http://www.intel.com/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="boot_option" unique="0" required="0">
+ <getopt mixed="-b, --boot-option=[option]" />
+ <content type="select" >
+ <option value="pxe" />
+ <option value="hd" />
+ <option value="hdsafe" />
+ <option value="cd" />
+ <option value="diag" />
+ </content>
+ <shortdesc lang="en">Change the default boot behavior of the machine.</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="16992" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_apc.xml b/tests/data/metadata/fence_apc.xml
new file mode 100644
index 0000000..6081b1f
--- /dev/null
+++ b/tests/data/metadata/fence_apc.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_apc" shortdesc="Fence agent for APC over telnet/ssh" >
+<longdesc>fence_apc is an I/O Fencing agent which can be used with the APC network power switch. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.apc.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\n&gt;&apos;, &apos;\napc&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\n&gt;&apos;, &apos;\napc&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" default="-1 -c blowfish" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="switch" unique="0" required="0">
+ <getopt mixed="-s, --switch=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical switch number on device</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_apc_snmp.xml b/tests/data/metadata/fence_apc_snmp.xml
new file mode 100644
index 0000000..02efbb0
--- /dev/null
+++ b/tests/data/metadata/fence_apc_snmp.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_apc_snmp" shortdesc="Fence agent for APC, Tripplite PDU over SNMP" >
+<symlink name="fence_tripplite_snmp" shortdesc="Fence agent for Tripplife over SNMP"/>
+<longdesc>fence_apc_snmp is an I/O Fencing agent which can be used with the APC network power switch or Tripplite PDU devices.It logs into a device via SNMP and reboots a specified outlet. It supports SNMP v1, v2c, v3 with all combinations of authenticity/privacy settings.</longdesc>
+<vendor-url>http://www.apc.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" default="private" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" default="1" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_aws.xml b/tests/data/metadata/fence_aws.xml
new file mode 100644
index 0000000..76995ec
--- /dev/null
+++ b/tests/data/metadata/fence_aws.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_aws" shortdesc="Fence agent for AWS (Amazon Web Services)" >
+<longdesc>fence_aws is an I/O Fencing agent for AWS (Amazon WebServices). It uses the boto3 library to connect to AWS.
+
+boto3 can be configured with AWS CLI or by creating ~/.aws/credentials.
+For instructions see: https://boto3.readthedocs.io/en/latest/guide/quickstart.html#configuration</longdesc>
+<vendor-url>http://www.amazon.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="region" unique="0" required="0">
+ <getopt mixed="-r, --region=[region]" />
+ <content type="string" />
+ <shortdesc lang="en">Region.</shortdesc>
+ </parameter>
+ <parameter name="access_key" unique="0" required="0">
+ <getopt mixed="-a, --access-key=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Access Key.</shortdesc>
+ </parameter>
+ <parameter name="secret_key" unique="0" required="0">
+ <getopt mixed="-s, --secret-key=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Secret Key.</shortdesc>
+ </parameter>
+ <parameter name="filter" unique="0" required="0">
+ <getopt mixed="--filter=[key=value]" />
+ <content type="string" />
+ <shortdesc lang="en">Filter for list-action</shortdesc>
+ </parameter>
+ <parameter name="boto3_debug" unique="0" required="0">
+ <getopt mixed="-b, --boto3_debug=[option]" />
+ <content type="string" default="False" />
+ <shortdesc lang="en">Boto Lib debug</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="60" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_azure_arm.xml b/tests/data/metadata/fence_azure_arm.xml
new file mode 100644
index 0000000..c6e1f20
--- /dev/null
+++ b/tests/data/metadata/fence_azure_arm.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_azure_arm" shortdesc="Fence agent for Azure Resource Manager" >
+<longdesc>fence_azure_arm is an I/O Fencing agent for Azure Resource Manager. It uses Azure SDK for Python to connect to Azure.
+
+For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
+
+Username and password are application ID and authentication key from "App registrations".
+
+NOTE: NETWORK FENCING
+Network fencing requires an additional Subnet named "fence-subnet" for the Virtual Network using a Network Security Group with the following rules:
++-----------+-----+-------------------------+------+------+-----+-----+--------+
+| DIRECTION | PRI | NAME | PORT | PROT | SRC | DST | ACTION |
++-----------+-----+-------------------------+------+------+-----+-----+--------+
+| Inbound | 100 | FENCE_DENY_ALL_INBOUND | Any | Any | Any | Any | Deny |
+| Outbound | 100 | FENCE_DENY_ALL_OUTBOUND | Any | Any | Any | Any | Deny |
++-----------+-----+-------------------------+------+------+-----+-----+--------+
+
+When using network fencing the reboot-action will cause a quick-return once the network has been fenced (instead of waiting for the off-action to succeed). It will check the status during the monitor-action, and request power-on when the shutdown operation is complete.</longdesc>
+<vendor-url>http://www.microsoft.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[appid]" />
+ <content type="string" />
+ <shortdesc lang="en">Application ID</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[authkey]" />
+ <content type="string" />
+ <shortdesc lang="en">Authentication key</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[authkey]" />
+ <content type="string" />
+ <shortdesc lang="en">Authentication key</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[appid]" />
+ <content type="string" />
+ <shortdesc lang="en">Application ID</shortdesc>
+ </parameter>
+ <parameter name="resourceGroup" unique="0" required="0">
+ <getopt mixed="--resourceGroup=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Name of resource group. Metadata service is used if the value is not provided.</shortdesc>
+ </parameter>
+ <parameter name="tenantId" unique="0" required="0">
+ <getopt mixed="--tenantId=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Id of Azure Active Directory tenant.</shortdesc>
+ </parameter>
+ <parameter name="subscriptionId" unique="0" required="0">
+ <getopt mixed="--subscriptionId=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Id of the Azure subscription. Metadata service is used if the value is not provided.</shortdesc>
+ </parameter>
+ <parameter name="network-fencing" unique="0" required="0" deprecated="1">
+ <getopt mixed="--network-fencing" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use network fencing. See NOTE-section for configuration.</shortdesc>
+ </parameter>
+ <parameter name="network_fencing" unique="0" required="0" obsoletes="network-fencing">
+ <getopt mixed="--network-fencing" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use network fencing. See NOTE-section for configuration.</shortdesc>
+ </parameter>
+ <parameter name="msi" unique="0" required="0">
+ <getopt mixed="--msi" />
+ <content type="boolean" />
+ <shortdesc lang="en">Determines if Managed Service Identity should be used.</shortdesc>
+ </parameter>
+ <parameter name="cloud" unique="0" required="0">
+ <getopt mixed="--cloud=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Name of the cloud you want to use.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="150" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_bladecenter.xml b/tests/data/metadata/fence_bladecenter.xml
new file mode 100644
index 0000000..3cc4153
--- /dev/null
+++ b/tests/data/metadata/fence_bladecenter.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_bladecenter" shortdesc="Fence agent for IBM BladeCenter" >
+<longdesc>fence_bladecenter is an I/O Fencing agent which can be used with IBM Bladecenters with recent enough firmware that includes telnet support. It logs into a Brocade chasis via telnet or ssh and uses the command line interface to power on and off blades.</longdesc>
+<vendor-url>http://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;system&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;system&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="missing_as_off" unique="0" required="0">
+ <getopt mixed="--missing-as-off" />
+ <content type="boolean" />
+ <shortdesc lang="en">Missing port returns OFF instead of failure</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="10" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_brocade.xml b/tests/data/metadata/fence_brocade.xml
new file mode 100644
index 0000000..a78738d
--- /dev/null
+++ b/tests/data/metadata/fence_brocade.xml
@@ -0,0 +1,209 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_brocade" shortdesc="Fence agent for HP Brocade over telnet/ssh" >
+<longdesc>fence_brocade is an I/O Fencing agent which can be used with Brocade FC switches. It logs into a Brocade switch via telnet and disables a specified port. Disabling the port which a machine is connected to effectively fences that machine. Lengthy telnet connections to the switch should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions. After a fence operation has taken place the fenced machine can no longer connect to the Brocade FC switch. When the fenced machine is ready to be brought back into the GFS cluster (after reboot) the port on the Brocade FC switch needs to be enabled. This can be done by running fence_brocade and specifying the enable action</longdesc>
+<vendor-url>http://www.brocade.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;&gt; &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;&gt; &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="1"/>
+ <action name="off" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_cdu.xml b/tests/data/metadata/fence_cdu.xml
new file mode 100644
index 0000000..ef87d79
--- /dev/null
+++ b/tests/data/metadata/fence_cdu.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_cdu" shortdesc="Fence agent for a Sentry Switch CDU over telnet" >
+<longdesc>fence_cdu is an I/O Fencing agent which can be used with the Sentry Switch CDU. It logs into the device via telnet and power's on/off an outlet.</longdesc>
+<vendor-url>http://www.servertech.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="switch" unique="0" required="0">
+ <getopt mixed="-s, --switch=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical switch number on device</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_cisco_mds.xml b/tests/data/metadata/fence_cisco_mds.xml
new file mode 100644
index 0000000..829c9dc
--- /dev/null
+++ b/tests/data/metadata/fence_cisco_mds.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_cisco_mds" shortdesc="Fence agent for Cisco MDS" >
+<longdesc>fence_cisco_mds is an I/O Fencing agent which can be used with any Cisco MDS 9000 series with SNMP enabled device.</longdesc>
+<vendor-url>http://www.cisco.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="1"/>
+ <action name="off" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_cisco_ucs.xml b/tests/data/metadata/fence_cisco_ucs.xml
new file mode 100644
index 0000000..76d15e9
--- /dev/null
+++ b/tests/data/metadata/fence_cisco_ucs.xml
@@ -0,0 +1,197 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_cisco_ucs" shortdesc="Fence agent for Cisco UCS" >
+<longdesc>fence_cisco_ucs is an I/O Fencing agent which can be used with Cisco UCS to fence machines.</longdesc>
+<vendor-url>http://www.cisco.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="80" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="notls" unique="0" required="0">
+ <getopt mixed="-t, --notls" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="suborg" unique="0" required="0">
+ <getopt mixed="--suborg=[path]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Additional path needed to access suborganization</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="missing_as_off" unique="0" required="0">
+ <getopt mixed="--missing-as-off" />
+ <content type="boolean" />
+ <shortdesc lang="en">Missing port returns OFF instead of failure</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_compute.xml b/tests/data/metadata/fence_compute.xml
new file mode 100644
index 0000000..f6aa192
--- /dev/null
+++ b/tests/data/metadata/fence_compute.xml
@@ -0,0 +1,222 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_compute" shortdesc="Fence agent for the automatic resurrection of OpenStack compute instances" >
+<longdesc>Used to tell Nova that compute nodes are down and to reschedule flagged instances</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth_url" unique="0" required="0">
+ <getopt mixed="-k, --auth-url=[url]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Keystone Admin Auth URL</shortdesc>
+ </parameter>
+ <parameter name="endpoint_type" unique="0" required="0">
+ <getopt mixed="-e, --endpoint-type=[endpoint]" />
+ <content type="string" default="internalURL" />
+ <shortdesc lang="en">Nova Endpoint type</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="region_name" unique="0" required="0">
+ <getopt mixed="--region-name=[region]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Region Name</shortdesc>
+ </parameter>
+ <parameter name="tenant_name" unique="0" required="0">
+ <getopt mixed="-t, --tenant-name=[name]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Keystone Admin Tenant or v3 Project</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="insecure" unique="0" required="0">
+ <getopt mixed="--insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Allow Insecure TLS Requests</shortdesc>
+ </parameter>
+ <parameter name="project-domain" unique="0" required="0" deprecated="1">
+ <getopt mixed="-P, --project-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 Project Domain</shortdesc>
+ </parameter>
+ <parameter name="project_domain" unique="0" required="0" obsoletes="project-domain">
+ <getopt mixed="-P, --project-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 Project Domain</shortdesc>
+ </parameter>
+ <parameter name="user-domain" unique="0" required="0" deprecated="1">
+ <getopt mixed="-u, --user-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 User Domain</shortdesc>
+ </parameter>
+ <parameter name="user_domain" unique="0" required="0" obsoletes="user-domain">
+ <getopt mixed="-u, --user-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 User Domain</shortdesc>
+ </parameter>
+ <parameter name="domain" unique="0" required="0">
+ <getopt mixed="-d, --domain=[string]" />
+ <content type="string" />
+ <shortdesc lang="en">DNS domain in which hosts live</shortdesc>
+ </parameter>
+ <parameter name="instance_filtering" unique="0" required="0">
+ <getopt mixed="--instance-filtering" />
+ <content type="boolean" default="True" />
+ <shortdesc lang="en">Allow instances to be evacuated</shortdesc>
+ </parameter>
+ <parameter name="no_shared_storage" unique="0" required="0">
+ <getopt mixed="--no-shared-storage" />
+ <content type="boolean" default="False" />
+ <shortdesc lang="en">Disable functionality for dealing with shared storage</shortdesc>
+ </parameter>
+ <parameter name="record_only" unique="0" required="0">
+ <getopt mixed="--record-only" />
+ <content type="string" default="False" />
+ <shortdesc lang="en">Only record the target as needing evacuation</shortdesc>
+ </parameter>
+ <parameter name="compute-domain" unique="0" required="0" deprecated="1">
+ <getopt mixed="--compute-domain=[string]" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by domain</shortdesc>
+ </parameter>
+ <parameter name="compute_domain" unique="0" required="0" obsoletes="compute-domain">
+ <getopt mixed="--compute-domain=[string]" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by domain</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="180" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="1"/>
+ <action name="off" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_crosslink.xml b/tests/data/metadata/fence_crosslink.xml
new file mode 100644
index 0000000..1102b4e
--- /dev/null
+++ b/tests/data/metadata/fence_crosslink.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_crosslink" shortdesc="Fence agent for cross-link two-node clusters" >
+<longdesc>This agent helps two-node clusters to tackle the situation where one node lost power, cannot be fenced by telling pacemaker that if the node is not reachable over the crosslink cable, we can assume it is dead</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="crosscableip" unique="0" required="1">
+ <getopt mixed="-a, --crosscableip=[IP]" />
+ <content type="string" />
+ <shortdesc lang="en">Cross-cable IP</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="timeout" unique="0" required="0">
+ <getopt mixed="-T, --timeout=[seconds]" />
+ <content type="string" default="5" />
+ <shortdesc lang="en">No ICMP reply in 5 seconds -> Node is considered dead</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_cyberpower_ssh.xml b/tests/data/metadata/fence_cyberpower_ssh.xml
new file mode 100644
index 0000000..505db63
--- /dev/null
+++ b/tests/data/metadata/fence_cyberpower_ssh.xml
@@ -0,0 +1,206 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_cyberpower_ssh" shortdesc="Fence agent for CyberPower over ssh" >
+<longdesc>fence_cyberpower_ssh is an I/O Fencing agent which can be used with the CyberPower network power switch. It logs into device via ssh and reboots a specified outlet. Lengthy ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.cyberpower.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\n&gt;&apos;, &apos;\nCyberPower &gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\n&gt;&apos;, &apos;\nCyberPower &gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_docker.xml b/tests/data/metadata/fence_docker.xml
new file mode 100644
index 0000000..f685b11
--- /dev/null
+++ b/tests/data/metadata/fence_docker.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_docker" shortdesc="Fence agent for Docker" >
+<longdesc>fence_docker is I/O fencing agent which can be used with the Docker Engine containers. You can use this fence-agent without any authentication, or you can use TLS authentication (use --ssl option, more info about TLS authentication in docker: http://docs.docker.com/examples/https/).</longdesc>
+<vendor-url>www.docker.io</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="443" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="api_version" unique="0" required="0">
+ <getopt mixed="--api-version" />
+ <content type="string" default="1.11" />
+ <shortdesc lang="en">Version of Docker Remote API (default: 1.11)</shortdesc>
+ </parameter>
+ <parameter name="tlscacert" unique="0" required="0">
+ <getopt mixed="--tlscacert" />
+ <content type="string" />
+ <shortdesc lang="en">Path to CA certificate (PEM format) for TLS authentication. Required if --ssl option is used.</shortdesc>
+ </parameter>
+ <parameter name="tlscert" unique="0" required="0">
+ <getopt mixed="--tlscert" />
+ <content type="string" />
+ <shortdesc lang="en">Path to client certificate (PEM format) for TLS authentication. Required if --ssl option is used.</shortdesc>
+ </parameter>
+ <parameter name="tlskey" unique="0" required="0">
+ <getopt mixed="--tlskey" />
+ <content type="string" />
+ <shortdesc lang="en">Path to client key (PEM format) for TLS authentication. Required if --ssl option is used.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_drac.xml b/tests/data/metadata/fence_drac.xml
new file mode 100644
index 0000000..a991261
--- /dev/null
+++ b/tests/data/metadata/fence_drac.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_drac" shortdesc="I/O Fencing agent for Dell DRAC IV" >
+<longdesc>fence_drac is an I/O Fencing agent which can be used with the Dell Remote Access Card (DRAC). This card provides remote access to controlling power to a server. It logs into the DRAC through the telnet interface of the card. By default, the telnet interface is not enabled. To enable the interface, you will need to use the racadm command in the racser-devel rpm available from Dell. To enable telnet on the DRAC: [root]# racadm config -g cfgSerial -o cfgSerialTelnetEnable 1 [root]# racadm racreset </longdesc>
+<vendor-url>http://www.dell.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\[username\\]# &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\[username\\]# &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_drac5.xml b/tests/data/metadata/fence_drac5.xml
new file mode 100644
index 0000000..a0c73eb
--- /dev/null
+++ b/tests/data/metadata/fence_drac5.xml
@@ -0,0 +1,219 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_drac5" shortdesc="Fence agent for Dell DRAC CMC/5" >
+<longdesc>fence_drac5 is an I/O Fencing agent which can be used with the Dell Remote Access Card v5 or CMC (DRAC). This device provides remote access to controlling power to a server. It logs into the DRAC through the telnet/ssh interface of the card. By default, the telnet interface is not enabled.</longdesc>
+<vendor-url>http://www.dell.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\$&apos;, &apos;DRAC\\/MC:&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\$&apos;, &apos;DRAC\\/MC:&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="drac_version" unique="0" required="0">
+ <getopt mixed="-d, --drac-version=[version]" />
+ <content type="select" >
+ <option value="DRAC CMC" />
+ <option value="DRAC MC" />
+ <option value="DRAC 5" />
+ </content>
+ <shortdesc lang="en">Force DRAC version to use</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_dummy.xml b/tests/data/metadata/fence_dummy.xml
new file mode 100644
index 0000000..0651f5a
--- /dev/null
+++ b/tests/data/metadata/fence_dummy.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_dummy" shortdesc="Dummy fence agent" >
+<longdesc>fence_dummy</longdesc>
+<vendor-url>http://www.example.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="random_sleep_range" unique="0" required="0">
+ <getopt mixed="--random_sleep_range=[seconds]" />
+ <content type="string" />
+ <shortdesc lang="en">Issue a sleep between 1 and X seconds. Used for testing.</shortdesc>
+ </parameter>
+ <parameter name="status_file" unique="0" required="0">
+ <getopt mixed="--status-file=[file]" />
+ <shortdesc lang="en">File with status</shortdesc>
+ </parameter>
+ <parameter name="type" unique="0" required="0">
+ <getopt mixed="--type=[type]" />
+ <content type="string" default="file" />
+ <shortdesc lang="en">Type of the dummy fence agent</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_eaton_snmp.xml b/tests/data/metadata/fence_eaton_snmp.xml
new file mode 100644
index 0000000..1d89b52
--- /dev/null
+++ b/tests/data/metadata/fence_eaton_snmp.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_eaton_snmp" shortdesc="Fence agent for Eaton over SNMP" >
+<longdesc>fence_eaton_snmp is an I/O Fencing agent which can be used with the Eaton network power switch. It logs into a device via SNMP and reboots a specified outlet. It supports SNMP v1 and v3 with all combinations of authenticity/privacy settings.</longdesc>
+<vendor-url>http://powerquality.eaton.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" default="private" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" default="1" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ecloud.xml b/tests/data/metadata/fence_ecloud.xml
new file mode 100644
index 0000000..9721710
--- /dev/null
+++ b/tests/data/metadata/fence_ecloud.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ecloud" shortdesc="Fence Agent for ANS eCloud" >
+<longdesc>fence_ecloud is a fence agent for use with the ANS eCloud platform which is compatible with eCloud VPC and eCloud v1.</longdesc>
+<vendor-url>https://www.ans.co.uk</vendor-url>
+<parameters>
+ <parameter name="apikey" unique="0" required="1">
+ <getopt mixed="--apikey=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">API Key</shortdesc>
+ </parameter>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[instance]" />
+ <content type="string" />
+ <shortdesc lang="en">Instance ID (VPC) or server ID (v1)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[instance]" />
+ <content type="string" />
+ <shortdesc lang="en">Instance ID (VPC) or server ID (v1)</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_emerson.xml b/tests/data/metadata/fence_emerson.xml
new file mode 100644
index 0000000..1ed792e
--- /dev/null
+++ b/tests/data/metadata/fence_emerson.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_emerson" shortdesc="Fence agent for Emerson over SNMP" >
+<longdesc>fence_emerson is an I/O Fencing agent which can be used with MPX and MPH2 managed rack PDU.</longdesc>
+<vendor-url>http://www.emersonnetworkpower.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_eps.xml b/tests/data/metadata/fence_eps.xml
new file mode 100644
index 0000000..a8cf8ad
--- /dev/null
+++ b/tests/data/metadata/fence_eps.xml
@@ -0,0 +1,175 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_eps" shortdesc="Fence agent for ePowerSwitch" >
+<longdesc>fence_eps is an I/O Fencing agent which can be used with the ePowerSwitch 8M+ power switch to fence connected machines. Fence agent works ONLY on 8M+ device, because this is only one, which has support for hidden page feature.
+
+Agent basically works by connecting to hidden page and pass appropriate arguments to GET request. This means, that hidden page feature must be enabled and properly configured.</longdesc>
+<vendor-url>http://www.epowerswitch.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="hidden_page" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --page=[page]" />
+ <content type="string" default="hidden.htm" />
+ <shortdesc lang="en">Name of hidden page</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="80" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="page" unique="0" required="0" obsoletes="hidden_page">
+ <getopt mixed="-c, --page=[page]" />
+ <content type="string" default="hidden.htm" />
+ <shortdesc lang="en">Name of hidden page</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_evacuate.xml b/tests/data/metadata/fence_evacuate.xml
new file mode 100644
index 0000000..df2181e
--- /dev/null
+++ b/tests/data/metadata/fence_evacuate.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_evacuate" shortdesc="Fence agent for the automatic resurrection of OpenStack compute instances" >
+<longdesc>Used to reschedule flagged instances</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth_url" unique="0" required="0">
+ <getopt mixed="-k, --auth-url=[url]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Keystone Admin Auth URL</shortdesc>
+ </parameter>
+ <parameter name="endpoint_type" unique="0" required="0">
+ <getopt mixed="-e, --endpoint-type=[endpoint]" />
+ <content type="string" default="internalURL" />
+ <shortdesc lang="en">Nova Endpoint type</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="region_name" unique="0" required="0">
+ <getopt mixed="--region-name=[region]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Region Name</shortdesc>
+ </parameter>
+ <parameter name="tenant_name" unique="0" required="0">
+ <getopt mixed="-t, --tenant-name=[name]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Keystone Admin Tenant or v3 Project</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="insecure" unique="0" required="0">
+ <getopt mixed="--insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Allow Insecure TLS Requests</shortdesc>
+ </parameter>
+ <parameter name="project-domain" unique="0" required="0" deprecated="1">
+ <getopt mixed="-P, --project-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 Project Domain</shortdesc>
+ </parameter>
+ <parameter name="project_domain" unique="0" required="0" obsoletes="project-domain">
+ <getopt mixed="-P, --project-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 Project Domain</shortdesc>
+ </parameter>
+ <parameter name="user-domain" unique="0" required="0" deprecated="1">
+ <getopt mixed="-u, --user-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 User Domain</shortdesc>
+ </parameter>
+ <parameter name="user_domain" unique="0" required="0" obsoletes="user-domain">
+ <getopt mixed="-u, --user-domain=[name]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone v3 User Domain</shortdesc>
+ </parameter>
+ <parameter name="domain" unique="0" required="0">
+ <getopt mixed="-d, --domain=[string]" />
+ <content type="string" />
+ <shortdesc lang="en">DNS domain in which hosts live</shortdesc>
+ </parameter>
+ <parameter name="instance_filtering" unique="0" required="0">
+ <getopt mixed="--instance-filtering" />
+ <content type="boolean" default="True" />
+ <shortdesc lang="en">Allow instances to be evacuated</shortdesc>
+ </parameter>
+ <parameter name="no_shared_storage" unique="0" required="0">
+ <getopt mixed="--no-shared-storage" />
+ <content type="boolean" default="False" />
+ <shortdesc lang="en">Disable functionality for dealing with shared storage</shortdesc>
+ </parameter>
+ <parameter name="compute-domain" unique="0" required="0" deprecated="1">
+ <getopt mixed="--compute-domain=[string]" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by domain</shortdesc>
+ </parameter>
+ <parameter name="compute_domain" unique="0" required="0" obsoletes="compute-domain">
+ <getopt mixed="--compute-domain=[string]" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by domain</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="180" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_gce.xml b/tests/data/metadata/fence_gce.xml
new file mode 100644
index 0000000..2a89b16
--- /dev/null
+++ b/tests/data/metadata/fence_gce.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_gce" shortdesc="Fence agent for GCE (Google Cloud Engine)" >
+<longdesc>fence_gce is an I/O Fencing agent for GCE (Google Cloud Engine). It uses the googleapiclient library to connect to GCE.
+googleapiclient can be configured with Google SDK CLI or by executing 'gcloud auth application-default login'.
+For instructions see: https://cloud.google.com/compute/docs/tutorials/python-guide</longdesc>
+<vendor-url>http://cloud.google.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="cycle" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="zone" unique="0" required="0">
+ <getopt mixed="--zone=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Zone.</shortdesc>
+ </parameter>
+ <parameter name="project" unique="0" required="0">
+ <getopt mixed="--project=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Project ID.</shortdesc>
+ </parameter>
+ <parameter name="stackdriver-logging" unique="0" required="0" deprecated="1">
+ <getopt mixed="--stackdriver-logging" />
+ <content type="boolean" />
+ <shortdesc lang="en">Stackdriver-logging support.</shortdesc>
+ </parameter>
+ <parameter name="stackdriver_logging" unique="0" required="0" obsoletes="stackdriver-logging">
+ <getopt mixed="--stackdriver-logging" />
+ <content type="boolean" />
+ <shortdesc lang="en">Stackdriver-logging support.</shortdesc>
+ </parameter>
+ <parameter name="baremetalsolution" unique="0" required="0">
+ <getopt mixed="--baremetalsolution" />
+ <content type="boolean" />
+ <shortdesc lang="en">If enabled this is a bare metal offering from google.</shortdesc>
+ </parameter>
+ <parameter name="apitimeout" unique="0" required="0">
+ <getopt mixed="--apitimeout=[seconds]" />
+ <content type="second" default="60" />
+ <shortdesc lang="en">Timeout in seconds to use for API calls, default is 60.</shortdesc>
+ </parameter>
+ <parameter name="retries" unique="0" required="0">
+ <getopt mixed="--retries=[retries]" />
+ <content type="integer" default="3" />
+ <shortdesc lang="en">Number of retries on failure for API calls, default is 3.</shortdesc>
+ </parameter>
+ <parameter name="retrysleep" unique="0" required="0">
+ <getopt mixed="--retrysleep=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Time to sleep in seconds between API retries, default is 5.</shortdesc>
+ </parameter>
+ <parameter name="serviceaccount" unique="0" required="0">
+ <getopt mixed="--serviceaccount=[filename]" />
+ <content type="string" />
+ <shortdesc lang="en">Service Account to use for authentication to the google cloud APIs.</shortdesc>
+ </parameter>
+ <parameter name="plugzonemap" unique="0" required="0">
+ <getopt mixed="--plugzonemap=[plugzonemap]" />
+ <content type="string" />
+ <shortdesc lang="en">Comma separated zone map when fencing multiple plugs.</shortdesc>
+ </parameter>
+ <parameter name="proxyhost" unique="0" required="0">
+ <getopt mixed="--proxyhost=[proxy_host]" />
+ <content type="string" />
+ <shortdesc lang="en">If a proxy is used for internet access, the proxy host should be specified.</shortdesc>
+ </parameter>
+ <parameter name="proxyport" unique="0" required="0">
+ <getopt mixed="--proxyport=[proxy_port]" />
+ <content type="integer" />
+ <shortdesc lang="en">If a proxy is used for internet access, the proxy port should be specified.</shortdesc>
+ </parameter>
+ <parameter name="earlyexit" unique="0" required="0">
+ <getopt mixed="--earlyexit" />
+ <content type="boolean" />
+ <shortdesc lang="en">If an existing reset operation is detected, the fence agent will return before the operation completes with a 0 return code.</shortdesc>
+ </parameter>
+ <parameter name="warntimeout" unique="0" required="0">
+ <getopt mixed="--warntimeout=[warn_timeout]" />
+ <content type="second" />
+ <shortdesc lang="en">If the operation is not completed within the timeout, the cluster operations are allowed to continue.</shortdesc>
+ </parameter>
+ <parameter name="errortimeout" unique="0" required="0">
+ <getopt mixed="--errortimeout=[error_timeout]" />
+ <content type="second" />
+ <shortdesc lang="en">If the operation is not completed within the timeout, cluster is notified of the operation failure.</shortdesc>
+ </parameter>
+ <parameter name="runonwarn" unique="0" required="0">
+ <getopt mixed="--runonwarn=[run_on_warn]" />
+ <content type="string" />
+ <shortdesc lang="en">If a timeout would occur while running the agent, then the supplied command is run.</shortdesc>
+ </parameter>
+ <parameter name="runonfail" unique="0" required="0">
+ <getopt mixed="--runonfail=[run_on_fail]" />
+ <content type="string" />
+ <shortdesc lang="en">If a failure would occur while running the agent, then the supplied command is run.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="60" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_hds_cb.xml b/tests/data/metadata/fence_hds_cb.xml
new file mode 100644
index 0000000..e25d889
--- /dev/null
+++ b/tests/data/metadata/fence_hds_cb.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_hds_cb" shortdesc="Fence agent for Hitachi Compute Blade systems" >
+<longdesc>fence_hds_cb is an I/O Fencing agent which can be used with Hitachi Compute Blades with recent enough firmware that includes telnet support.</longdesc>
+<vendor-url>http://www.hds.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\) :&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\) :&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="missing_as_off" unique="0" required="0">
+ <getopt mixed="--missing-as-off" />
+ <content type="boolean" />
+ <shortdesc lang="en">Missing port returns OFF instead of failure</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_heuristics_ping.xml b/tests/data/metadata/fence_heuristics_ping.xml
new file mode 100644
index 0000000..b10189b
--- /dev/null
+++ b/tests/data/metadata/fence_heuristics_ping.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_heuristics_ping" shortdesc="Fence agent for ping-heuristic based fencing" >
+<longdesc>fence_heuristics_ping uses ping-heuristics to control execution of another fence agent on the same fencing level.
+
+This is not a fence agent by itself! Its only purpose is to enable/disable another fence agent that lives on the same fencing level but after fence_heuristics_ping.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="cycle" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="ping_count" unique="0" required="0">
+ <getopt mixed="--ping-count=[number]" />
+ <content type="string" default="10" />
+ <shortdesc lang="en">The number of ping-probes that is being sent per target</shortdesc>
+ </parameter>
+ <parameter name="ping_good_count" unique="0" required="0">
+ <getopt mixed="--ping-good-count=[number]" />
+ <content type="string" default="8" />
+ <shortdesc lang="en">The number of positive ping-probes required to account a target as available</shortdesc>
+ </parameter>
+ <parameter name="ping_interval" unique="0" required="0">
+ <getopt mixed="--ping-interval=[seconds]" />
+ <content type="string" default="1" />
+ <shortdesc lang="en">The interval in seconds between ping-probes</shortdesc>
+ </parameter>
+ <parameter name="ping_maxfail" unique="0" required="0">
+ <getopt mixed="--ping-maxfail=[number]" />
+ <content type="string" default="0" />
+ <shortdesc lang="en">The number of failed ping-targets to still account as overall success</shortdesc>
+ </parameter>
+ <parameter name="ping_targets" unique="0" required="1">
+ <getopt mixed="--ping-targets=tgt1,[inet6:]tgt2" />
+ <content type="string" default="" />
+ <shortdesc lang="en">A comma separated list of ping-targets (optionally prepended by 'inet:' or 'inet6:') to be probed</shortdesc>
+ </parameter>
+ <parameter name="ping_timeout" unique="0" required="0">
+ <getopt mixed="--ping-timeout=[seconds]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">The timeout in seconds till an individual ping-probe is accounted as lost</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_hpblade.xml b/tests/data/metadata/fence_hpblade.xml
new file mode 100644
index 0000000..0957fcd
--- /dev/null
+++ b/tests/data/metadata/fence_hpblade.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_hpblade" shortdesc="Fence agent for HP BladeSystem" >
+<longdesc>fence_hpblade is an I/O Fencing agent which can be used with HP BladeSystem and HP Integrity Superdome X. It logs into the onboard administrator of an enclosure via telnet or ssh and uses the command line interface to power blades or partitions on or off.</longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;c7000oa&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;c7000oa&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="10" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="missing_as_off" unique="0" required="0">
+ <getopt mixed="--missing-as-off" />
+ <content type="boolean" />
+ <shortdesc lang="en">Missing port returns OFF instead of failure</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ibm_powervs.xml b/tests/data/metadata/fence_ibm_powervs.xml
new file mode 100644
index 0000000..79878a9
--- /dev/null
+++ b/tests/data/metadata/fence_ibm_powervs.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ibm_powervs" shortdesc="Fence agent for IBM PowerVS" >
+<longdesc>fence_ibm_powervs is an I/O Fencing agent which can be used with IBM PowerVS to fence virtual machines.</longdesc>
+<vendor-url>https://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="api-type" unique="0" required="0" deprecated="1">
+ <getopt mixed="--api-type=[public|private]" />
+ <content type="string" default="private" />
+ <shortdesc lang="en">API-type (public|private)</shortdesc>
+ </parameter>
+ <parameter name="api_type" unique="0" required="0" obsoletes="api-type">
+ <getopt mixed="--api-type=[public|private]" />
+ <content type="string" default="private" />
+ <shortdesc lang="en">API-type (public|private)</shortdesc>
+ </parameter>
+ <parameter name="crn" unique="0" required="1">
+ <getopt mixed="--crn=[crn]" />
+ <content type="string" />
+ <shortdesc lang="en">CRN</shortdesc>
+ </parameter>
+ <parameter name="instance" unique="0" required="1">
+ <getopt mixed="--instance=[instance]" />
+ <content type="string" />
+ <shortdesc lang="en">PowerVS Instance</shortdesc>
+ </parameter>
+ <parameter name="proxy" unique="0" required="0">
+ <getopt mixed="--proxy=[http://&lt;URL&gt;:&lt;PORT&gt;]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Network proxy</shortdesc>
+ </parameter>
+ <parameter name="region" unique="0" required="1">
+ <getopt mixed="--region=[region]" />
+ <content type="string" />
+ <shortdesc lang="en">Region</shortdesc>
+ </parameter>
+ <parameter name="token" unique="0" required="1">
+ <getopt mixed="--token=[token]" />
+ <content type="string" />
+ <shortdesc lang="en">API Token</shortdesc>
+ </parameter>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="30" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="500" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ibm_vpc.xml b/tests/data/metadata/fence_ibm_vpc.xml
new file mode 100644
index 0000000..fe29ffb
--- /dev/null
+++ b/tests/data/metadata/fence_ibm_vpc.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ibm_vpc" shortdesc="Fence agent for IBM Cloud VPC" >
+<longdesc>fence_ibm_vpc is an I/O Fencing agent which can be used with IBM Cloud VPC to fence virtual machines.</longdesc>
+<vendor-url>https://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="apikey" unique="0" required="1">
+ <getopt mixed="--apikey=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">API Key</shortdesc>
+ </parameter>
+ <parameter name="limit" unique="0" required="0">
+ <getopt mixed="--limit=[number]" />
+ <content type="string" default="50" />
+ <shortdesc lang="en">Number of nodes returned by API</shortdesc>
+ </parameter>
+ <parameter name="proxy" unique="0" required="0">
+ <getopt mixed="--proxy=[http://&lt;URL&gt;:&lt;PORT&gt;]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">Network proxy</shortdesc>
+ </parameter>
+ <parameter name="region" unique="0" required="1">
+ <getopt mixed="--region=[region]" />
+ <content type="string" />
+ <shortdesc lang="en">Region</shortdesc>
+ </parameter>
+ <parameter name="token_file" unique="0" required="0">
+ <getopt mixed="--token-file=[path]" />
+ <shortdesc lang="en">Path to the token cache file</shortdesc>
+ </parameter>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="30" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="15" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ibmblade.xml b/tests/data/metadata/fence_ibmblade.xml
new file mode 100644
index 0000000..3286ca6
--- /dev/null
+++ b/tests/data/metadata/fence_ibmblade.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ibmblade" shortdesc="Fence agent for IBM BladeCenter over SNMP" >
+<longdesc>fence_ibmblade is an I/O Fencing agent which can be used with IBM BladeCenter chassis. It issues SNMP Set request to BladeCenter chassis, rebooting, powering up or down the specified Blade Server.</longdesc>
+<vendor-url>http://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" default="1" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ibmz.xml b/tests/data/metadata/fence_ibmz.xml
new file mode 100644
index 0000000..ba74fa6
--- /dev/null
+++ b/tests/data/metadata/fence_ibmz.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ibmz" shortdesc="Fence agent for IBM z LPARs" >
+<longdesc>fence_ibmz is a power fencing agent which uses the HMC Web Services API to fence IBM z LPARs.</longdesc>
+<vendor-url>http://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="6794" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug id in the format cpc-name/partition-name (case-sensitive)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug id in the format cpc-name/partition-name (case-sensitive)</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="connect_retries" unique="0" required="0">
+ <getopt mixed="--connect-retries=[number]" />
+ <content type="integer" default="3" />
+ <shortdesc lang="en">How many times to retry on connection errors</shortdesc>
+ </parameter>
+ <parameter name="connect_timeout" unique="0" required="0">
+ <getopt mixed="--connect-timeout=[seconds]" />
+ <content type="second" default="30" />
+ <shortdesc lang="en">How long to wait to establish a connection</shortdesc>
+ </parameter>
+ <parameter name="operation_timeout" unique="0" required="0">
+ <getopt mixed="--operation-timeout=[seconds]" />
+ <content type="second" default="900" />
+ <shortdesc lang="en">How long to wait for power operation to complete</shortdesc>
+ </parameter>
+ <parameter name="read_retries" unique="0" required="0">
+ <getopt mixed="--read-retries=[number]" />
+ <content type="integer" default="3" />
+ <shortdesc lang="en">How many times to retry on read errors</shortdesc>
+ </parameter>
+ <parameter name="read_timeout" unique="0" required="0">
+ <getopt mixed="--read-timeout=[seconds]" />
+ <content type="second" default="300" />
+ <shortdesc lang="en">How long to wait for server data</shortdesc>
+ </parameter>
+ <parameter name="load_on_activate" unique="0" required="0">
+ <getopt mixed="--load-on-activate" />
+ <content type="boolean" />
+ <shortdesc lang="en">Rely on the HMC to perform a load operation on activation</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="300" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_idrac.xml b/tests/data/metadata/fence_idrac.xml
new file mode 100644
index 0000000..2d48764
--- /dev/null
+++ b/tests/data/metadata/fence_idrac.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_idrac" shortdesc="Fence agent for IPMI" >
+<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>
+<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>
+<symlink name="fence_ilo5" shortdesc="Fence agent for HP iLO5"/>
+<symlink name="fence_ipmilanplus" shortdesc="Fence agent for IPMIv2 lanplus"/>
+<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>
+<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>
+<longdesc>fence_ipmilan is an I/O Fencing agentwhich can be used with machines controlled by IPMI.This agent calls support software ipmitool (http://ipmitool.sf.net/). WARNING! This fence agent might report success before the node is powered off. You should use -m/method onoff if your fence device works correctly with that option.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-A, --auth=[auth]" />
+ <content type="select" >
+ <option value="md5" />
+ <option value="password" />
+ <option value="none" />
+ </content>
+ <shortdesc lang="en">IPMI Lan Auth type.</shortdesc>
+ </parameter>
+ <parameter name="cipher" unique="0" required="0">
+ <getopt mixed="-C, --cipher=[cipher]" />
+ <content type="string" />
+ <shortdesc lang="en">Ciphersuite to use (same as ipmitool -C parameter)</shortdesc>
+ </parameter>
+ <parameter name="hexadecimal_kg" unique="0" required="0">
+ <getopt mixed="--hexadecimal-kg=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Hexadecimal-encoded Kg key for IPMIv2 authentication</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="623" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="lanplus" unique="0" required="0">
+ <getopt mixed="-P, --lanplus" />
+ <content type="boolean" default="0" />
+ <shortdesc lang="en">Use Lanplus to improve security of connection</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="privlvl" unique="0" required="0">
+ <getopt mixed="-L, --privlvl=[level]" />
+ <content type="select" default="administrator" >
+ <option value="callback" />
+ <option value="user" />
+ <option value="operator" />
+ <option value="administrator" />
+ </content>
+ <shortdesc lang="en">Privilege level on IPMI device</shortdesc>
+ </parameter>
+ <parameter name="target" unique="0" required="0">
+ <getopt mixed="--target=[targetaddress]" />
+ <content type="string" />
+ <shortdesc lang="en">Bridge IPMI requests to the remote target address</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_path" unique="0" required="0">
+ <getopt mixed="--ipmitool-path=[path]" />
+ <shortdesc lang="en">Path to ipmitool binary</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_timeout" unique="0" required="0">
+ <getopt mixed="--ipmitool-timeout=[timeout]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">Timeout (sec) for IPMI operation</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ifmib.xml b/tests/data/metadata/fence_ifmib.xml
new file mode 100644
index 0000000..4b56e23
--- /dev/null
+++ b/tests/data/metadata/fence_ifmib.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ifmib" shortdesc="Fence agent for IF MIB" >
+<longdesc>fence_ifmib is an I/O Fencing agent which can be used with any SNMP IF-MIB capable device.
+
+It was written with managed ethernet switches in mind, in order to fence iSCSI SAN connections. However, there are many devices that support the IF-MIB interface. The agent uses IF-MIB::ifAdminStatus to control the state of an interface.</longdesc>
+<vendor-url>http://www.ietf.org/wg/concluded/ifmib.html</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" default="2c" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="1"/>
+ <action name="off" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo.xml b/tests/data/metadata/fence_ilo.xml
new file mode 100644
index 0000000..0bac03c
--- /dev/null
+++ b/tests/data/metadata/fence_ilo.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo" shortdesc="Fence agent for HP iLO" >
+<symlink name="fence_ilo2" shortdesc="Fence agent for HP iLO2"/>
+<longdesc>fence_ilo is an I/O Fencing agent used for HP servers with the Integrated Light Out (iLO) PCI card.The agent opens an SSL connection to the iLO card. Once the SSL connection is established, the agent is able to communicate with the iLO card through an XML stream.</longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="443" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="notls" unique="0" required="0">
+ <getopt mixed="-t, --notls" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="ribcl" unique="0" required="0" deprecated="1">
+ <getopt mixed="-r, --ribcl-version=[version]" />
+ <content type="string" />
+ <shortdesc lang="en">Force ribcl version to use</shortdesc>
+ </parameter>
+ <parameter name="ribcl_version" unique="0" required="0" obsoletes="ribcl">
+ <getopt mixed="-r, --ribcl-version=[version]" />
+ <content type="string" />
+ <shortdesc lang="en">Force ribcl version to use</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="tls1.0" unique="0" required="0">
+ <getopt mixed="--tls1.0" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force TLS1.0. This should only be used for devices that do not support TLS1.1 and up.</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="10" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="3" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo2.xml b/tests/data/metadata/fence_ilo2.xml
new file mode 100644
index 0000000..3d954a3
--- /dev/null
+++ b/tests/data/metadata/fence_ilo2.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo2" shortdesc="Fence agent for HP iLO" >
+<symlink name="fence_ilo2" shortdesc="Fence agent for HP iLO2"/>
+<longdesc>fence_ilo is an I/O Fencing agent used for HP servers with the Integrated Light Out (iLO) PCI card.The agent opens an SSL connection to the iLO card. Once the SSL connection is established, the agent is able to communicate with the iLO card through an XML stream.</longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="443" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="notls" unique="0" required="0">
+ <getopt mixed="-t, --notls" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="ribcl" unique="0" required="0" deprecated="1">
+ <getopt mixed="-r, --ribcl-version=[version]" />
+ <content type="string" />
+ <shortdesc lang="en">Force ribcl version to use</shortdesc>
+ </parameter>
+ <parameter name="ribcl_version" unique="0" required="0" obsoletes="ribcl">
+ <getopt mixed="-r, --ribcl-version=[version]" />
+ <content type="string" />
+ <shortdesc lang="en">Force ribcl version to use</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="tls1.0" unique="0" required="0">
+ <getopt mixed="--tls1.0" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force TLS1.0. This should only be used for devices that do not support TLS1.1 and up.</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="10" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="3" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo3.xml b/tests/data/metadata/fence_ilo3.xml
new file mode 100644
index 0000000..0567b53
--- /dev/null
+++ b/tests/data/metadata/fence_ilo3.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo3" shortdesc="Fence agent for IPMI" >
+<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>
+<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>
+<symlink name="fence_ilo5" shortdesc="Fence agent for HP iLO5"/>
+<symlink name="fence_ipmilanplus" shortdesc="Fence agent for IPMIv2 lanplus"/>
+<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>
+<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>
+<longdesc>fence_ipmilan is an I/O Fencing agentwhich can be used with machines controlled by IPMI.This agent calls support software ipmitool (http://ipmitool.sf.net/). WARNING! This fence agent might report success before the node is powered off. You should use -m/method onoff if your fence device works correctly with that option.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-A, --auth=[auth]" />
+ <content type="select" >
+ <option value="md5" />
+ <option value="password" />
+ <option value="none" />
+ </content>
+ <shortdesc lang="en">IPMI Lan Auth type.</shortdesc>
+ </parameter>
+ <parameter name="cipher" unique="0" required="0">
+ <getopt mixed="-C, --cipher=[cipher]" />
+ <content type="string" />
+ <shortdesc lang="en">Ciphersuite to use (same as ipmitool -C parameter)</shortdesc>
+ </parameter>
+ <parameter name="hexadecimal_kg" unique="0" required="0">
+ <getopt mixed="--hexadecimal-kg=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Hexadecimal-encoded Kg key for IPMIv2 authentication</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="623" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="lanplus" unique="0" required="0">
+ <getopt mixed="-P, --lanplus" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use Lanplus to improve security of connection</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="privlvl" unique="0" required="0">
+ <getopt mixed="-L, --privlvl=[level]" />
+ <content type="select" default="administrator" >
+ <option value="callback" />
+ <option value="user" />
+ <option value="operator" />
+ <option value="administrator" />
+ </content>
+ <shortdesc lang="en">Privilege level on IPMI device</shortdesc>
+ </parameter>
+ <parameter name="target" unique="0" required="0">
+ <getopt mixed="--target=[targetaddress]" />
+ <content type="string" />
+ <shortdesc lang="en">Bridge IPMI requests to the remote target address</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_path" unique="0" required="0">
+ <getopt mixed="--ipmitool-path=[path]" />
+ <shortdesc lang="en">Path to ipmitool binary</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="4" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_timeout" unique="0" required="0">
+ <getopt mixed="--ipmitool-timeout=[timeout]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">Timeout (sec) for IPMI operation</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo3_ssh.xml b/tests/data/metadata/fence_ilo3_ssh.xml
new file mode 100644
index 0000000..e2a2566
--- /dev/null
+++ b/tests/data/metadata/fence_ilo3_ssh.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo3_ssh" shortdesc="Fence agent for HP iLO over SSH" >
+<symlink name="fence_ilo3_ssh" shortdesc="Fence agent for HP iLO3 over SSH"/>
+<symlink name="fence_ilo4_ssh" shortdesc="Fence agent for HP iLO4 over SSH"/>
+<symlink name="fence_ilo5_ssh" shortdesc="Fence agent for HP iLO5 over SSH"/>
+<longdesc>fence_ilo_ssh is a fence agent that connects to iLO device. It logs into device via ssh and reboot a specified outlet.
+
+WARNING: The monitor-action is prone to timeouts. Use the fence_ilo-equivalent to avoid this issue.</longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo4.xml b/tests/data/metadata/fence_ilo4.xml
new file mode 100644
index 0000000..647bb10
--- /dev/null
+++ b/tests/data/metadata/fence_ilo4.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo4" shortdesc="Fence agent for IPMI" >
+<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>
+<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>
+<symlink name="fence_ilo5" shortdesc="Fence agent for HP iLO5"/>
+<symlink name="fence_ipmilanplus" shortdesc="Fence agent for IPMIv2 lanplus"/>
+<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>
+<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>
+<longdesc>fence_ipmilan is an I/O Fencing agentwhich can be used with machines controlled by IPMI.This agent calls support software ipmitool (http://ipmitool.sf.net/). WARNING! This fence agent might report success before the node is powered off. You should use -m/method onoff if your fence device works correctly with that option.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-A, --auth=[auth]" />
+ <content type="select" >
+ <option value="md5" />
+ <option value="password" />
+ <option value="none" />
+ </content>
+ <shortdesc lang="en">IPMI Lan Auth type.</shortdesc>
+ </parameter>
+ <parameter name="cipher" unique="0" required="0">
+ <getopt mixed="-C, --cipher=[cipher]" />
+ <content type="string" />
+ <shortdesc lang="en">Ciphersuite to use (same as ipmitool -C parameter)</shortdesc>
+ </parameter>
+ <parameter name="hexadecimal_kg" unique="0" required="0">
+ <getopt mixed="--hexadecimal-kg=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Hexadecimal-encoded Kg key for IPMIv2 authentication</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="623" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="lanplus" unique="0" required="0">
+ <getopt mixed="-P, --lanplus" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use Lanplus to improve security of connection</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="privlvl" unique="0" required="0">
+ <getopt mixed="-L, --privlvl=[level]" />
+ <content type="select" default="administrator" >
+ <option value="callback" />
+ <option value="user" />
+ <option value="operator" />
+ <option value="administrator" />
+ </content>
+ <shortdesc lang="en">Privilege level on IPMI device</shortdesc>
+ </parameter>
+ <parameter name="target" unique="0" required="0">
+ <getopt mixed="--target=[targetaddress]" />
+ <content type="string" />
+ <shortdesc lang="en">Bridge IPMI requests to the remote target address</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_path" unique="0" required="0">
+ <getopt mixed="--ipmitool-path=[path]" />
+ <shortdesc lang="en">Path to ipmitool binary</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_timeout" unique="0" required="0">
+ <getopt mixed="--ipmitool-timeout=[timeout]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">Timeout (sec) for IPMI operation</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo4_ssh.xml b/tests/data/metadata/fence_ilo4_ssh.xml
new file mode 100644
index 0000000..4fd6b2e
--- /dev/null
+++ b/tests/data/metadata/fence_ilo4_ssh.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo4_ssh" shortdesc="Fence agent for HP iLO over SSH" >
+<symlink name="fence_ilo3_ssh" shortdesc="Fence agent for HP iLO3 over SSH"/>
+<symlink name="fence_ilo4_ssh" shortdesc="Fence agent for HP iLO4 over SSH"/>
+<symlink name="fence_ilo5_ssh" shortdesc="Fence agent for HP iLO5 over SSH"/>
+<longdesc>fence_ilo_ssh is a fence agent that connects to iLO device. It logs into device via ssh and reboot a specified outlet.
+
+WARNING: The monitor-action is prone to timeouts. Use the fence_ilo-equivalent to avoid this issue.</longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo5.xml b/tests/data/metadata/fence_ilo5.xml
new file mode 100644
index 0000000..6c99db2
--- /dev/null
+++ b/tests/data/metadata/fence_ilo5.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo5" shortdesc="Fence agent for IPMI" >
+<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>
+<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>
+<symlink name="fence_ilo5" shortdesc="Fence agent for HP iLO5"/>
+<symlink name="fence_ipmilanplus" shortdesc="Fence agent for IPMIv2 lanplus"/>
+<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>
+<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>
+<longdesc>fence_ipmilan is an I/O Fencing agentwhich can be used with machines controlled by IPMI.This agent calls support software ipmitool (http://ipmitool.sf.net/). WARNING! This fence agent might report success before the node is powered off. You should use -m/method onoff if your fence device works correctly with that option.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-A, --auth=[auth]" />
+ <content type="select" >
+ <option value="md5" />
+ <option value="password" />
+ <option value="none" />
+ </content>
+ <shortdesc lang="en">IPMI Lan Auth type.</shortdesc>
+ </parameter>
+ <parameter name="cipher" unique="0" required="0">
+ <getopt mixed="-C, --cipher=[cipher]" />
+ <content type="string" />
+ <shortdesc lang="en">Ciphersuite to use (same as ipmitool -C parameter)</shortdesc>
+ </parameter>
+ <parameter name="hexadecimal_kg" unique="0" required="0">
+ <getopt mixed="--hexadecimal-kg=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Hexadecimal-encoded Kg key for IPMIv2 authentication</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="623" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="lanplus" unique="0" required="0">
+ <getopt mixed="-P, --lanplus" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use Lanplus to improve security of connection</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="privlvl" unique="0" required="0">
+ <getopt mixed="-L, --privlvl=[level]" />
+ <content type="select" default="administrator" >
+ <option value="callback" />
+ <option value="user" />
+ <option value="operator" />
+ <option value="administrator" />
+ </content>
+ <shortdesc lang="en">Privilege level on IPMI device</shortdesc>
+ </parameter>
+ <parameter name="target" unique="0" required="0">
+ <getopt mixed="--target=[targetaddress]" />
+ <content type="string" />
+ <shortdesc lang="en">Bridge IPMI requests to the remote target address</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_path" unique="0" required="0">
+ <getopt mixed="--ipmitool-path=[path]" />
+ <shortdesc lang="en">Path to ipmitool binary</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_timeout" unique="0" required="0">
+ <getopt mixed="--ipmitool-timeout=[timeout]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">Timeout (sec) for IPMI operation</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo5_ssh.xml b/tests/data/metadata/fence_ilo5_ssh.xml
new file mode 100644
index 0000000..036aec5
--- /dev/null
+++ b/tests/data/metadata/fence_ilo5_ssh.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo5_ssh" shortdesc="Fence agent for HP iLO over SSH" >
+<symlink name="fence_ilo3_ssh" shortdesc="Fence agent for HP iLO3 over SSH"/>
+<symlink name="fence_ilo4_ssh" shortdesc="Fence agent for HP iLO4 over SSH"/>
+<symlink name="fence_ilo5_ssh" shortdesc="Fence agent for HP iLO5 over SSH"/>
+<longdesc>fence_ilo_ssh is a fence agent that connects to iLO device. It logs into device via ssh and reboot a specified outlet.
+
+WARNING: The monitor-action is prone to timeouts. Use the fence_ilo-equivalent to avoid this issue.</longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo_moonshot.xml b/tests/data/metadata/fence_ilo_moonshot.xml
new file mode 100644
index 0000000..c88c592
--- /dev/null
+++ b/tests/data/metadata/fence_ilo_moonshot.xml
@@ -0,0 +1,206 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo_moonshot" shortdesc="Fence agent for HP Moonshot iLO" >
+<longdesc></longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="22" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo_mp.xml b/tests/data/metadata/fence_ilo_mp.xml
new file mode 100644
index 0000000..7d4fd22
--- /dev/null
+++ b/tests/data/metadata/fence_ilo_mp.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo_mp" shortdesc="Fence agent for HP iLO MP" >
+<longdesc></longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ilo_ssh.xml b/tests/data/metadata/fence_ilo_ssh.xml
new file mode 100644
index 0000000..2e1cb84
--- /dev/null
+++ b/tests/data/metadata/fence_ilo_ssh.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ilo_ssh" shortdesc="Fence agent for HP iLO over SSH" >
+<symlink name="fence_ilo3_ssh" shortdesc="Fence agent for HP iLO3 over SSH"/>
+<symlink name="fence_ilo4_ssh" shortdesc="Fence agent for HP iLO4 over SSH"/>
+<symlink name="fence_ilo5_ssh" shortdesc="Fence agent for HP iLO5 over SSH"/>
+<longdesc>fence_ilo_ssh is a fence agent that connects to iLO device. It logs into device via ssh and reboot a specified outlet.
+
+WARNING: The monitor-action is prone to timeouts. Use the fence_ilo-equivalent to avoid this issue.</longdesc>
+<vendor-url>http://www.hp.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;MP&gt;&apos;, &apos;hpiLO-&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_imm.xml b/tests/data/metadata/fence_imm.xml
new file mode 100644
index 0000000..5c5bf91
--- /dev/null
+++ b/tests/data/metadata/fence_imm.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_imm" shortdesc="Fence agent for IPMI" >
+<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>
+<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>
+<symlink name="fence_ilo5" shortdesc="Fence agent for HP iLO5"/>
+<symlink name="fence_ipmilanplus" shortdesc="Fence agent for IPMIv2 lanplus"/>
+<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>
+<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>
+<longdesc>fence_ipmilan is an I/O Fencing agentwhich can be used with machines controlled by IPMI.This agent calls support software ipmitool (http://ipmitool.sf.net/). WARNING! This fence agent might report success before the node is powered off. You should use -m/method onoff if your fence device works correctly with that option.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-A, --auth=[auth]" />
+ <content type="select" >
+ <option value="md5" />
+ <option value="password" />
+ <option value="none" />
+ </content>
+ <shortdesc lang="en">IPMI Lan Auth type.</shortdesc>
+ </parameter>
+ <parameter name="cipher" unique="0" required="0">
+ <getopt mixed="-C, --cipher=[cipher]" />
+ <content type="string" />
+ <shortdesc lang="en">Ciphersuite to use (same as ipmitool -C parameter)</shortdesc>
+ </parameter>
+ <parameter name="hexadecimal_kg" unique="0" required="0">
+ <getopt mixed="--hexadecimal-kg=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Hexadecimal-encoded Kg key for IPMIv2 authentication</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="623" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="lanplus" unique="0" required="0">
+ <getopt mixed="-P, --lanplus" />
+ <content type="boolean" default="0" />
+ <shortdesc lang="en">Use Lanplus to improve security of connection</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="privlvl" unique="0" required="0">
+ <getopt mixed="-L, --privlvl=[level]" />
+ <content type="select" default="administrator" >
+ <option value="callback" />
+ <option value="user" />
+ <option value="operator" />
+ <option value="administrator" />
+ </content>
+ <shortdesc lang="en">Privilege level on IPMI device</shortdesc>
+ </parameter>
+ <parameter name="target" unique="0" required="0">
+ <getopt mixed="--target=[targetaddress]" />
+ <content type="string" />
+ <shortdesc lang="en">Bridge IPMI requests to the remote target address</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_path" unique="0" required="0">
+ <getopt mixed="--ipmitool-path=[path]" />
+ <shortdesc lang="en">Path to ipmitool binary</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_timeout" unique="0" required="0">
+ <getopt mixed="--ipmitool-timeout=[timeout]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">Timeout (sec) for IPMI operation</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_intelmodular.xml b/tests/data/metadata/fence_intelmodular.xml
new file mode 100644
index 0000000..5dad0d0
--- /dev/null
+++ b/tests/data/metadata/fence_intelmodular.xml
@@ -0,0 +1,226 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_intelmodular" shortdesc="Fence agent for Intel Modular" >
+<longdesc>fence_intelmodular is an I/O Fencing agent which can be used with Intel Modular device (tested on Intel MFSYS25, should work with MFSYS35 as well).
+
+Note: Since firmware update version 2.7, SNMP v2 write support is removed, and replaced by SNMP v3 support. So agent now has default SNMP version 3. If you are using older firmware, please supply -d for command line and snmp_version option for your cluster.conf.</longdesc>
+<vendor-url>http://www.intel.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ipdu.xml b/tests/data/metadata/fence_ipdu.xml
new file mode 100644
index 0000000..22024a7
--- /dev/null
+++ b/tests/data/metadata/fence_ipdu.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ipdu" shortdesc="Fence agent for iPDU over SNMP" >
+<longdesc>fence_ipdu is an I/O Fencing agent which can be used with the IBM iPDU network power switch. It logs into a device via SNMP and reboots a specified outlet. It supports SNMP v3 with all combinations of authenticity/privacy settings.</longdesc>
+<vendor-url>http://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" default="private" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" default="3" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ipmilan.xml b/tests/data/metadata/fence_ipmilan.xml
new file mode 100644
index 0000000..a31afcf
--- /dev/null
+++ b/tests/data/metadata/fence_ipmilan.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ipmilan" shortdesc="Fence agent for IPMI" >
+<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>
+<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>
+<symlink name="fence_ilo5" shortdesc="Fence agent for HP iLO5"/>
+<symlink name="fence_ipmilanplus" shortdesc="Fence agent for IPMIv2 lanplus"/>
+<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>
+<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>
+<longdesc>fence_ipmilan is an I/O Fencing agentwhich can be used with machines controlled by IPMI.This agent calls support software ipmitool (http://ipmitool.sf.net/). WARNING! This fence agent might report success before the node is powered off. You should use -m/method onoff if your fence device works correctly with that option.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-A, --auth=[auth]" />
+ <content type="select" >
+ <option value="md5" />
+ <option value="password" />
+ <option value="none" />
+ </content>
+ <shortdesc lang="en">IPMI Lan Auth type.</shortdesc>
+ </parameter>
+ <parameter name="cipher" unique="0" required="0">
+ <getopt mixed="-C, --cipher=[cipher]" />
+ <content type="string" />
+ <shortdesc lang="en">Ciphersuite to use (same as ipmitool -C parameter)</shortdesc>
+ </parameter>
+ <parameter name="hexadecimal_kg" unique="0" required="0">
+ <getopt mixed="--hexadecimal-kg=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Hexadecimal-encoded Kg key for IPMIv2 authentication</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="623" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="lanplus" unique="0" required="0">
+ <getopt mixed="-P, --lanplus" />
+ <content type="boolean" default="0" />
+ <shortdesc lang="en">Use Lanplus to improve security of connection</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="privlvl" unique="0" required="0">
+ <getopt mixed="-L, --privlvl=[level]" />
+ <content type="select" default="administrator" >
+ <option value="callback" />
+ <option value="user" />
+ <option value="operator" />
+ <option value="administrator" />
+ </content>
+ <shortdesc lang="en">Privilege level on IPMI device</shortdesc>
+ </parameter>
+ <parameter name="target" unique="0" required="0">
+ <getopt mixed="--target=[targetaddress]" />
+ <content type="string" />
+ <shortdesc lang="en">Bridge IPMI requests to the remote target address</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_path" unique="0" required="0">
+ <getopt mixed="--ipmitool-path=[path]" />
+ <shortdesc lang="en">Path to ipmitool binary</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_timeout" unique="0" required="0">
+ <getopt mixed="--ipmitool-timeout=[timeout]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">Timeout (sec) for IPMI operation</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ipmilanplus.xml b/tests/data/metadata/fence_ipmilanplus.xml
new file mode 100644
index 0000000..19c2529
--- /dev/null
+++ b/tests/data/metadata/fence_ipmilanplus.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ipmilanplus" shortdesc="Fence agent for IPMI" >
+<symlink name="fence_ilo3" shortdesc="Fence agent for HP iLO3"/>
+<symlink name="fence_ilo4" shortdesc="Fence agent for HP iLO4"/>
+<symlink name="fence_ilo5" shortdesc="Fence agent for HP iLO5"/>
+<symlink name="fence_ipmilanplus" shortdesc="Fence agent for IPMIv2 lanplus"/>
+<symlink name="fence_imm" shortdesc="Fence agent for IBM Integrated Management Module"/>
+<symlink name="fence_idrac" shortdesc="Fence agent for Dell iDRAC"/>
+<longdesc>fence_ipmilan is an I/O Fencing agentwhich can be used with machines controlled by IPMI.This agent calls support software ipmitool (http://ipmitool.sf.net/). WARNING! This fence agent might report success before the node is powered off. You should use -m/method onoff if your fence device works correctly with that option.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-A, --auth=[auth]" />
+ <content type="select" >
+ <option value="md5" />
+ <option value="password" />
+ <option value="none" />
+ </content>
+ <shortdesc lang="en">IPMI Lan Auth type.</shortdesc>
+ </parameter>
+ <parameter name="cipher" unique="0" required="0">
+ <getopt mixed="-C, --cipher=[cipher]" />
+ <content type="string" />
+ <shortdesc lang="en">Ciphersuite to use (same as ipmitool -C parameter)</shortdesc>
+ </parameter>
+ <parameter name="hexadecimal_kg" unique="0" required="0">
+ <getopt mixed="--hexadecimal-kg=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Hexadecimal-encoded Kg key for IPMIv2 authentication</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="623" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="lanplus" unique="0" required="0">
+ <getopt mixed="-P, --lanplus" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use Lanplus to improve security of connection</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="privlvl" unique="0" required="0">
+ <getopt mixed="-L, --privlvl=[level]" />
+ <content type="select" default="administrator" >
+ <option value="callback" />
+ <option value="user" />
+ <option value="operator" />
+ <option value="administrator" />
+ </content>
+ <shortdesc lang="en">Privilege level on IPMI device</shortdesc>
+ </parameter>
+ <parameter name="target" unique="0" required="0">
+ <getopt mixed="--target=[targetaddress]" />
+ <content type="string" />
+ <shortdesc lang="en">Bridge IPMI requests to the remote target address</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_path" unique="0" required="0">
+ <getopt mixed="--ipmitool-path=[path]" />
+ <shortdesc lang="en">Path to ipmitool binary</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="ipmitool_timeout" unique="0" required="0">
+ <getopt mixed="--ipmitool-timeout=[timeout]" />
+ <content type="string" default="2" />
+ <shortdesc lang="en">Timeout (sec) for IPMI operation</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ironic.xml b/tests/data/metadata/fence_ironic.xml
new file mode 100644
index 0000000..813b037
--- /dev/null
+++ b/tests/data/metadata/fence_ironic.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ironic" shortdesc="Fence agent for OpenStack's Ironic (Bare Metal as a service) service" >
+<longdesc>fence_ironic is a Fencing agent which can be used with machines controlled by the Ironic service. This agent calls the openstack CLI. WARNING! This fence agent is not intended for production use. Relying on a functional ironic service for fencing is not a good design choice.</longdesc>
+<vendor-url>https://wiki.openstack.org/wiki/Ironic</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="auth-url" unique="0" required="1" deprecated="1">
+ <getopt mixed="--auth-url=[authurl]" />
+ <content type="string" />
+ <shortdesc lang="en">Keystone Admin Auth URL</shortdesc>
+ </parameter>
+ <parameter name="auth_url" unique="0" required="1" obsoletes="auth-url">
+ <getopt mixed="--auth-url=[authurl]" />
+ <content type="string" />
+ <shortdesc lang="en">Keystone Admin Auth URL</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="tenant-name" unique="0" required="0" deprecated="1">
+ <getopt mixed="-t, --tenant-name=[tenant]" />
+ <content type="string" default="admin" />
+ <shortdesc lang="en">Keystone Admin Tenant</shortdesc>
+ </parameter>
+ <parameter name="tenant_name" unique="0" required="0" obsoletes="tenant-name">
+ <getopt mixed="-t, --tenant-name=[tenant]" />
+ <content type="string" default="admin" />
+ <shortdesc lang="en">Keystone Admin Tenant</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="openstack-path" unique="0" required="0" deprecated="1">
+ <getopt mixed="--openstack-path=[path]" />
+ <content type="string" default="/usr/bin/openstack" />
+ <shortdesc lang="en">Path to the OpenStack binary</shortdesc>
+ </parameter>
+ <parameter name="openstack_path" unique="0" required="0" obsoletes="openstack-path">
+ <getopt mixed="--openstack-path=[path]" />
+ <shortdesc lang="en">Path to the OpenStack binary</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_kdump.xml b/tests/data/metadata/fence_kdump.xml
new file mode 100644
index 0000000..aa08538
--- /dev/null
+++ b/tests/data/metadata/fence_kdump.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_kdump" shortdesc="fencing agent for use with kdump crash recovery service">
+<longdesc>fence_kdump is an I/O fencing agent to be used with the kdump
+crash recovery service. When the fence_kdump agent is invoked,
+it will listen for a message from the failed node that acknowledges
+that the failed node it executing the kdump crash kernel.
+Note that fence_kdump is not a replacement for traditional
+fencing methods. The fence_kdump agent can only detect that a
+node has entered the kdump crash recovery service. This allows the
+kdump crash recovery service complete without being preempted by
+traditional power fencing methods.
+
+Note: the "off" action listen for message from failed node that
+acknowledges node has entered kdump crash recovery service. If a valid
+message is received from the failed node, the node is considered to be
+fenced and the agent returns success. Failure to receive a valid
+message from the failed node in the given timeout period results in
+fencing failure. When multiple node names/IP addresses are specified
+a single valid message is sufficient for success. This is useful when
+single node can send message via several different IP addresses.
+</longdesc>
+<vendor-url>http://www.kernel.org/pub/linux/utils/kernel/kexec/</vendor-url>
+<parameters>
+ <parameter name="nodename" unique="0" required="0">
+ <getopt mixed="-n, --nodename=NODE[,NODE...]" />
+ <content type="string" />
+ <shortdesc lang="en">List of names or IP addresses of node to be fenced. This option is
+required for the "off" action. Multiple values separated by commas
+can be specified. All values must be of same IP network family.</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-p, --ipport=PORT" />
+ <content type="string" default="7410" />
+ <shortdesc lang="en">IP port number that the fence_kdump agent will use to listen for
+messages.</shortdesc>
+ </parameter>
+ <parameter name="family" unique="0" required="0">
+ <getopt mixed="-f, --family=FAMILY" />
+ <content type="string" default="auto" />
+ <shortdesc lang="en">IP network family. Force the fence_kdump agent to use a specific
+family. The value for FAMILY can be "auto", "ipv4", or
+"ipv6".</shortdesc>
+ </parameter>
+ <parameter name="action" unique="0" required="0">
+ <getopt mixed="-o, --action=ACTION" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action to perform. The value for ACTION can be either
+"off" or "metadata".</shortdesc>
+ </parameter>
+ <parameter name="timeout" unique="0" required="0">
+ <getopt mixed="-t, --timeout=TIMEOUT" />
+ <content type="string" default="60" />
+ <shortdesc lang="en">Number of seconds to wait for message from failed node. If no message
+is received within TIMEOUT seconds, the fence_kdump agent
+returns failure.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Print verbose output</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Print version</shortdesc>
+ </parameter>
+ <parameter name="usage" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Print usage</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="off" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_kubevirt.xml b/tests/data/metadata/fence_kubevirt.xml
new file mode 100644
index 0000000..e6b42aa
--- /dev/null
+++ b/tests/data/metadata/fence_kubevirt.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_kubevirt" shortdesc="Fence agent for KubeVirt" >
+<longdesc>fence_kubevirt is an I/O Fencing agent for KubeVirt.</longdesc>
+<vendor-url>https://kubevirt.io/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="namespace" unique="0" required="0">
+ <getopt mixed="--namespace=[namespace]" />
+ <content type="string" />
+ <shortdesc lang="en">Namespace of the KubeVirt machine.</shortdesc>
+ </parameter>
+ <parameter name="kubeconfig" unique="0" required="0">
+ <getopt mixed="--kubeconfig=[kubeconfig]" />
+ <content type="string" />
+ <shortdesc lang="en">Kubeconfig file path</shortdesc>
+ </parameter>
+ <parameter name="apiversion" unique="0" required="0">
+ <getopt mixed="--apiversion=[apiversion]" />
+ <content type="string" default="kubevirt.io/v1" />
+ <shortdesc lang="en">Version of the KubeVirt API.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="40" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ldom.xml b/tests/data/metadata/fence_ldom.xml
new file mode 100644
index 0000000..59facad
--- /dev/null
+++ b/tests/data/metadata/fence_ldom.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ldom" shortdesc="Fence agent for Sun LDOM" >
+<longdesc>fence_ldom is an I/O Fencing agent which can be used with LDoms virtual machines. This agent works so, that run ldm command on host machine. So ldm must be directly runnable.
+
+Very useful parameter is -c (or cmd_prompt in stdin mode). This must be set to something, what is displayed after successful login to host machine. Default string is space on end of string (default for root in bash). But (for example) csh use ], so in that case you must use parameter -c with argument ]. Very similar situation is, if you use bash and login to host machine with other user than root. Than prompt is $, so again, you must use parameter -c.</longdesc>
+<vendor-url>http://www.sun.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\ $&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\ $&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="22" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_lindypdu.xml b/tests/data/metadata/fence_lindypdu.xml
new file mode 100644
index 0000000..56f81f4
--- /dev/null
+++ b/tests/data/metadata/fence_lindypdu.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_lindypdu" shortdesc="Fence agent for Lindy over SNMP" >
+<longdesc>fence_lindypdu is an I/O Fencing agent which can be used with the Lindy PDU network power switch. It logs into a device via SNMP and reboots a specified outlet. It supports SNMP v1 with all combinations of authenticity/privacy settings.</longdesc>
+<vendor-url>http://www.lindy.co.uk</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" default="public" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" default="1" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="switch" unique="0" required="0">
+ <getopt mixed="-s, --switch=[id]" />
+ <content type="string" default="1" />
+ <shortdesc lang="en">Physical switch number on device</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_lpar.xml b/tests/data/metadata/fence_lpar.xml
new file mode 100644
index 0000000..22f12dc
--- /dev/null
+++ b/tests/data/metadata/fence_lpar.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_lpar" shortdesc="Fence agent for IBM LPAR" >
+<longdesc></longdesc>
+<vendor-url>http://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;:~&gt;&apos;, &apos;]\\$&apos;, &apos;\\$ &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;:~&gt;&apos;, &apos;]\\$&apos;, &apos;\\$ &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="hmc_version" unique="0" required="0">
+ <getopt mixed="-H, --hmc-version=[version]" />
+ <content type="select" default="4" >
+ <option value="3" />
+ <option value="4" />
+ <option value="ivm" />
+ </content>
+ <shortdesc lang="en">Force HMC version to use</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="22" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="managed" unique="0" required="1">
+ <getopt mixed="-s, --managed=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Managed system name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="15" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_mpath.xml b/tests/data/metadata/fence_mpath.xml
new file mode 100644
index 0000000..e22d3a1
--- /dev/null
+++ b/tests/data/metadata/fence_mpath.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_mpath" shortdesc="Fence agent for multipath persistent reservation" >
+<longdesc>fence_mpath is an I/O fencing agent that uses SCSI-3 persistent reservations to control access multipath devices. Underlying devices must support SCSI-3 persistent reservations (SPC-3 or greater) as well as the "preempt-and-abort" subcommand.
+The fence_mpath agent works by having a unique key for each node that has to be set in /etc/multipath.conf. Once registered, a single node will become the reservation holder by creating a "write exclusive, registrants only" reservation on the device(s). The result is that only registered nodes may write to the device(s). When a node failure occurs, the fence_mpath agent will remove the key belonging to the failed node from the device(s). The failed node will no longer be able to write to the device(s). A manual reboot is required.
+
+When used as a watchdog device you can define e.g. retry=1, retry-sleep=2 and verbose=yes parameters in /etc/sysconfig/stonith if you have issues with it failing.</longdesc>
+<vendor-url>https://www.sourceware.org/dm/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="devices" unique="0" required="0">
+ <getopt mixed="-d, --devices=[devices]" />
+ <content type="string" />
+ <shortdesc lang="en">List of devices to use for current operation. Devices can be comma-separated list of device-mapper multipath devices (eg. /dev/mapper/3600508b400105df70000e00000ac0000 or /dev/mapper/mpath1). Each device must support SCSI-3 persistent reservations.</shortdesc>
+ </parameter>
+ <parameter name="key" unique="0" required="0">
+ <getopt mixed="-k, --key=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by port/-n/--plug</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Key to use for the current operation. This key should be unique to a node and have to be written in /etc/multipath.conf. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s).</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Key to use for the current operation. This key should be unique to a node and have to be written in /etc/multipath.conf. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s).</shortdesc>
+ </parameter>
+ <parameter name="suppress-errors" unique="0" required="0" deprecated="1">
+ <getopt mixed="--suppress-errors" />
+ <content type="boolean" />
+ <shortdesc lang="en">Error log suppression.</shortdesc>
+ </parameter>
+ <parameter name="suppress_errors" unique="0" required="0" obsoletes="suppress-errors">
+ <getopt mixed="--suppress-errors" />
+ <content type="boolean" />
+ <shortdesc lang="en">Error log suppression.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="mpathpersist_path" unique="0" required="0">
+ <getopt mixed="--mpathpersist-path=[path]" />
+ <shortdesc lang="en">Path to mpathpersist binary</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="store_path" unique="0" required="0">
+ <getopt mixed="--store-path=[path]" />
+ <shortdesc lang="en">Path to directory where fence agent can store information</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" on_target="1" automatic="1"/>
+ <action name="off" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_netio.xml b/tests/data/metadata/fence_netio.xml
new file mode 100644
index 0000000..95f3cf3
--- /dev/null
+++ b/tests/data/metadata/fence_netio.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_netio" shortdesc="I/O Fencing agent for Koukaam NETIO-230B" >
+<longdesc>fence_netio is an I/O Fencing agent which can be used with the Koukaam NETIO-230B Power Distribution Unit. It logs into device via telnet and reboots a specified outlet. Lengthy telnet connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.koukaam.se/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="1234" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_openstack.xml b/tests/data/metadata/fence_openstack.xml
new file mode 100644
index 0000000..0bf1a78
--- /dev/null
+++ b/tests/data/metadata/fence_openstack.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_openstack" shortdesc="Fence agent for OpenStack's Nova service" >
+<longdesc>fence_openstack is a Fencing agent which can be used with machines controlled by the Openstack's Nova service. This agent calls the python-novaclient and it is mandatory to be installed </longdesc>
+<vendor-url>https://wiki.openstack.org/wiki/Nova</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[UUID]" />
+ <content type="string" />
+ <shortdesc lang="en">UUID of the node to be fenced.</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[UUID]" />
+ <content type="string" />
+ <shortdesc lang="en">UUID of the node to be fenced.</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="auth-url" unique="0" required="0" deprecated="1">
+ <getopt mixed="--auth-url=[authurl]" />
+ <content type="string" />
+ <shortdesc lang="en">Keystone Auth URL</shortdesc>
+ </parameter>
+ <parameter name="auth_url" unique="0" required="0" obsoletes="auth-url">
+ <getopt mixed="--auth-url=[authurl]" />
+ <content type="string" />
+ <shortdesc lang="en">Keystone Auth URL</shortdesc>
+ </parameter>
+ <parameter name="project-name" unique="0" required="0" deprecated="1">
+ <getopt mixed="--project-name=[project]" />
+ <content type="string" default="admin" />
+ <shortdesc lang="en">Keystone Project</shortdesc>
+ </parameter>
+ <parameter name="project_name" unique="0" required="0" obsoletes="project-name">
+ <getopt mixed="--project-name=[project]" />
+ <content type="string" default="admin" />
+ <shortdesc lang="en">Keystone Project</shortdesc>
+ </parameter>
+ <parameter name="user-domain-name" unique="0" required="0" deprecated="1">
+ <getopt mixed="--user-domain-name=[domain]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone User Domain Name</shortdesc>
+ </parameter>
+ <parameter name="user_domain_name" unique="0" required="0" obsoletes="user-domain-name">
+ <getopt mixed="--user-domain-name=[domain]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone User Domain Name</shortdesc>
+ </parameter>
+ <parameter name="project-domain-name" unique="0" required="0" deprecated="1">
+ <getopt mixed="--project-domain-name=[domain]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone Project Domain Name</shortdesc>
+ </parameter>
+ <parameter name="project_domain_name" unique="0" required="0" obsoletes="project-domain-name">
+ <getopt mixed="--project-domain-name=[domain]" />
+ <content type="string" default="Default" />
+ <shortdesc lang="en">Keystone Project Domain Name</shortdesc>
+ </parameter>
+ <parameter name="cloud" unique="0" required="0">
+ <getopt mixed="--cloud=[cloud]" />
+ <content type="string" />
+ <shortdesc lang="en">Cloud from clouds.yaml</shortdesc>
+ </parameter>
+ <parameter name="openrc" unique="0" required="0">
+ <getopt mixed="--openrc=[openrc]" />
+ <content type="string" />
+ <shortdesc lang="en">openrc config file</shortdesc>
+ </parameter>
+ <parameter name="uuid" unique="0" required="0">
+ <getopt mixed="--uuid=[uuid]" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by port/-n/--plug</shortdesc>
+ </parameter>
+ <parameter name="cacert" unique="0" required="0">
+ <getopt mixed="--cacert=[cacert]" />
+ <content type="string" default="" />
+ <shortdesc lang="en">SSL X.509 certificates file</shortdesc>
+ </parameter>
+ <parameter name="apitimeout" unique="0" required="0">
+ <getopt mixed="--apitimeout=[seconds]" />
+ <content type="second" default="60" />
+ <shortdesc lang="en">Timeout in seconds to use for API calls, default is 60.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="60" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_ovh.xml b/tests/data/metadata/fence_ovh.xml
new file mode 100644
index 0000000..79d5eda
--- /dev/null
+++ b/tests/data/metadata/fence_ovh.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_ovh" shortdesc="Fence agent for OVH" >
+<longdesc>fence_ovh is an Power Fencing agent which can be used within OVH datecentre. Poweroff is simulated with a reboot into rescue-pro mode.</longdesc>
+<vendor-url>http://www.ovh.net</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="email" unique="0" required="1">
+ <getopt mixed="-Z, --email=[email]" />
+ <content type="string" />
+ <shortdesc lang="en">Reboot email</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_powerman.xml b/tests/data/metadata/fence_powerman.xml
new file mode 100644
index 0000000..10514fd
--- /dev/null
+++ b/tests/data/metadata/fence_powerman.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_powerman" shortdesc="Fence Agent for Powerman" >
+<longdesc>This is a Pacemaker Fence Agent for the Powerman management utility that was designed for LLNL systems.</longdesc>
+<vendor-url>https://github.com/chaos/powerman</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="10101" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="powerman_path" unique="0" required="0">
+ <getopt mixed="--powerman-path=[path]" />
+ <shortdesc lang="en">Path to powerman binary</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_pve.xml b/tests/data/metadata/fence_pve.xml
new file mode 100644
index 0000000..1ed3cda
--- /dev/null
+++ b/tests/data/metadata/fence_pve.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_pve" shortdesc="Fencing agent for the Proxmox Virtual Environment" >
+<longdesc>The fence_pve agent can be used to fence virtual machines acting as nodes in a virtualized cluster.</longdesc>
+<vendor-url>http://www.proxmox.com/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP Address or Hostname of a node within the Proxmox cluster.</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP Address or Hostname of a node within the Proxmox cluster.</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="8006" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" default="root@pam" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Id of the virtual machine.</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Id of the virtual machine.</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" default="root@pam" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="pve_node" unique="0" required="0">
+ <getopt mixed="-N, --pve-node=[node_name]" />
+ <content type="string" />
+ <shortdesc lang="en">Proxmox node name on which machine is located. (Must be specified if not using --pve-node-auto)</shortdesc>
+ </parameter>
+ <parameter name="pve_node_auto" unique="0" required="0">
+ <getopt mixed="-A, --pve-node-auto" />
+ <content type="boolean" />
+ <shortdesc lang="en">Automatically select proxmox node. (This option overrides --pve-node)</shortdesc>
+ </parameter>
+ <parameter name="vmtype" unique="0" required="1">
+ <getopt mixed="--vmtype" />
+ <content type="string" default="qemu" />
+ <shortdesc lang="en">Virtual machine type lxc or qemu. (Default: qemu)</shortdesc>
+ </parameter>
+ <parameter name="node_name" unique="0" required="0" deprecated="1">
+ <getopt mixed="--nodename" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by --pve-node</shortdesc>
+ </parameter>
+ <parameter name="nodename" unique="0" required="0" obsoletes="node_name">
+ <getopt mixed="--nodename" />
+ <content type="string" />
+ <shortdesc lang="en">Replaced by --pve-node</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_raritan.xml b/tests/data/metadata/fence_raritan.xml
new file mode 100644
index 0000000..5e387c7
--- /dev/null
+++ b/tests/data/metadata/fence_raritan.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_raritan" shortdesc="I/O Fencing agent for Raritan Dominion PX" >
+<longdesc>fence_raritan is an I/O Fencing agent which can be used with the Raritan DPXS12-20 Power Distribution Unit. It logs into device via telnet and reboots a specified outlet. Lengthy telnet connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.raritan.com/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_raritan_px3.xml b/tests/data/metadata/fence_raritan_px3.xml
new file mode 100644
index 0000000..af33cfd
--- /dev/null
+++ b/tests/data/metadata/fence_raritan_px3.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_raritan_px3" shortdesc="I/O Fencing agent for Raritan Dominion PX2 and PX3" >
+<longdesc>fence_raritan is an I/O Fencing agent which can be used with the Raritan PX2 and PX3 Power Distribution Unit series. It logs into device via telnet or ssh and reboots a specified outlet. Single outlets and grouped outlets are supported. The fence is tested on this model: PX3-5466V. There have been issues seen with the telnet prompt on 3.4.x and 3.5.x Raritan firmware versions. It's recommended to update to at least version 3.6.x</longdesc>
+<vendor-url>http://www.raritan.com/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default=".*\[My PDU\] #" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default=".*\[My PDU\] #" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="8" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_rcd_serial.xml b/tests/data/metadata/fence_rcd_serial.xml
new file mode 100644
index 0000000..c14d342
--- /dev/null
+++ b/tests/data/metadata/fence_rcd_serial.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_rcd_serial" shortdesc="rcd_serial fence agent" >
+<longdesc>fence_rcd_serial operates a serial cable that toggles a reset of an opposing server using the reset switch on its motherboard. The cable itself is simple with no power, network or moving parts. An example of the cable is available here: https://smcleod.net/rcd-stonith/ and the circuit design is available in the fence-agents src as SVG</longdesc>
+<vendor-url>https://github.com/sammcj/fence_rcd_serial</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="cycle" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="serial_port" unique="0" required="1">
+ <getopt mixed="--serial-port=[port]" />
+ <content type="string" default="/dev/ttyS0" />
+ <shortdesc lang="en">Port of the serial device</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="2" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="reboot" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_redfish.xml b/tests/data/metadata/fence_redfish.xml
new file mode 100644
index 0000000..76a23af
--- /dev/null
+++ b/tests/data/metadata/fence_redfish.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_redfish" shortdesc="I/O Fencing agent for Redfish" >
+<longdesc>fence_redfish is an I/O Fencing agent which can be used with Out-of-Band controllers that support Redfish APIs. These controllers provide remote access to control power on a server.</longdesc>
+<vendor-url>http://www.dmtf.org</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="443" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="redfish-uri" unique="0" required="0" deprecated="1">
+ <getopt mixed="--redfish-uri=[uri]" />
+ <content type="string" default="/redfish/v1" />
+ <shortdesc lang="en">Base or starting Redfish URI</shortdesc>
+ </parameter>
+ <parameter name="redfish_uri" unique="0" required="0" obsoletes="redfish-uri">
+ <getopt mixed="--redfish-uri=[uri]" />
+ <content type="string" default="/redfish/v1" />
+ <shortdesc lang="en">Base or starting Redfish URI</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="systems-uri" unique="0" required="0" deprecated="1">
+ <getopt mixed="--systems-uri=[uri]" />
+ <content type="string" />
+ <shortdesc lang="en">Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1</shortdesc>
+ </parameter>
+ <parameter name="systems_uri" unique="0" required="0" obsoletes="systems-uri">
+ <getopt mixed="--systems-uri=[uri]" />
+ <content type="string" />
+ <shortdesc lang="en">Redfish Systems resource URI, i.e. /redfish/v1/Systems/System.Embedded.1</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+ <action name="diag" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_rhevm.xml b/tests/data/metadata/fence_rhevm.xml
new file mode 100644
index 0000000..0b22399
--- /dev/null
+++ b/tests/data/metadata/fence_rhevm.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_rhevm" shortdesc="Fence agent for RHEV-M REST API" >
+<longdesc>fence_rhevm is an I/O Fencing agent which can be used with RHEV-M REST API to fence virtual machines.</longdesc>
+<vendor-url>http://www.redhat.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="80" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="notls" unique="0" required="0">
+ <getopt mixed="-t, --notls" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">VM name in RHV</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">VM name in RHV</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="use_cookies" unique="0" required="0">
+ <getopt mixed="--use-cookies" />
+ <content type="boolean" />
+ <shortdesc lang="en">Reuse cookies for authentication</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="api_version" unique="0" required="0">
+ <getopt mixed="--api-version" />
+ <content type="string" default="auto" />
+ <shortdesc lang="en">Version of RHEV API (default: auto)</shortdesc>
+ </parameter>
+ <parameter name="cookie_file" unique="0" required="0">
+ <getopt mixed="--cookie-file" />
+ <shortdesc lang="en">Path to cookie file for authentication</shortdesc>
+ </parameter>
+ <parameter name="api_path" unique="0" required="0">
+ <getopt mixed="--api-path=[path]" />
+ <shortdesc lang="en">The path part of the API URL</shortdesc>
+ </parameter>
+ <parameter name="disable_http_filter" unique="0" required="0">
+ <getopt mixed="--disable-http-filter" />
+ <content type="boolean" />
+ <shortdesc lang="en">Set HTTP Filter header to false</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_rsa.xml b/tests/data/metadata/fence_rsa.xml
new file mode 100644
index 0000000..284f918
--- /dev/null
+++ b/tests/data/metadata/fence_rsa.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_rsa" shortdesc="Fence agent for IBM RSA" >
+<longdesc>fence_rsa is an I/O Fencing agent which can be used with the IBM RSA II management interface. It logs into an RSA II device via telnet and reboots the associated machine. Lengthy telnet connections to the RSA II device should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" default="-F /dev/null" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="10" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_rsb.xml b/tests/data/metadata/fence_rsb.xml
new file mode 100644
index 0000000..e3d6e10
--- /dev/null
+++ b/tests/data/metadata/fence_rsb.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_rsb" shortdesc="I/O Fencing agent for Fujitsu-Siemens RSB" >
+<longdesc>fence_rsb is an I/O Fencing agent which can be used with the Fujitsu-Siemens RSB management interface. It logs into device via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.fujitsu.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;to quit:&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;to quit:&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="3172" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_sanbox2.xml b/tests/data/metadata/fence_sanbox2.xml
new file mode 100644
index 0000000..b29b8bb
--- /dev/null
+++ b/tests/data/metadata/fence_sanbox2.xml
@@ -0,0 +1,176 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_sanbox2" shortdesc="Fence agent for QLogic SANBox2 FC switches" >
+<longdesc>fence_sanbox2 is an I/O Fencing agent which can be used with QLogic SANBox2 FC switches. It logs into a SANBox2 switch via telnet and disables a specified port. Disabling the port which a machine is connected to effectively fences that machine. Lengthy telnet connections to the switch should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.qlogic.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos; #&gt; &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos; #&gt; &apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="1"/>
+ <action name="off" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_sbd.xml b/tests/data/metadata/fence_sbd.xml
new file mode 100644
index 0000000..d5600b7
--- /dev/null
+++ b/tests/data/metadata/fence_sbd.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_sbd" shortdesc="Fence agent for sbd" >
+<longdesc>fence_sbd is I/O Fencing agent which can be used in environments where sbd can be used (shared storage).</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="devices" unique="0" required="1">
+ <getopt mixed="--devices=[device_a,device_b]" />
+ <content type="string" />
+ <shortdesc lang="en">SBD Device</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="cycle" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="30" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="sbd_path" unique="0" required="0">
+ <getopt mixed="--sbd-path=[path]" />
+ <shortdesc lang="en">Path to SBD binary</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_scsi.xml b/tests/data/metadata/fence_scsi.xml
new file mode 100644
index 0000000..4fa8618
--- /dev/null
+++ b/tests/data/metadata/fence_scsi.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_scsi" shortdesc="Fence agent for SCSI persistent reservation" >
+<longdesc>fence_scsi is an I/O fencing agent that uses SCSI-3 persistent reservations to control access to shared storage devices. These devices must support SCSI-3 persistent reservations (SPC-3 or greater) as well as the "preempt-and-abort" subcommand.
+The fence_scsi agent works by having each node in the cluster register a unique key with the SCSI device(s). Reservation key is generated from "node id" (default) or from "node name hash" (RECOMMENDED) by adjusting "key_value" option. Using hash is recommended to prevent issues when removing nodes from cluster without full cluster restart. Once registered, a single node will become the reservation holder by creating a "write exclusive, registrants only" reservation on the device(s). The result is that only registered nodes may write to the device(s). When a node failure occurs, the fence_scsi agent will remove the key belonging to the failed node from the device(s). The failed node will no longer be able to write to the device(s). A manual reboot is required.
+
+When used as a watchdog device you can define e.g. retry=1, retry-sleep=2 and verbose=yes parameters in /etc/sysconfig/stonith if you have issues with it failing.</longdesc>
+<vendor-url></vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="off" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="aptpl" unique="0" required="0">
+ <getopt mixed="-a, --aptpl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use the APTPL flag for registrations. This option is only used for the 'on' action.</shortdesc>
+ </parameter>
+ <parameter name="devices" unique="0" required="0">
+ <getopt mixed="-d, --devices=[devices]" />
+ <content type="string" />
+ <shortdesc lang="en">List of devices to use for current operation. Devices can be comma-separated list of raw devices (eg. /dev/sdc). Each device must support SCSI-3 persistent reservations.</shortdesc>
+ </parameter>
+ <parameter name="key" unique="0" required="0">
+ <getopt mixed="-k, --key=[key]" />
+ <content type="string" />
+ <shortdesc lang="en">Key to use for the current operation. This key should be unique to a node. For the "on" action, the key specifies the key use to register the local node. For the "off" action, this key specifies the key to be removed from the device(s).</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[nodename]" />
+ <content type="string" />
+ <shortdesc lang="en">Name of the node to be fenced. The node name is used to generate the key value used for the current operation. This option will be ignored when used with the -k option.</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[nodename]" />
+ <content type="string" />
+ <shortdesc lang="en">Name of the node to be fenced. The node name is used to generate the key value used for the current operation. This option will be ignored when used with the -k option.</shortdesc>
+ </parameter>
+ <parameter name="readonly" unique="0" required="0">
+ <getopt mixed="--readonly" />
+ <content type="boolean" />
+ <shortdesc lang="en">Open DEVICE read-only.</shortdesc>
+ </parameter>
+ <parameter name="suppress-errors" unique="0" required="0" deprecated="1">
+ <getopt mixed="--suppress-errors" />
+ <content type="boolean" />
+ <shortdesc lang="en">Error log suppression.</shortdesc>
+ </parameter>
+ <parameter name="suppress_errors" unique="0" required="0" obsoletes="suppress-errors">
+ <getopt mixed="--suppress-errors" />
+ <content type="boolean" />
+ <shortdesc lang="en">Error log suppression.</shortdesc>
+ </parameter>
+ <parameter name="logfile" unique="0" required="0">
+ <getopt mixed="-f, --logfile" />
+ <content type="string" />
+ <shortdesc lang="en">Log output (stdout and stderr) to file</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="corosync_cmap_path" unique="0" required="0">
+ <getopt mixed="--corosync-cmap-path=[path]" />
+ <shortdesc lang="en">Path to corosync-cmapctl binary</shortdesc>
+ </parameter>
+ <parameter name="key_value" unique="0" required="0">
+ <getopt mixed="--key-value=&lt;id|hash&gt;" />
+ <content type="string" default="id" />
+ <shortdesc lang="en">Method used to generate the SCSI key. "id" (default) uses the positional ID from "corosync-cmactl nodelist" output which can get inconsistent when nodes are removed from cluster without full cluster restart. "hash" uses part of hash made out of node names which is not affected over time but there is theoretical chance that hashes can collide as size of SCSI key is quite limited.</shortdesc>
+ </parameter>
+ <parameter name="sg_persist_path" unique="0" required="0">
+ <getopt mixed="--sg_persist-path=[path]" />
+ <shortdesc lang="en">Path to sg_persist binary</shortdesc>
+ </parameter>
+ <parameter name="sg_turs_path" unique="0" required="0">
+ <getopt mixed="--sg_turs-path=[path]" />
+ <shortdesc lang="en">Path to sg_turs binary</shortdesc>
+ </parameter>
+ <parameter name="vgs_path" unique="0" required="0">
+ <getopt mixed="--vgs-path=[path]" />
+ <shortdesc lang="en">Path to vgs binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" on_target="1" automatic="1"/>
+ <action name="off" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_skalar.xml b/tests/data/metadata/fence_skalar.xml
new file mode 100644
index 0000000..84f3f4e
--- /dev/null
+++ b/tests/data/metadata/fence_skalar.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_skalar" shortdesc="Skala-R Fence agent" >
+<longdesc>A fence agent for Skala-R.</longdesc>
+<vendor-url>https://www.skala-r.ru/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="force" unique="0" required="0">
+ <getopt mixed="--force" />
+ <content type="boolean" />
+ <shortdesc lang="en">vm_stop command parameter, force stop or not, default false</shortdesc>
+ </parameter>
+ <parameter name="graceful" unique="0" required="0">
+ <getopt mixed="--graceful" />
+ <content type="boolean" />
+ <shortdesc lang="en">vm_stop command parameter, graceful stop or not, default false</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="80" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_tripplite_snmp.xml b/tests/data/metadata/fence_tripplite_snmp.xml
new file mode 100644
index 0000000..c5f66d5
--- /dev/null
+++ b/tests/data/metadata/fence_tripplite_snmp.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_tripplite_snmp" shortdesc="Fence agent for APC, Tripplite PDU over SNMP" >
+<symlink name="fence_tripplite_snmp" shortdesc="Fence agent for Tripplife over SNMP"/>
+<longdesc>fence_apc_snmp is an I/O Fencing agent which can be used with the APC network power switch or Tripplite PDU devices.It logs into a device via SNMP and reboots a specified outlet. It supports SNMP v1, v2c, v3 with all combinations of authenticity/privacy settings.</longdesc>
+<vendor-url>http://www.apc.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="community" unique="0" required="0">
+ <getopt mixed="-c, --community=[community]" />
+ <content type="string" default="private" />
+ <shortdesc lang="en">Set the community string</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="161" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="snmp_auth_prot" unique="0" required="0">
+ <getopt mixed="-b, --snmp-auth-prot=[prot]" />
+ <content type="select" >
+ <option value="MD5" />
+ <option value="SHA" />
+ </content>
+ <shortdesc lang="en">Set authentication protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd" unique="0" required="0">
+ <getopt mixed="-P, --snmp-priv-passwd=[pass]" />
+ <content type="string" />
+ <shortdesc lang="en">Set privacy protocol password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_passwd_script" unique="0" required="0">
+ <getopt mixed="-R, --snmp-priv-passwd-script" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve privacy password</shortdesc>
+ </parameter>
+ <parameter name="snmp_priv_prot" unique="0" required="0">
+ <getopt mixed="-B, --snmp-priv-prot=[prot]" />
+ <content type="select" >
+ <option value="DES" />
+ <option value="AES" />
+ </content>
+ <shortdesc lang="en">Set privacy protocol</shortdesc>
+ </parameter>
+ <parameter name="snmp_sec_level" unique="0" required="0">
+ <getopt mixed="-E, --snmp-sec-level=[level]" />
+ <content type="select" >
+ <option value="noAuthNoPriv" />
+ <option value="authNoPriv" />
+ <option value="authPriv" />
+ </content>
+ <shortdesc lang="en">Set security level</shortdesc>
+ </parameter>
+ <parameter name="snmp_version" unique="0" required="0">
+ <getopt mixed="-d, --snmp-version=[version]" />
+ <content type="select" default="1" >
+ <option value="1" />
+ <option value="2c" />
+ <option value="3" />
+ </content>
+ <shortdesc lang="en">Specifies SNMP version to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="snmpget_path" unique="0" required="0">
+ <getopt mixed="--snmpget-path=[path]" />
+ <shortdesc lang="en">Path to snmpget binary</shortdesc>
+ </parameter>
+ <parameter name="snmpset_path" unique="0" required="0">
+ <getopt mixed="--snmpset-path=[path]" />
+ <shortdesc lang="en">Path to snmpset binary</shortdesc>
+ </parameter>
+ <parameter name="snmpwalk_path" unique="0" required="0">
+ <getopt mixed="--snmpwalk-path=[path]" />
+ <shortdesc lang="en">Path to snmpwalk binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_vbox.xml b/tests/data/metadata/fence_vbox.xml
new file mode 100644
index 0000000..35577a6
--- /dev/null
+++ b/tests/data/metadata/fence_vbox.xml
@@ -0,0 +1,240 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_vbox" shortdesc="Fence agent for VirtualBox" >
+<longdesc>fence_vbox is an I/O Fencing agent which can be used with the virtual machines managed by VirtualBox. It logs via ssh to a dom0 where it runs VBoxManage to do all of the work.
+
+By default, vbox needs to log in as a user that is a member of the vboxusers group. Also, you must allow ssh login in your sshd_config.</longdesc>
+<vendor-url>https://www.virtualbox.org/</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\[EXPECT\\]#&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\[EXPECT\\]#&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="22" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" default="-t &apos;/bin/bash -c &quot;PS1=\\[EXPECT\\]# HISTFILE=/dev/null /bin/bash --noprofile --norc&quot;&apos;" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="host_os" unique="0" required="0">
+ <getopt mixed="--host-os=[os]" />
+ <content type="select" default="linux" >
+ <option value="linux" />
+ <option value="macos" />
+ <option value="windows" />
+ </content>
+ <shortdesc lang="en">Operating system of the host</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="missing_as_off" unique="0" required="0">
+ <getopt mixed="--missing-as-off" />
+ <content type="boolean" />
+ <shortdesc lang="en">Missing port returns OFF instead of failure</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="vboxmanage_path" unique="0" required="0">
+ <getopt mixed="--vboxmanage-path=[path]" />
+ <shortdesc lang="en">Path to VBoxManage on the host</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_virsh.xml b/tests/data/metadata/fence_virsh.xml
new file mode 100644
index 0000000..82fe9b6
--- /dev/null
+++ b/tests/data/metadata/fence_virsh.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_virsh" shortdesc="Fence agent for virsh" >
+<longdesc>fence_virsh is an I/O Fencing agent which can be used with the virtual machines managed by libvirt. It logs via ssh to a dom0 and there run virsh command, which does all work.
+
+By default, virsh needs root account to do properly work. So you must allow ssh login in your sshd_config.</longdesc>
+<vendor-url>http://libvirt.org</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\[EXPECT\\]#&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;\\[EXPECT\\]#&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="22" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" default="-t &apos;/bin/bash -c &quot;PS1=\\[EXPECT\\]# /bin/bash --noprofile --norc&quot;&apos;" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="missing_as_off" unique="0" required="0">
+ <getopt mixed="--missing-as-off" />
+ <content type="boolean" />
+ <shortdesc lang="en">Missing port returns OFF instead of failure</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="sudo" unique="0" required="0" deprecated="1">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="use_sudo" unique="0" required="0" obsoletes="sudo">
+ <getopt mixed="--use-sudo" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use sudo (without password) when calling 3rd party software</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="sudo_path" unique="0" required="0">
+ <getopt mixed="--sudo-path=[path]" />
+ <shortdesc lang="en">Path to sudo binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_virt.xml b/tests/data/metadata/fence_virt.xml
new file mode 100644
index 0000000..612d4d3
--- /dev/null
+++ b/tests/data/metadata/fence_virt.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_virt" shortdesc="Fence agent for virtual machines">
+<longdesc>fence_virt is an I/O Fencing agent which can be used with virtual machines.
+
+NOTE: reboot-action does not power on nodes that are powered off.</longdesc>
+<vendor-url>https://libvirt.org</vendor-url>
+<parameters>
+ <parameter name="debug" unique="0" required="0">
+ <getopt mixed="-d" />
+ <content type="boolean" />
+ <shortdesc lang="en">Specify (stdin) or increment (command line) debug level</shortdesc>
+ </parameter>
+ <parameter name="serial_device" unique="0" required="0">
+ <getopt mixed="-D" />
+ <content type="string" default="/dev/ttyS1" />
+ <shortdesc lang="en">Serial device (default=/dev/ttyS1)</shortdesc>
+ </parameter>
+ <parameter name="serial_params" unique="0" required="0">
+ <getopt mixed="-P" />
+ <content type="string" default="115200,8N1" />
+ <shortdesc lang="en">Serial Parameters (default=115200,8N1)</shortdesc>
+ </parameter>
+ <parameter name="channel_address" unique="0" required="0">
+ <getopt mixed="-A" />
+ <content type="string" default="10.0.2.179" />
+ <shortdesc lang="en">VM Channel IP address (default=10.0.2.179)</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-p" />
+ <content type="string" default="1229" />
+ <shortdesc lang="en">TCP, Multicast, VMChannel, or VM socket port (default=1229)</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n" />
+ <content type="string" />
+ <shortdesc lang="en">Virtual Machine (domain name) to fence</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-H" />
+ <content type="string" />
+ <shortdesc lang="en">Virtual Machine (domain name) to fence</shortdesc>
+ </parameter>
+ <parameter name="action" unique="0" required="0">
+ <getopt mixed="-o" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action (null, off, on, [reboot], status, list, list-status, monitor, validate-all, metadata)</shortdesc>
+ </parameter>
+ <parameter name="timeout" unique="0" required="0">
+ <getopt mixed="-t" />
+ <content type="string" default="30" />
+ <shortdesc lang="en">Fencing timeout (in seconds; default=30)</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0">
+ <getopt mixed="-T" />
+ <content type="string" default="127.0.0.1" />
+ <shortdesc lang="en">IP address to connect to in TCP mode (default=127.0.0.1 / ::1)</shortdesc>
+ </parameter>
+ <parameter name="vsock" unique="0" required="0">
+ <getopt mixed="-S" />
+ <content type="integer" default="2" />
+ <shortdesc lang="en">vm socket CID to connect to in vsock mode</shortdesc>
+ </parameter>
+ <parameter name="auth" unique="0" required="0">
+ <getopt mixed="-C" />
+ <content type="string" default="sha256" />
+ <shortdesc lang="en">Authentication (none, sha1, [sha256], sha512)</shortdesc>
+ </parameter>
+ <parameter name="hash" unique="0" required="0">
+ <getopt mixed="-c" />
+ <content type="string" default="sha256" />
+ <shortdesc lang="en">Packet hash strength (none, sha1, [sha256], sha512)</shortdesc>
+ </parameter>
+ <parameter name="key_file" unique="0" required="0">
+ <getopt mixed="-k" />
+ <content type="string" default="/etc/cluster/fence_xvm.key" />
+ <shortdesc lang="en">Shared key file (default=/etc/cluster/fence_xvm.key)</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="-w" />
+ <content type="string" default="0" />
+ <shortdesc lang="en">Fencing delay (in seconds; default=0)</shortdesc>
+ </parameter>
+ <parameter name="domain" unique="0" required="0" deprecated="1">
+ <getopt mixed="" />
+ <content type="string" />
+ <shortdesc lang="en">Virtual Machine (domain name) to fence (deprecated; use port)</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="null" />
+ <action name="on" />
+ <action name="off" />
+ <action name="reboot" />
+ <action name="metadata" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_vmware.xml b/tests/data/metadata/fence_vmware.xml
new file mode 100644
index 0000000..a46ffdb
--- /dev/null
+++ b/tests/data/metadata/fence_vmware.xml
@@ -0,0 +1,217 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_vmware" shortdesc="Fence agent for VMWare" >
+<longdesc>fence_vmware is an I/O Fencing agent which can be used with the VMware ESX, VMware ESXi or VMware Server to fence virtual machines.
+
+Before you can use this agent, it must be installed VI Perl Toolkit or vmrun command on every node you want to make fencing.
+
+VI Perl Toolkit is preferred for VMware ESX/ESXi and Virtual Center. Vmrun command is only solution for VMware Server 1/2 (this command will works against ESX/ESXi 3.5 up2 and VC up2 too, but not cluster aware!) and is available as part of VMware VIX API SDK package. VI Perl and VIX API SDK are both available from VMware web pages (not int RHEL repository!).
+
+You can specify type of VMware you are connecting to with -d switch (or vmware_type for stdin). Possible values are esx, server2 and server1.Default value is esx, which will use VI Perl. With server1 and server2, vmrun command is used.
+
+After you have successfully installed VI Perl Toolkit or VIX API, you should be able to run fence_vmware_helper (part of this agent) or vmrun command. This agent supports only vmrun from version 2.0.0 (VIX API 1.6.0).</longdesc>
+<vendor-url>http://www.vmware.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="exec" unique="0" required="0">
+ <getopt mixed="-e, --exec=[command]" />
+ <content type="string" />
+ <shortdesc lang="en">Command to execute</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="0" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="0" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="22" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="0" obsoletes="port">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="0" deprecated="1">
+ <getopt mixed="-n, --plug=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device (together with --port-as-ip)</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="vmware_type" unique="0" required="0">
+ <getopt mixed="-d, --vmware_type=[type]" />
+ <content type="string" default="esx" />
+ <shortdesc lang="en">Type of VMware to connect</shortdesc>
+ </parameter>
+ <parameter name="vmware_datacenter" unique="0" required="0">
+ <getopt mixed="-s, --vmware-datacenter=[dc]" />
+ <content type="string" />
+ <shortdesc lang="en">VMWare datacenter filter</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="port_as_ip" unique="0" required="0">
+ <getopt mixed="--port-as-ip" />
+ <content type="boolean" />
+ <shortdesc lang="en">Make "port/plug" to be an alias to IP address</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_vmware_rest.xml b/tests/data/metadata/fence_vmware_rest.xml
new file mode 100644
index 0000000..5c69c2f
--- /dev/null
+++ b/tests/data/metadata/fence_vmware_rest.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_vmware_rest" shortdesc="Fence agent for VMware REST API" >
+<longdesc>fence_vmware_rest is an I/O Fencing agent which can be used with VMware API to fence virtual machines.
+
+NOTE: If there's more than 1000 VMs there is a filter parameter to work around the API limit. See https://code.vmware.com/apis/62/vcenter-management#/VM%20/get_vcenter_vm for full list of filters.</longdesc>
+<vendor-url>https://www.vmware.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="80" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="notls" unique="0" required="0">
+ <getopt mixed="-t, --notls" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="api_path" unique="0" required="0">
+ <getopt mixed="--api-path=[path]" />
+ <shortdesc lang="en">The path part of the API URL</shortdesc>
+ </parameter>
+ <parameter name="filter" unique="0" required="0">
+ <getopt mixed="--filter=[filter]" />
+ <content type="string" />
+ <shortdesc lang="en">Filter to only return relevant VMs. It can be used to avoid the agent failing when more than 1000 VMs should be returned.</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_vmware_soap.xml b/tests/data/metadata/fence_vmware_soap.xml
new file mode 100644
index 0000000..72b27e3
--- /dev/null
+++ b/tests/data/metadata/fence_vmware_soap.xml
@@ -0,0 +1,189 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_vmware_soap" shortdesc="Fence agent for VMWare over SOAP API" >
+<longdesc>fence_vmware_soap is an I/O Fencing agent which can be used with the virtual machines managed by VMWare products that have SOAP API v4.1+.
+
+Name of virtual machine (-n / port) has to be used in inventory path format (e.g. /datacenter/vm/Discovered virtual machine/myMachine). In the cases when name of yours VM is unique you can use it instead. Alternatively you can always use UUID to access virtual machine.</longdesc>
+<vendor-url>http://www.vmware.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="80" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="notls" unique="0" required="0">
+ <getopt mixed="-t, --notls" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_vmware_vcloud.xml b/tests/data/metadata/fence_vmware_vcloud.xml
new file mode 100644
index 0000000..3c8bb74
--- /dev/null
+++ b/tests/data/metadata/fence_vmware_vcloud.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_vmware_vcloud" shortdesc="Fence agent for VMware vCloud Director API" >
+<longdesc>fence_vmware_vcloud is an I/O Fencing agent which can be used with VMware vCloud Director API to fence virtual machines.</longdesc>
+<vendor-url>https://www.vmware.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="80" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="notls" unique="0" required="0">
+ <getopt mixed="-t, --notls" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="api_path" unique="0" required="0">
+ <getopt mixed="--api-path=[path]" />
+ <shortdesc lang="en">The path part of the API URL</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_wti.xml b/tests/data/metadata/fence_wti.xml
new file mode 100644
index 0000000..b9eb9c6
--- /dev/null
+++ b/tests/data/metadata/fence_wti.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_wti" shortdesc="Fence agent for WTI" >
+<longdesc>fence_wti is an I/O Fencing agent which can be used with the WTI Network Power Switch (NPS). It logs into an NPS via telnet or ssh and boots a specified plug. Lengthy telnet connections to the NPS should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.</longdesc>
+<vendor-url>http://www.wti.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="cmd_prompt" unique="0" required="0" deprecated="1">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;RSM&gt;&apos;, &apos;MPC&gt;&apos;, &apos;IPS&gt;&apos;, &apos;TPS&gt;&apos;, &apos;NBB&gt;&apos;, &apos;NPS&gt;&apos;, &apos;VMR&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="command_prompt" unique="0" required="0" obsoletes="cmd_prompt">
+ <getopt mixed="-c, --command-prompt=[prompt]" />
+ <content type="string" default="[&apos;RSM&gt;&apos;, &apos;MPC&gt;&apos;, &apos;IPS&gt;&apos;, &apos;TPS&gt;&apos;, &apos;NBB&gt;&apos;, &apos;NPS&gt;&apos;, &apos;VMR&gt;&apos;]" />
+ <shortdesc lang="en">Force Python regex for command prompt</shortdesc>
+ </parameter>
+ <parameter name="identity_file" unique="0" required="0">
+ <getopt mixed="-k, --identity-file=[filename]" />
+ <shortdesc lang="en">Identity file (private key) for SSH</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="23" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="secure" unique="0" required="0" deprecated="1">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh" unique="0" required="0" obsoletes="secure">
+ <getopt mixed="-x, --ssh" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSH connection</shortdesc>
+ </parameter>
+ <parameter name="ssh_options" unique="0" required="0">
+ <getopt mixed="--ssh-options=[options]" />
+ <content type="string" />
+ <shortdesc lang="en">SSH options to use</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="10" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="ssh_path" unique="0" required="0">
+ <getopt mixed="--ssh-path=[path]" />
+ <shortdesc lang="en">Path to ssh binary</shortdesc>
+ </parameter>
+ <parameter name="telnet_path" unique="0" required="0">
+ <getopt mixed="--telnet-path=[path]" />
+ <shortdesc lang="en">Path to telnet binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_xenapi.xml b/tests/data/metadata/fence_xenapi.xml
new file mode 100644
index 0000000..380ac28
--- /dev/null
+++ b/tests/data/metadata/fence_xenapi.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_xenapi" shortdesc="Fence agent for Citrix XenServer over XenAPI" >
+<longdesc>fence_cxs is an I/O Fencing agent used on Citrix XenServer hosts. It uses the XenAPI, supplied by Citrix, to establish an XML-RPC session to a XenServer host. Once the session is established, further XML-RPC commands are issued in order to switch on, switch off, restart and query the status of virtual machines running on the host.</longdesc>
+<vendor-url>http://www.xenproject.org</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="0" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="session_url" unique="0" required="1">
+ <getopt mixed="-s, --session-url" />
+ <content type="string" />
+ <shortdesc lang="en">URL to connect to XenServer on</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="0" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="3" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/data/metadata/fence_zvmip.xml b/tests/data/metadata/fence_zvmip.xml
new file mode 100644
index 0000000..6996ab7
--- /dev/null
+++ b/tests/data/metadata/fence_zvmip.xml
@@ -0,0 +1,225 @@
+<?xml version="1.0" ?>
+<resource-agent name="fence_zvmip" shortdesc="Fence agent for use with z/VM Virtual Machines" >
+<longdesc>The fence_zvm agent is intended to be used with with z/VM SMAPI service via TCP/IP
+
+To use this agent the z/VM SMAPI service needs to be configured to allow the virtual machine running this agent to connect to it and issue
+the image_recycle operation. This involves updating the VSMWORK1 AUTHLIST VMSYS:VSMWORK1. file. The entry should look something similar to
+this:
+
+Column 1 Column 66 Column 131
+
+ | | |
+ V V V
+
+XXXXXXXX ALL IMAGE_CHARACTERISTICS
+
+Where XXXXXXX is the name of the virtual machine used in the authuser field of the request. This virtual machine also has to be authorized
+to access the system's directory manager.
+</longdesc>
+<vendor-url>http://www.ibm.com</vendor-url>
+<parameters>
+ <parameter name="action" unique="0" required="1">
+ <getopt mixed="-o, --action=[action]" />
+ <content type="string" default="reboot" />
+ <shortdesc lang="en">Fencing action</shortdesc>
+ </parameter>
+ <parameter name="inet4_only" unique="0" required="0">
+ <getopt mixed="-4, --inet4-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc>
+ </parameter>
+ <parameter name="inet6_only" unique="0" required="0">
+ <getopt mixed="-6, --inet6-only" />
+ <content type="boolean" />
+ <shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc>
+ </parameter>
+ <parameter name="ip" unique="0" required="1" obsoletes="ipaddr">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipaddr" unique="0" required="1" deprecated="1">
+ <getopt mixed="-a, --ip=[ip]" />
+ <content type="string" />
+ <shortdesc lang="en">IP address or hostname of fencing device</shortdesc>
+ </parameter>
+ <parameter name="ipport" unique="0" required="0">
+ <getopt mixed="-u, --ipport=[port]" />
+ <content type="integer" default="44444" />
+ <shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc>
+ </parameter>
+ <parameter name="login" unique="0" required="1" deprecated="1">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="method" unique="0" required="0">
+ <getopt mixed="-m, --method=[method]" />
+ <content type="select" default="onoff" >
+ <option value="onoff" />
+ <option value="cycle" />
+ </content>
+ <shortdesc lang="en">Method to fence</shortdesc>
+ </parameter>
+ <parameter name="passwd" unique="0" required="0" deprecated="1">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="passwd_script" unique="0" required="0" deprecated="1">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="password" unique="0" required="0" obsoletes="passwd">
+ <getopt mixed="-p, --password=[password]" />
+ <content type="string" />
+ <shortdesc lang="en">Login password or passphrase</shortdesc>
+ </parameter>
+ <parameter name="password_script" unique="0" required="0" obsoletes="passwd_script">
+ <getopt mixed="-S, --password-script=[script]" />
+ <content type="string" />
+ <shortdesc lang="en">Script to run to retrieve password</shortdesc>
+ </parameter>
+ <parameter name="plug" unique="0" required="1" obsoletes="port">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="port" unique="0" required="1" deprecated="1">
+ <getopt mixed="-n, --plug=[id]" />
+ <content type="string" />
+ <shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc>
+ </parameter>
+ <parameter name="ssl" unique="0" required="0">
+ <getopt mixed="-z, --ssl" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate (Default)</shortdesc>
+ </parameter>
+ <parameter name="ssl_insecure" unique="0" required="0">
+ <getopt mixed="--ssl-insecure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="ssl_secure" unique="0" required="0">
+ <getopt mixed="--ssl-secure" />
+ <content type="boolean" />
+ <shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc>
+ </parameter>
+ <parameter name="username" unique="0" required="1" obsoletes="login">
+ <getopt mixed="-l, --username=[name]" />
+ <content type="string" />
+ <shortdesc lang="en">Login name</shortdesc>
+ </parameter>
+ <parameter name="disable_ssl" unique="0" required="0">
+ <getopt mixed="--disable-ssl" />
+ <content type="boolean" />
+ <shortdesc lang="en">Don't use SSL</shortdesc>
+ </parameter>
+ <parameter name="quiet" unique="0" required="0">
+ <getopt mixed="-q, --quiet" />
+ <content type="boolean" />
+ <shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog.</shortdesc>
+ </parameter>
+ <parameter name="verbose" unique="0" required="0">
+ <getopt mixed="-v, --verbose" />
+ <content type="boolean" />
+ <shortdesc lang="en">Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity.</shortdesc>
+ </parameter>
+ <parameter name="verbose_level" unique="0" required="0">
+ <getopt mixed="--verbose-level" />
+ <content type="integer" />
+ <shortdesc lang="en">Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin).</shortdesc>
+ </parameter>
+ <parameter name="debug" unique="0" required="0" deprecated="1">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <content type="string" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="debug_file" unique="0" required="0" obsoletes="debug">
+ <getopt mixed="-D, --debug-file=[debugfile]" />
+ <shortdesc lang="en">Write debug information to given file</shortdesc>
+ </parameter>
+ <parameter name="version" unique="0" required="0">
+ <getopt mixed="-V, --version" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display version information and exit</shortdesc>
+ </parameter>
+ <parameter name="help" unique="0" required="0">
+ <getopt mixed="-h, --help" />
+ <content type="boolean" />
+ <shortdesc lang="en">Display help and exit</shortdesc>
+ </parameter>
+ <parameter name="plug_separator" unique="0" required="0">
+ <getopt mixed="--plug-separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for plug parameter when specifying more than 1 plug</shortdesc>
+ </parameter>
+ <parameter name="separator" unique="0" required="0">
+ <getopt mixed="-C, --separator=[char]" />
+ <content type="string" default="," />
+ <shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc>
+ </parameter>
+ <parameter name="delay" unique="0" required="0">
+ <getopt mixed="--delay=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds before fencing is started</shortdesc>
+ </parameter>
+ <parameter name="disable_timeout" unique="0" required="0">
+ <getopt mixed="--disable-timeout=[true/false]" />
+ <content type="string" />
+ <shortdesc lang="en">Disable timeout (true/false) (default: true when run from Pacemaker 2.0+)</shortdesc>
+ </parameter>
+ <parameter name="login_timeout" unique="0" required="0">
+ <getopt mixed="--login-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc>
+ </parameter>
+ <parameter name="missing_as_off" unique="0" required="0">
+ <getopt mixed="--missing-as-off" />
+ <content type="boolean" default="1" />
+ <shortdesc lang="en">Missing port returns OFF instead of failure</shortdesc>
+ </parameter>
+ <parameter name="power_timeout" unique="0" required="0">
+ <getopt mixed="--power-timeout=[seconds]" />
+ <content type="second" default="20" />
+ <shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="power_wait" unique="0" required="0">
+ <getopt mixed="--power-wait=[seconds]" />
+ <content type="second" default="0" />
+ <shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc>
+ </parameter>
+ <parameter name="shell_timeout" unique="0" required="0">
+ <getopt mixed="--shell-timeout=[seconds]" />
+ <content type="second" default="5" />
+ <shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc>
+ </parameter>
+ <parameter name="stonith_status_sleep" unique="0" required="0">
+ <getopt mixed="--stonith-status-sleep=[seconds]" />
+ <content type="second" default="1" />
+ <shortdesc lang="en">Sleep X seconds between status calls during a STONITH action</shortdesc>
+ </parameter>
+ <parameter name="retry_on" unique="0" required="0">
+ <getopt mixed="--retry-on=[attempts]" />
+ <content type="integer" default="1" />
+ <shortdesc lang="en">Count of attempts to retry power on</shortdesc>
+ </parameter>
+ <parameter name="gnutlscli_path" unique="0" required="0">
+ <getopt mixed="--gnutlscli-path=[path]" />
+ <shortdesc lang="en">Path to gnutls-cli binary</shortdesc>
+ </parameter>
+</parameters>
+<actions>
+ <action name="on" automatic="0"/>
+ <action name="off" />
+ <action name="reboot" />
+ <action name="status" />
+ <action name="list" />
+ <action name="list-status" />
+ <action name="monitor" />
+ <action name="metadata" />
+ <action name="manpage" />
+ <action name="validate-all" />
+</actions>
+</resource-agent>
diff --git a/tests/devices.d/dummy-with_action.cfg b/tests/devices.d/dummy-with_action.cfg
new file mode 100644
index 0000000..5550c36
--- /dev/null
+++ b/tests/devices.d/dummy-with_action.cfg
@@ -0,0 +1,9 @@
+name = "Dummy fence device configuration"
+agent = "/bin/true"
+[options]
+ login = "foo", "--username", "-l"
+ passwd = "bar", "--password", "-p"
+ ipaddr = "fence.example.com", "--ip", "-a"
+ port = "1", "--plug"
+ action = "status", "--action", "-o"
+
diff --git a/tests/devices.d/dummy.cfg b/tests/devices.d/dummy.cfg
new file mode 100644
index 0000000..855fbfe
--- /dev/null
+++ b/tests/devices.d/dummy.cfg
@@ -0,0 +1,3 @@
+name = "Dummy fence device configuration"
+agent = "/home/marx/GIT/fence-agents/agents/dummy/fence_dummy"
+[options]
diff --git a/tests/devices.d/invalid-missing_option.cfg b/tests/devices.d/invalid-missing_option.cfg
new file mode 100644
index 0000000..0805fdc
--- /dev/null
+++ b/tests/devices.d/invalid-missing_option.cfg
@@ -0,0 +1,4 @@
+name = "Invalid device definition: Both short and long options are missing"
+agent = "/bin/true"
+[options]
+ login = "foo"
diff --git a/tests/devices.d/true-with_action.cfg b/tests/devices.d/true-with_action.cfg
new file mode 100644
index 0000000..d95c9fe
--- /dev/null
+++ b/tests/devices.d/true-with_action.cfg
@@ -0,0 +1,8 @@
+name = "Dummy fence device configuration"
+agent = "/bin/true"
+[options]
+ login = [ "foo", "--username", "-l" ]
+ passwd = [ "bar", "--password", "-p" ]
+ ipaddr = [ "fence.example.com", "--ip", "-a" ]
+ port = [ "1", "--plug" ]
+ action = [ "status", "--action", "-o" ]
diff --git a/tests/devices.d/true.cfg b/tests/devices.d/true.cfg
new file mode 100644
index 0000000..4ba0aa5
--- /dev/null
+++ b/tests/devices.d/true.cfg
@@ -0,0 +1,8 @@
+name = "Dummy fence device configuration"
+agent = "/bin/true"
+[options]
+ login = [ "foo", "--username", "-l" ]
+ passwd = [ "bar", "--password", "-p" ]
+ ipaddr = [ "fence.example.com", "--ip", "-a" ]
+ port = [ "1", "--plug" ]
+
diff --git a/tests/fence_testing.py b/tests/fence_testing.py
new file mode 100755
index 0000000..14cfe0c
--- /dev/null
+++ b/tests/fence_testing.py
@@ -0,0 +1,126 @@
+""" Library for fence agents testing via predefined scenarios """
+from configobj import ConfigObj
+import re, sys, os
+
+EC_CONFIG_FAIL = 1
+
+def _prepare_command(agent_file, method):
+ """ Parse configuration of fence device and prepare (command + STDIN values) to execute.
+
+ Fence device configuration is used to generate a command which can be executed.
+ Because fence agents supports several options how to enter data, we can select
+ from three different methods ("stdin", "getopt" - short options, "longopt").
+ When method "stdin" is used then this function will generate also text which should
+ be entered on STDIN instead of command itself.
+
+ Example of agent definition:
+ name = "Dummy fence device configuration"
+ agent = "/bin/true"
+ [options]
+ login = [ "foo", "--username", "-l" ]
+ passwd = [ "bar", "--password", "-p" ]
+ ipaddr = [ "fence.example.com", "--ip", "-a" ]
+ port = [ "1", "--plug" ]
+ """
+ assert (method in ["stdin", "getopt", "longopt"]), "Invalid method entered"
+
+ config = ConfigObj(agent_file, unrepr = True)
+
+ assert ("agent" in config), "Fence agent has to be defined"
+ final_command = config["agent"]
+ stdin_values = None
+
+ for opt in list(config["options"].keys()):
+ assert isinstance(config["options"][opt], list), "Option %s have to have at least value and longopt"% (opt)
+ assert len(config["options"][opt]) >= 2, "Option %s have to have at least value and longopt"% (opt)
+ value = config["options"][opt][0]
+ if opt == "action":
+ ## ignore action as it is not part of fence device definition
+ continue
+
+ if method == "stdin":
+ option = opt
+ if stdin_values == None:
+ stdin_values = ""
+ stdin_values += option + "=" + value + "\n"
+ elif method == "longopt":
+ option = config["options"][opt][1]
+ final_command += " " + option + " " + value
+ elif method == "getopt":
+ if len(config["options"][opt]) == (2 + 1):
+ option = config["options"][opt][2]
+ else:
+ option = config["options"][opt][1]
+ final_command += " " + option + " " + value
+
+ return (final_command, stdin_values)
+
+def test_action(agent, action_file, method, verbose = False):
+ """ Run defined sequence of actions on a given fence agent.
+
+ This function will run one set of test on a fence agent. Test itself consists of
+ sequence of action and expected return codes. User can select from actions supported
+ by fence agent (on, off, reboot, list, status, monitor) and sleep(X) command where X
+ is in seconds and determine the length of pause between commands. Each action has to
+ have defined regular expression which define acceptable return codes from fence agent
+ or sleep.
+
+ Example of action configuration file:
+ name = "Simple Status"
+ actions = [ { "command" : "status", "return_code" : "^[02]$" }, { "command" : "sleep(1)", "return_code" : "^0$" } ]
+ """
+ re_sleep_command = re.compile('sleep\(([0-9]+)\)', re.IGNORECASE)
+ config = ConfigObj(action_file, unrepr = True)
+
+ (command, stdin_options) = _prepare_command(agent, method)
+
+ for action in config["actions"]:
+ assert "command" in action, "Action %s need to have defined 'command'"% (action_file)
+ assert "return_code" in action, "Command %s (in %s) need to have 'return_code' defined"% (action_file, action["command"])
+
+ sleep_wait = None
+ current_command = None
+ current_stdin_options = None
+
+ if not (action["command"] in [ "status", "reboot", "on", "off", "list", "monitor" ]):
+ is_sleep = re.search(re_sleep_command, action["command"])
+ if is_sleep != None:
+ sleep_wait = is_sleep.group(1)
+ else:
+ sys.stderr.write("ERROR: %s contains unsupported action \"%s\"\n"% (action_file, action["command"]))
+ sys.exit(1)
+
+ if sleep_wait != None:
+ current_command = "/bin/sleep " + sleep_wait
+ current_stdin_options = None
+ else:
+ current_command = command
+ current_stdin_options = stdin_options
+
+ if method == "stdin":
+ if current_stdin_options == None:
+ current_stdin_options = ""
+ current_stdin_options += "action=%s"% (action["command"])
+ elif method == "longopt":
+ current_command += " --action=%s"% (action["command"])
+ elif method == "getopt":
+ current_command += " -o %s"% (action["command"])
+
+ # @note: Broken pipe can occur here and I'm not sure why - non-deterministic
+ if method == "stdin" and sleep_wait == None:
+ current_command = "printf \"" + current_stdin_options + "\" | " + current_command
+
+ if verbose == False:
+ result = os.system(current_command + " &> /dev/null")
+ else:
+ print(current_command)
+ result = os.system(current_command)
+ exitcode = (result >> 8) & 0xFF
+
+ is_valid_result_code = re.search(action["return_code"], str(exitcode), re.IGNORECASE)
+
+ if is_valid_result_code == None:
+ print(("TEST FAILED: %s failed on %s when using (%s)\n"% (agent, action_file, method)))
+ print(("TEST INFO: %s returns %s\n"% (action["command"], str(exitcode))))
+ return
+ print(("TEST PASSED: %s worked on %s (%s)\n"% (agent, action_file, method)))
diff --git a/tests/fence_testing_test.py b/tests/fence_testing_test.py
new file mode 100755
index 0000000..36b2a5e
--- /dev/null
+++ b/tests/fence_testing_test.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+import unittest
+import fence_testing
+
+class TestPrepareCommand(unittest.TestCase):
+ DEVICE_MISSING_OPTION = "devices.d/invalid-missing_option.cfg"
+ DEVICE_CORRECT = "devices.d/true.cfg"
+ DEVICE_CORRECT_WITH_ACTION = "devices.d/true-with_action.cfg"
+
+ def test_missing_device(self):
+ self.assertRaises(fence_testing._prepare_command, None, "getopt")
+
+ def test_missing_option(self):
+ self.assertRaises(AssertionError, fence_testing._prepare_command, self.DEVICE_MISSING_OPTION, "stdin")
+
+ def test_valid_methods(self):
+ fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ fence_testing._prepare_command(self.DEVICE_CORRECT, "longopt")
+ fence_testing._prepare_command(self.DEVICE_CORRECT, "stdin")
+
+ def test_invalid_method(self):
+ self.assertRaises(AssertionError, fence_testing._prepare_command, self.DEVICE_CORRECT, "invalid")
+
+ def test_is_action_ignored(self):
+ (command1, _) = fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ (command2, _) = fence_testing._prepare_command(self.DEVICE_CORRECT_WITH_ACTION, "getopt")
+ self.assertEqual(command1, command2)
+
+ def test_is_stdin_empty(self):
+ (_, stdin) = fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ self.assertEqual(None, stdin)
+ (_, stdin) = fence_testing._prepare_command(self.DEVICE_CORRECT, "longopt")
+ self.assertEqual(None, stdin)
+
+ def test_prepared_command_getopt(self):
+ ## Test also fallback to longopt if short is not present
+ (command, _) = fence_testing._prepare_command(self.DEVICE_CORRECT, "getopt")
+ self.assertEqual("/bin/true -l foo -p bar -a fence.example.com --plug 1", command)
+
+ def test_prepared_command_longopt(self):
+ (command, _) = fence_testing._prepare_command(self.DEVICE_CORRECT, "longopt")
+ self.assertEqual("/bin/true --username foo --password bar --ip fence.example.com --plug 1", command)
+
+ def test_prepared_command_stdin(self):
+ (command, stdin) = fence_testing._prepare_command(self.DEVICE_CORRECT, "stdin")
+ self.assertEqual("/bin/true", command)
+ self.assertEqual("login=foo\npasswd=bar\nipaddr=fence.example.com\nport=1\n", stdin)
+
+class TestTestAction(unittest.TestCase):
+ def test_valid_actions(self):
+ pass
+
+ def test_invalid_actions(self):
+ pass
+
+ def test_valid_return_code(self):
+ pass
+
+ def test_invalid_return_code(self):
+ pass
+
+ def test_valid_re_contains(self):
+ pass
+
+ def test_invalid_re_contains(self):
+ pass
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test-apc2.py b/tests/test-apc2.py
new file mode 100755
index 0000000..bb5aefd
--- /dev/null
+++ b/tests/test-apc2.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ DEVICE = "devices.d/apc-v2.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+ ACT_LIST = "actions.d/list.cfg"
+
+ test_action(DEVICE, ACT_STATUS, "getopt")
+ test_action(DEVICE, ACT_ONOFF, "stdin")
+ test_action(DEVICE, ACT_LIST, "getopt")
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/tests/test-apc5.py b/tests/test-apc5.py
new file mode 100755
index 0000000..6cea3b1
--- /dev/null
+++ b/tests/test-apc5.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ DEVICE = "devices.d/apc-v5.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+ ACT_LIST = "actions.d/list.cfg"
+
+ test_action(DEVICE, ACT_STATUS, "getopt", verbose=1)
+# test_action(DEVICE, ACT_ONOFF, "stdin")
+ test_action(DEVICE, ACT_LIST, "getopt")
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/tests/test-drac4.py b/tests/test-drac4.py
new file mode 100755
index 0000000..75c24c5
--- /dev/null
+++ b/tests/test-drac4.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ DRAC4 = "devices.d/dell-drac-4I.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+
+ test_action(DRAC4, ACT_STATUS, "getopt")
+ test_action(DRAC4, ACT_ONOFF, "stdin")
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/tests/test-multi-apc2.py b/tests/test-multi-apc2.py
new file mode 100755
index 0000000..7ab9754
--- /dev/null
+++ b/tests/test-multi-apc2.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ DEVICE = "devices.d/multi-apc-v2.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+ ACT_LIST = "actions.d/list.cfg"
+
+ test_action(DEVICE, ACT_STATUS, "getopt")
+ test_action(DEVICE, ACT_ONOFF, "stdin")
+ test_action(DEVICE, ACT_LIST, "getopt")
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/tests/test.py b/tests/test.py
new file mode 100755
index 0000000..8e82ed9
--- /dev/null
+++ b/tests/test.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+from fence_testing import test_action
+
+def main():
+ ## @todo: utility1 - run single 'agent' 'action' 'method'
+ ## @todo: utility2 - run complex tests (using utility1?) -> file with test suites
+
+ AGENTDEF = "devices.d/true.cfg"
+ DUMMYDEF = "devices.d/dummy.cfg"
+
+ ACT_STATUS = "actions.d/status.cfg"
+ ACT_ONOFF = "actions.d/power-on-off.cfg"
+
+# test_action(AGENTDEF, ACTIONDEF, "stdin")
+# test_action(AGENTDEF, ACTIONDEF, "getopt")
+ test_action(DUMMYDEF, ACT_STATUS, "getopt")
+ test_action(DUMMYDEF, ACT_ONOFF, "getopt")
+
+if __name__ == "__main__":
+ main() \ No newline at end of file