-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfence_cxs.py
executable file
·235 lines (206 loc) · 7.93 KB
/
fence_cxs.py
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#!/usr/bin/env python
#
#############################################################################
# Copyright 2011 Matt 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
#############################################################################
# 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, string, getopt
import XenAPI
def usage():
print "Usage: fence_cxs [-hv] [-a <action>] -l <login username> -p <login password> -s <session url> [-u <UUID>]"
print "Where:-"
print " -a : Specifies the action to perfom. Can be any of \"on|off|reboot|status|list\". Defaults to \"status\"."
print " -h : Print this help message."
print " -l : The username for the XenServer host."
print " -p : The password for the XenServer host."
print " -s : The URL of the web interface on the XenServer host."
print " -U : The UUID of the virtual machine to fence or query. Defaults to the empty string which will return"
print " the status of all hosts when action is set to \"status\". If the action is set to \"on|off|reboot\""
print " then the UUID must be specified."
# Process command line options and populate the config array
def process_opts():
config = {
"action" : "status",
"session_url" : "",
"session_user" : "",
"session_pass" : "",
"uuid" : "",
"name" : "",
"verbose" : False
}
# If we have at least one argument then we want to parse the command line using getopts
if len(sys.argv) > 1:
try:
opts, args = getopt.getopt(sys.argv[1:], "a:hl:n:s:p:U:v", ["help", "verbose", "action=", "session-url=", "login-name=", "name=", "password=", "uuid="])
except getopt.GetoptError, err:
# We got an unrecognised option, so print he help message and exit
print str(err)
usage()
sys.exit(1)
for opt, arg in opts:
if opt in ("-v", "--verbose"):
config["verbose"] = True
elif opt in ("-a", "--action"):
config["action"] = clean_action(arg)
elif opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-s", "--session-url"):
config["session_url"] = arg
elif opt in ("-l", "--login-name"):
config["session_user"] = arg
elif opt in ("-n", "--name"):
config["name"] = arg
elif opt in ("-p", "--password"):
config["session_pass"] = arg
elif opt in ("-U", "--uuid"):
config["uuid"] = arg.lower()
else:
assert False, "unhandled option"
# Otherwise process stdin for parameters. This is to handle the Red Hat clustering
# mechanism where by fenced passes in name/value pairs instead of using command line
# options.
else:
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]
name = clean_param_name(name)
if name == "action":
value = clean_action(value)
if name in config:
config[name] = value
else:
sys.stderr.write("Parse error: Ignoring unknown option '"+line+"'\n")
if( config["session_url"] == "" or config["session_user"] == "" or config["session_pass"] == "" ):
print "You must specify the session url, username and password.";
usage();
sys.exit(2);
return config
# why, well just to be nice. Given an action will return the corresponding
# value that the rest of the script uses.
def clean_action(action):
if action.lower() in ("on", "poweron", "powerup"):
return "on"
elif action.lower() in ("off", "poweroff", "powerdown"):
return "off"
elif action.lower() in ("reboot", "reset", "restart"):
return "reboot"
elif action.lower() in ("status", "powerstatus", "list"):
return "status"
else:
print "Bad action", action
usage()
exit(4)
# why, well just to be nice. Given a parameter will return the corresponding
# value that the rest of the script uses.
def clean_param_name(name):
if name.lower() in ("action", "operation", "op"):
return "action"
elif name.lower() in ("session_user", "login", "login-name", "login_name", "user", "username", "session-user"):
return "session_user"
elif name.lower() in ("session_pass", "pass", "passwd", "password", "session-pass"):
return "session_pass"
elif name.lower() in ("session_url", "url", "session-url"):
return "session_url"
else:
# we should never get here as getopt should handle the checking of this input.
print "Bad parameter specified", name
usage()
exit(5)
# Print the power status of a VM. If no UUID is given, then all VM's are queried
def get_power_status(session, uuid = "", name = ""):
try:
# If the UUID hasn't been set, then output the status of all
# valid virtual machines.
if( len(uuid) > 0 ):
vms = [session.xenapi.VM.get_by_uuid(uuid)]
elif( len(name) > 0 ):
vms = session.xenapi.VM.get_by_name_label(name)
else:
vms = session.xenapi.VM.get_all()
for vm in vms:
record = session.xenapi.VM.get_record(vm);
# We only want to print out the status for actual virtual machines. The above get_all function
# returns any templates and also the control domain. This is one of the reasons the process
# takes such a long time to list all VM's. Hopefully there is a way to filter this in the
# request packet in the future.
if not(record["is_a_template"]) and not(record["is_control_domain"]):
name = record["name_label"]
print "UUID:", record["uuid"], "NAME:", name, "POWER STATUS:", record["power_state"]
except Exception, exn:
print str(exn);
def set_power_status(session, uuid, name, action):
try:
vm = None
if( len(uuid) > 0 ):
vm = session.xenapi.VM.get_by_uuid(uuid)
elif( len(name) > 0 ):
vm_arr = session.xenapi.VM.get_by_name_label(name)
if( len(vm_arr) == 1 ):
vm = vm_arr[0]
else
raise Exception("Multiple VM's have that name. Use UUID instead.")
if( vm != None ):
record = session.xenapi.VM.get_record(vm);
if not(record["is_a_template"]) and not(record["is_control_domain"]):
if( action == "on" ):
session.xenapi.VM.start(vm, False, True)
elif( action == "off" ):
session.xenapi.VM.hard_shutdown(vm)
elif( action == "reboot" ):
session.xenapi.VM.hard_reboot(vm)
else:
raise Exception("Bad power status");
except Exception, exn:
print str(exn);
def main():
config = process_opts();
session = session_start(config["session_url"]);
session_login(session, config["session_user"], config["session_pass"]);
if( config["action"] == "status" ):
get_power_status(session, config["uuid"], config["name"])
else:
if( config["verbose"] ):
print "Power status before action"
get_power_status(session, config["uuid"])
set_power_status(session, config["uuid"], config["name"], config["action"])
if( config["verbose"] ):
print "Power status after action"
get_power_status(session, config["uuid"])
# Function to initiate the session with the XenServer system
def session_start(url):
try:
session = XenAPI.Session(url);
except Exception, exn:
print str(exn);
sys.exit(3);
return session;
def session_login(session, username, password):
try:
session.xenapi.login_with_password(username, password);
except Exception, exn:
print str(exn);
sys.exit(3);
if __name__ == "__main__":
main()
# vim:set ts=4 sw=4