This file is indexed.

/usr/sbin/fence_apc_snmp is in fence-agents 3.1.5-2ubuntu2.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/usr/bin/python

# The Following agent has been tested on:
# - APC Switched Rack PDU (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) - SNMP v1
# - APC Web/SNMP Management Card (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) - SNMP v1 and v3 (noAuthNoPrivacy,authNoPrivacy, authPrivacy)
# - APC Switched Rack PDU (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) - SNMP v1

import sys, re, pexpect
sys.path.append("/usr/share/fence")
from fencing import *
from fencing_snmp import *

#BEGIN_VERSION_GENERATION
RELEASE_VERSION="3.1.5"
BUILD_DATE="(built Mon Feb 6 23:36:21 UTC 2012)"
REDHAT_COPYRIGHT="Copyright (C) Red Hat, Inc. 2004-2010 All rights reserved."
#END_VERSION_GENERATION

### 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
device=None

# Port ID
port_id=None
# Switch ID
switch_id=None

# Classes describing Device params
class ApcRPDU:
	# 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:
	# 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:
	# 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

### FUNCTIONS ###
def apc_set_device(conn,options):
	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,
		    None:ApcMS}

	# First resolve type of APC
	apc_type=conn.walk(OID_SYS_OBJECT_ID)

	if (not ((len(apc_type)==1) and (agents_dir.has_key(apc_type[0][1])))):
		apc_type=[[None,None]]

	device=agents_dir[apc_type[0][1]]

	conn.log_command("Trying %s"%(device.ident_str))

def apc_resolv_port_id(conn,options):
	global port_id,switch_id,device

	if (device==None):
		apc_set_device(conn,options)

	# Now we resolv port_id/switch_id
	if ((options["-n"].isdigit()) and ((not device.has_switches) or (options["-s"].isdigit()))):
		port_id=int(options["-n"])

		if (device.has_switches):
			switch_id=int(options["-s"])
	else:
		table=conn.walk(device.outlet_table_oid,30)

		for x in table:
			if (x[1].strip('"')==options["-n"]):
				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["-n"]))

def get_power_status(conn,options):
	global port_id,switch_id,device

	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):
	global port_id,switch_id,device

	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["-o"]=="on" and device.turn_on or device.turn_off))


def get_outlets_status(conn, options):
	global device

	result={}

	if (device==None):
		apc_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

# Define new options
def apc_snmp_define_defaults():
	all_opt["snmp_version"]["default"]="1"
	all_opt["community"]["default"]="private"

# Main agent method
def main():
	device_opt = [ "help", "version", "agent", "quiet", "verbose", "debug",
		       "action", "ipaddr", "login", "passwd", "passwd_script",
		       "test", "port", "separator", "no_login", "no_password",
		       "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level",
		       "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script",
		       "udpport","inet4_only","inet6_only",
		       "power_timeout", "shell_timeout", "login_timeout", "power_wait" ]

	atexit.register(atexit_handler)

	snmp_define_defaults ()
	apc_snmp_define_defaults()

	options=check_input(device_opt,process_input(device_opt))

        ## Support for -n [switch]:[plug] notation that was used before
	if ((options.has_key("-n")) and (-1 != options["-n"].find(":"))):
		(switch, plug) = options["-n"].split(":", 1)
		if ((switch.isdigit()) and (plug.isdigit())):
		        options["-s"] = switch
			options["-n"] = plug

	if (not (options.has_key("-s"))):
		options["-s"]="1"

	docs = { }
	docs["shortdesc"] = "Fence agent for APC over SNMP"
	docs["longdesc"] = "fence_apc_snmp is an I/O Fencing agent \
which can be used with the APC 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://www.apc.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()