Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3154422
fence_vmware_rest.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
fence_vmware_rest.py
View Options
#!@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"
in
opt
or
"--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"
in
opt
or
"--ssl-secure"
in
opt
:
conn
.
setopt
(
pycurl
.
SSL_VERIFYPEER
,
1
)
conn
.
setopt
(
pycurl
.
SSL_VERIFYHOST
,
2
)
if
"--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
()
File Metadata
Details
Attached
Mime Type
text/x-script.python
Expires
Wed, Feb 26, 1:18 PM (21 h, 48 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1465378
Default Alt Text
fence_vmware_rest.py (5 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment