summaryrefslogtreecommitdiffstats
path: root/agents
diff options
context:
space:
mode:
Diffstat (limited to 'agents')
-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
174 files changed, 67448 insertions, 0 deletions
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()