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
|
#!@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()
|