diff -uNr a/configure.ac b/configure.ac --- a/configure.ac 2017-10-05 10:21:12.966801280 +0200 +++ b/configure.ac 2017-10-05 10:22:01.993319558 +0200 @@ -267,6 +267,7 @@ fence/agents/apc_snmp/Makefile fence/agents/amt/Makefile fence/agents/amt_ws/Makefile + fence/agents/aws/Makefile fence/agents/bladecenter/Makefile fence/agents/brocade/Makefile fence/agents/cisco_mds/Makefile diff -uNr a/fence/agents/aws/fence_aws.py b/fence/agents/aws/fence_aws.py --- a/fence/agents/aws/fence_aws.py 1970-01-01 01:00:00.000000000 +0100 +++ b/fence/agents/aws/fence_aws.py 2017-08-29 12:01:39.187348926 +0200 @@ -0,0 +1,139 @@ +#!/usr/bin/python -tt + +import sys, re +import logging +import atexit +sys.path.append("/usr/share/fence") +from fencing import * +from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay + +try: + import boto3 + from botocore.exceptions import ClientError, EndpointConnectionError, NoRegionError +except: + pass + +#BEGIN_VERSION_GENERATION +RELEASE_VERSION="Fence agent for AWS (Amazon Web Services)" +REDHAT_COPYRIGHT="" +BUILD_DATE="" +#END_VERSION_GENERATION + +def get_nodes_list(conn, options): + result = {} + try: + for instance in conn.instances.all(): + result[instance.id] = ("", None) + except ClientError: + fail_usage("Failed: Incorrect Access Key or Secret Key.") + except EndpointConnectionError: + fail_usage("Failed: Incorrect Region.") + + return result + +def get_power_status(conn, options): + try: + instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [options["--plug"]]}]) + state = list(instance)[0].state["Name"] + if state == "running": + return "on" + elif state == "stopped": + return "off" + else: + return "unknown" + + except ClientError: + fail_usage("Failed: Incorrect Access Key or Secret Key.") + except EndpointConnectionError: + fail_usage("Failed: Incorrect Region.") + except IndexError: + return "fail" + +def set_power_status(conn, options): + if (options["--action"]=="off"): + conn.instances.filter(InstanceIds=[options["--plug"]]).stop(Force=True) + elif (options["--action"]=="on"): + conn.instances.filter(InstanceIds=[options["--plug"]]).start() + + +def define_new_opts(): + all_opt["region"] = { + "getopt" : "r:", + "longopt" : "region", + "help" : "-r, --region=[name] Region, e.g. us-east-1", + "shortdesc" : "Region.", + "required" : "0", + "order" : 2 + } + all_opt["access_key"] = { + "getopt" : "a:", + "longopt" : "access-key", + "help" : "-a, --access-key=[name] Access Key", + "shortdesc" : "Access Key.", + "required" : "0", + "order" : 3 + } + all_opt["secret_key"] = { + "getopt" : "s:", + "longopt" : "secret-key", + "help" : "-s, --secret-key=[name] Secret Key", + "shortdesc" : "Secret Key.", + "required" : "0", + "order" : 4 + } + +# Main agent method +def main(): + conn = None + + device_opt = ["port", "no_password", "region", "access_key", "secret_key"] + + atexit.register(atexit_handler) + + define_new_opts() + + all_opt["power_timeout"]["default"] = "60" + + options = check_input(device_opt, process_input(device_opt)) + + docs = {} + docs["shortdesc"] = "Fence agent for AWS (Amazon Web Services)" + docs["longdesc"] = "fence_aws is an I/O Fencing agent for AWS (Amazon Web\ +Services). It uses the boto3 library to connect to AWS.\ +\n.P\n\ +boto3 can be configured with AWS CLI or by creating ~/.aws/credentials.\n\ +For instructions see: https://boto3.readthedocs.io/en/latest/guide/quickstart.html#configuration" + docs["vendorurl"] = "http://www.amazon.com" + show_docs(options, docs) + + run_delay(options) + + if "--region" in options and "--access-key" in options and "--secret-key" in options: + region = options["--region"] + access_key = options["--access-key"] + secret_key = options["--secret-key"] + try: + conn = boto3.resource('ec2', region_name=region, + aws_access_key_id=access_key, + aws_secret_access_key=secret_key) + except NameError: + fail_usage("Failed: boto3 Python library not available") + except: + fail_usage("Failed: Unable to connect to AWS. Check your configuration.") + else: + # If setup with "aws configure" or manually in + # ~/.aws/credentials + try: + conn = boto3.resource('ec2') + except NameError: + fail_usage("Failed: boto3 Python library not available") + except: + # If any of region/access/secret are missing + fail_usage("Failed: Unable to connect to AWS. Check your configuration.") + + # Operate the fencing device + result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list) + sys.exit(result) + +if __name__ == "__main__": + main() diff -uNr a/fence/agents/aws/Makefile.am b/fence/agents/aws/Makefile.am --- a/fence/agents/aws/Makefile.am 1970-01-01 01:00:00.000000000 +0100 +++ b/fence/agents/aws/Makefile.am 2017-08-29 10:57:41.315547575 +0200 @@ -0,0 +1,17 @@ +MAINTAINERCLEANFILES = Makefile.in + +TARGET = fence_aws + +SRC = $(TARGET).py + +EXTRA_DIST = $(SRC) + +sbin_SCRIPTS = $(TARGET) + +man_MANS = $(TARGET).8 + +FENCE_TEST_ARGS = -r test -a test -s test -n 1 + +include $(top_srcdir)/make/fencebuild.mk +include $(top_srcdir)/make/fenceman.mk +include $(top_srcdir)/make/agentpycheck.mk diff -uNr a/tests/data/metadata/fence_aws.xml b/tests/data/metadata/fence_aws.xml --- a/tests/data/metadata/fence_aws.xml 1970-01-01 01:00:00.000000000 +0100 +++ b/tests/data/metadata/fence_aws.xml 2017-08-29 10:52:48.250543883 +0200 @@ -0,0 +1,111 @@ + + +fence_aws is an I/O Fencing agent for AWS (Amazon WebServices). It uses the boto3 library to connect to AWS. +.P +boto3 can be configured with AWS CLI or by creating ~/.aws/credentials. +For instructions see: https://boto3.readthedocs.io/en/latest/guide/quickstart.html#configuration +http://www.amazon.com + + + + + Fencing Action + + + + + Physical plug number, name of virtual machine or UUID + + + + + Physical plug number, name of virtual machine or UUID + + + + + Region. + + + + + Access Key. + + + + + Secret Key. + + + + + Verbose mode + + + + + Write debug information to given file + + + + + Write debug information to given file + + + + + Display version information and exit + + + + + Display help and exit + + + + + Separator for CSV created by operation list + + + + + Test X seconds for status change after ON/OFF + + + + + Wait X seconds after issuing ON/OFF + + + + + Wait X seconds for cmd prompt after issuing command + + + + + Wait X seconds before fencing is started + + + + + Wait X seconds for cmd prompt after login + + + + + Count of attempts to retry power on + + + + + + + + + + + + + +