diff --git a/agents/aws/fence_aws.py b/agents/aws/fence_aws.py index 647b66fc..74321e8e 100644 --- a/agents/aws/fence_aws.py +++ b/agents/aws/fence_aws.py @@ -1,126 +1,134 @@ #!@PYTHON@ -tt import sys, re import logging import atexit sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * -from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay +from fencing import fail, fail_usage, run_delay, EC_STATUS import boto3 from botocore.exceptions import ClientError, EndpointConnectionError, NoRegionError 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.") + except Exception as e: + logging.error("Failed to get node list: %s", e) 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" + fail(EC_STATUS) + except Exception as e: + logging.error("Failed to get power status: %s", e) + fail(EC_STATUS) 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() - + try: + if (options["--action"]=="off"): + conn.instances.filter(InstanceIds=[options["--plug"]]).stop(Force=True) + elif (options["--action"]=="on"): + conn.instances.filter(InstanceIds=[options["--plug"]]).start() + except Exception as e: + logging.error("Failed to power %s %s: %s", \ + options["--action"], options["--plug"], e) def define_new_opts(): all_opt["region"] = { "getopt" : "r:", "longopt" : "region", - "help" : "-r, --region=[name] Region, e.g. us-east-1", + "help" : "-r, --region=[region] 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", + "help" : "-a, --access-key=[key] 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", + "help" : "-s, --secret-key=[key] 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: - fail_usage("Failed: Unable to connect to AWS. Check your configuration.") + except Exception as e: + fail_usage("Failed: Unable to connect to AWS: " + str(e)) else: # If setup with "aws configure" or manually in # ~/.aws/credentials try: conn = boto3.resource('ec2') - except: + except Exception as e: # If any of region/access/secret are missing - fail_usage("Failed: Unable to connect to AWS. Check your configuration.") + fail_usage("Failed: Unable to connect to AWS: " + str(e)) # 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 --git a/tests/data/metadata/fence_aws.xml b/tests/data/metadata/fence_aws.xml index 4dea4418..5e5d5d99 100644 --- a/tests/data/metadata/fence_aws.xml +++ b/tests/data/metadata/fence_aws.xml @@ -1,117 +1,117 @@ fence_aws is an I/O Fencing agent for AWS (Amazon WebServices). It uses the boto3 library to connect to AWS. 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 on device, UUID or identification of machine Physical plug number on device, UUID or identification of machine - + Region. - + Access Key. - + Secret Key. Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. 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 'list' operation Wait X seconds before fencing is started Wait X seconds for cmd prompt after login 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 Count of attempts to retry power on