forked from ClusterLabs/fence-agents
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
364 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
#!@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 | ||
|
||
state = {"POWERED_ON": "on", 'POWERED_OFF': "off"} | ||
|
||
def get_power_status(conn, options): | ||
res = send_command(conn, "vcenter/vm?filter.names={}".format(options["--plug"]))["value"] | ||
|
||
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"]] | ||
|
||
send_command(conn, "vcenter/vm/{}/power/{}".format(options["id"], action), "POST") | ||
|
||
def get_list(conn, options): | ||
outlets = {} | ||
|
||
res = send_command(conn, "vcenter/vm") | ||
|
||
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): | ||
send_command(conn, "com/vmware/cis/session", "DELETE") | ||
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 Exception(e[1]) | ||
|
||
rc = conn.getinfo(pycurl.HTTP_CODE) | ||
result = web_buffer.getvalue().decode() | ||
|
||
web_buffer.close() | ||
|
||
if len(result) > 0: | ||
result = json.loads(result) | ||
|
||
if rc != 200: | ||
raise Exception("{}: {}".format(rc, result["value"]["messages"][0]["default_message"])) | ||
|
||
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} | ||
|
||
|
||
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 REST API" | ||
docs["longdesc"] = "fence_vmware_rest is an I/O Fencing agent which can be \ | ||
used with VMware 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
<?xml version="1.0" ?> | ||
<resource-agent name="fence_vmware_rest" shortdesc="Fence agent for VMware REST API" > | ||
<longdesc>fence_vmware_rest is an I/O Fencing agent which can be used with VMware API to fence virtual machines.</longdesc> | ||
<vendor-url>https://www.vmware.com</vendor-url> | ||
<parameters> | ||
<parameter name="action" unique="0" required="1"> | ||
<getopt mixed="-o, --action=[action]" /> | ||
<content type="string" default="reboot" /> | ||
<shortdesc lang="en">Fencing action</shortdesc> | ||
</parameter> | ||
<parameter name="inet4_only" unique="0" required="0"> | ||
<getopt mixed="-4, --inet4-only" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Forces agent to use IPv4 addresses only</shortdesc> | ||
</parameter> | ||
<parameter name="inet6_only" unique="0" required="0"> | ||
<getopt mixed="-6, --inet6-only" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Forces agent to use IPv6 addresses only</shortdesc> | ||
</parameter> | ||
<parameter name="ip" unique="0" required="1" obsoletes="ipaddr"> | ||
<getopt mixed="-a, --ip=[ip]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">IP address or hostname of fencing device</shortdesc> | ||
</parameter> | ||
<parameter name="ipaddr" unique="0" required="1" deprecated="1"> | ||
<getopt mixed="-a, --ip=[ip]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">IP address or hostname of fencing device</shortdesc> | ||
</parameter> | ||
<parameter name="ipport" unique="0" required="0"> | ||
<getopt mixed="-u, --ipport=[port]" /> | ||
<content type="integer" default="80" /> | ||
<shortdesc lang="en">TCP/UDP port to use for connection with device</shortdesc> | ||
</parameter> | ||
<parameter name="login" unique="0" required="1" deprecated="1"> | ||
<getopt mixed="-l, --username=[name]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Login name</shortdesc> | ||
</parameter> | ||
<parameter name="notls" unique="0" required="0"> | ||
<getopt mixed="-t, --notls" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Disable TLS negotiation and force SSL3.0. This should only be used for devices that do not support TLS1.0 and up.</shortdesc> | ||
</parameter> | ||
<parameter name="passwd" unique="0" required="0" deprecated="1"> | ||
<getopt mixed="-p, --password=[password]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Login password or passphrase</shortdesc> | ||
</parameter> | ||
<parameter name="passwd_script" unique="0" required="0" deprecated="1"> | ||
<getopt mixed="-S, --password-script=[script]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Script to run to retrieve password</shortdesc> | ||
</parameter> | ||
<parameter name="password" unique="0" required="0" obsoletes="passwd"> | ||
<getopt mixed="-p, --password=[password]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Login password or passphrase</shortdesc> | ||
</parameter> | ||
<parameter name="password_script" unique="0" required="0" obsoletes="passwd_script"> | ||
<getopt mixed="-S, --password-script=[script]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Script to run to retrieve password</shortdesc> | ||
</parameter> | ||
<parameter name="plug" unique="0" required="1" obsoletes="port"> | ||
<getopt mixed="-n, --plug=[id]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc> | ||
</parameter> | ||
<parameter name="port" unique="0" required="1" deprecated="1"> | ||
<getopt mixed="-n, --plug=[id]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Physical plug number on device, UUID or identification of machine</shortdesc> | ||
</parameter> | ||
<parameter name="ssl" unique="0" required="0"> | ||
<getopt mixed="-z, --ssl" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc> | ||
</parameter> | ||
<parameter name="ssl_insecure" unique="0" required="0"> | ||
<getopt mixed="--ssl-insecure" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Use SSL connection without verifying certificate</shortdesc> | ||
</parameter> | ||
<parameter name="ssl_secure" unique="0" required="0"> | ||
<getopt mixed="--ssl-secure" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Use SSL connection with verifying certificate</shortdesc> | ||
</parameter> | ||
<parameter name="username" unique="0" required="1" obsoletes="login"> | ||
<getopt mixed="-l, --username=[name]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Login name</shortdesc> | ||
</parameter> | ||
<parameter name="api_path" unique="0" required="0"> | ||
<getopt mixed="--api-path=[path]" /> | ||
<shortdesc lang="en">The path part of the API URL</shortdesc> | ||
</parameter> | ||
<parameter name="quiet" unique="0" required="0"> | ||
<getopt mixed="-q, --quiet" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Disable logging to stderr. Does not affect --verbose or --debug logging to syslog.</shortdesc> | ||
</parameter> | ||
<parameter name="verbose" unique="0" required="0"> | ||
<getopt mixed="-v, --verbose" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Verbose mode</shortdesc> | ||
</parameter> | ||
<parameter name="debug" unique="0" required="0" deprecated="1"> | ||
<getopt mixed="-D, --debug-file=[debugfile]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Write debug information to given file</shortdesc> | ||
</parameter> | ||
<parameter name="debug_file" unique="0" required="0" obsoletes="debug"> | ||
<getopt mixed="-D, --debug-file=[debugfile]" /> | ||
<content type="string" /> | ||
<shortdesc lang="en">Write debug information to given file</shortdesc> | ||
</parameter> | ||
<parameter name="version" unique="0" required="0"> | ||
<getopt mixed="-V, --version" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Display version information and exit</shortdesc> | ||
</parameter> | ||
<parameter name="help" unique="0" required="0"> | ||
<getopt mixed="-h, --help" /> | ||
<content type="boolean" /> | ||
<shortdesc lang="en">Display help and exit</shortdesc> | ||
</parameter> | ||
<parameter name="separator" unique="0" required="0"> | ||
<getopt mixed="-C, --separator=[char]" /> | ||
<content type="string" default="," /> | ||
<shortdesc lang="en">Separator for CSV created by 'list' operation</shortdesc> | ||
</parameter> | ||
<parameter name="delay" unique="0" required="0"> | ||
<getopt mixed="--delay=[seconds]" /> | ||
<content type="second" default="0" /> | ||
<shortdesc lang="en">Wait X seconds before fencing is started</shortdesc> | ||
</parameter> | ||
<parameter name="login_timeout" unique="0" required="0"> | ||
<getopt mixed="--login-timeout=[seconds]" /> | ||
<content type="second" default="5" /> | ||
<shortdesc lang="en">Wait X seconds for cmd prompt after login</shortdesc> | ||
</parameter> | ||
<parameter name="power_timeout" unique="0" required="0"> | ||
<getopt mixed="--power-timeout=[seconds]" /> | ||
<content type="second" default="20" /> | ||
<shortdesc lang="en">Test X seconds for status change after ON/OFF</shortdesc> | ||
</parameter> | ||
<parameter name="power_wait" unique="0" required="0"> | ||
<getopt mixed="--power-wait=[seconds]" /> | ||
<content type="second" default="1" /> | ||
<shortdesc lang="en">Wait X seconds after issuing ON/OFF</shortdesc> | ||
</parameter> | ||
<parameter name="shell_timeout" unique="0" required="0"> | ||
<getopt mixed="--shell-timeout=[seconds]" /> | ||
<content type="second" default="5" /> | ||
<shortdesc lang="en">Wait X seconds for cmd prompt after issuing command</shortdesc> | ||
</parameter> | ||
<parameter name="retry_on" unique="0" required="0"> | ||
<getopt mixed="--retry-on=[attempts]" /> | ||
<content type="integer" default="1" /> | ||
<shortdesc lang="en">Count of attempts to retry power on</shortdesc> | ||
</parameter> | ||
<parameter name="gnutlscli_path" unique="0" required="0"> | ||
<getopt mixed="--gnutlscli-path=[path]" /> | ||
<shortdesc lang="en">Path to gnutls-cli binary</shortdesc> | ||
</parameter> | ||
</parameters> | ||
<actions> | ||
<action name="on" automatic="0"/> | ||
<action name="off" /> | ||
<action name="reboot" /> | ||
<action name="status" /> | ||
<action name="list" /> | ||
<action name="list-status" /> | ||
<action name="monitor" /> | ||
<action name="metadata" /> | ||
<action name="validate-all" /> | ||
</actions> | ||
</resource-agent> |