diff --git a/agents/aws_vpc_net/fence_aws_vpc_net.py b/agents/aws_vpc_net/fence_aws_vpc_net.py new file mode 100644 index 00000000..b1cf299e --- /dev/null +++ b/agents/aws_vpc_net/fence_aws_vpc_net.py @@ -0,0 +1,964 @@ +#!@PYTHON@ -tt + +import sys, re +import json +import atexit +import logging +import time +import requests + +sys.path.append("@FENCEAGENTSLIBDIR@") + +from fencing import * +from fencing import ( + run_delay, + fail, + fail_usage, + EC_STATUS, + EC_GENERIC_ERROR, + SyslogLibHandler +) + +try: + import boto3 + from botocore.exceptions import ConnectionError, ClientError, EndpointConnectionError, NoRegionError +except ImportError: + pass + +# Logger configuration +logger = logging.getLogger() +logger.propagate = False +logger.setLevel(logging.INFO) +logger.addHandler(SyslogLibHandler()) +logging.getLogger('botocore.vendored').propagate = False + +status = { + "running": "on", + "stopped": "off", + "pending": "unknown", + "stopping": "unknown", + "shutting-down": "unknown", + "terminated": "unknown" +} + +def check_sg_modifications(ec2_client, instance_id, options): + """Check if security groups have been modified according to the specified options. + + Args: + ec2_client: The boto3 EC2 client + instance_id: The ID of the EC2 instance + options: Dictionary containing the fencing options + + Returns: + bool: True if all interfaces have been properly modified, False otherwise + """ + try: + state, _, interfaces = get_instance_details(ec2_client, instance_id) + if state == "running": # Only check SGs if instance is running + sg_to_remove = options.get("--secg", "").split(",") if options.get("--secg") else [] + if sg_to_remove: + # Check if all interfaces have had their security groups modified + all_interfaces_fenced = True + for interface in interfaces: + current_sgs = interface["SecurityGroups"] + if "--invert-sg-removal" in options: + # In keep_only mode, check if interface only has the specified groups + if sorted(current_sgs) != sorted(sg_to_remove): + logger.debug(f"Interface {interface['NetworkInterfaceId']} still has different security groups") + all_interfaces_fenced = False + break + else: + # In remove mode, check if specified groups were removed + if any(sg in current_sgs for sg in sg_to_remove): + logger.debug(f"Interface {interface['NetworkInterfaceId']} still has security groups that should be removed") + all_interfaces_fenced = False + break + + if all_interfaces_fenced: + logger.debug("All interfaces have had their security groups successfully modified - considering instance fenced") + return True + except Exception as e: + logger.debug("Failed to check security group modifications: %s", e) + return False + +def get_power_status(conn, options): + logger.debug("Starting status operation") + try: + instance_id = options["--plug"] + ec2_client = conn.meta.client + + # Get the lastfence tag first + lastfence_response = ec2_client.describe_tags( + Filters=[ + {"Name": "resource-id", "Values": [instance_id]}, + {"Name": "key", "Values": ["lastfence"]} + ] + ) + + # If --ignore-tag-write-failure is set, prioritize checking SG modifications + if "--ignore-tag-write-failure" in options: + logger.debug("--ignore-tag-write-failure is set, checking security group modifications first") + if check_sg_modifications(ec2_client, instance_id, options): + logger.info("All interfaces are properly fenced based on security group state, ignoring tag state") + return "off" + logger.debug("Not all interfaces are fenced, proceeding with tag checks") + # Only proceed with tag checks if we haven't determined state from SG modifications + + try: + # If no lastfence tag exists, instance is not fenced + if not lastfence_response["Tags"]: + logger.debug("No lastfence tag found for instance %s - instance is not fenced", instance_id) + return "on" + + lastfence_timestamp = lastfence_response["Tags"][0]["Value"] + except Exception as e: + if "--ignore-tag-write-failure" in options: + logger.warning(f"Failed to check lastfence tag but continuing due to ignore-tag-write-failure: {str(e)}") + # If we can't read tags but --ignore-tag-write-failure is set, rely on SG state + return "on" # Default to "on" to allow fence operation to proceed + raise + + # Check for backup tags with pattern Original_SG_Backup_{instance_id}_* + response = ec2_client.describe_tags( + Filters=[ + {"Name": "resource-id", "Values": [instance_id]}, + {"Name": "key", "Values": [f"Original_SG_Backup_{instance_id}*"]} + ] + ) + + # If no backup tags exist, instance is not fenced (unless --ignore-tag-write-failure handled above) + if not response["Tags"]: + logger.debug("No backup tags found for instance %s - instance is not fenced", instance_id) + return "on" + + # Loop through backup tags to find matching timestamp + for tag in response["Tags"]: + try: + backup_data = json.loads(tag["Value"]) + backup_timestamp = backup_data.get("t") # Using shortened timestamp field + + if not backup_timestamp: + logger.debug("No timestamp found in backup data for tag %s", tag["Key"]) + continue + + # Validate timestamps match + if str(backup_timestamp) == str(lastfence_timestamp): + # Check if security groups were actually modified to confirm fencing + if check_sg_modifications(ec2_client, instance_id, options): + logger.debug("Found matching backup tag %s and verified all interfaces have SG changes - instance is fenced", tag["Key"]) + return "off" + else: + # If we can't verify SG changes but have matching tags, assume fenced for backward compatibility + logger.debug("Found matching backup tag %s but couldn't verify SG changes - assuming instance is fenced", tag["Key"]) + return "off" + + except (json.JSONDecodeError, KeyError) as e: + logger.error(f"Failed to parse backup data for tag {tag['Key']}: {str(e)}") + continue + + logger.debug("No backup tags with matching timestamp found - instance is not fenced") + return "on" + + except ClientError: + fail_usage("Failed: Incorrect Access Key or Secret Key.") + except EndpointConnectionError: + fail_usage("Failed: Incorrect Region.") + except IndexError: + fail(EC_STATUS) + except Exception as e: + logger.error("Failed to get power status: %s", e) + fail(EC_STATUS) + +# Retrieve instance ID for self-check +def get_instance_id(): + """Retrieve the instance ID of the current EC2 instance.""" + try: + token = requests.put( + "http://169.254.169.254/latest/api/token", + headers={"X-aws-ec2-metadata-token-ttl-seconds": "21600"}, + ).content.decode("UTF-8") + instance_id = requests.get( + "http://169.254.169.254/latest/meta-data/instance-id", + headers={"X-aws-ec2-metadata-token": token}, + ).content.decode("UTF-8") + return instance_id + except Exception as err: + logger.error("Failed to retrieve instance ID for self-check: %s", err) + return None + + +# Retrieve instance details +def get_instance_details(ec2_client, instance_id): + """Retrieve instance details including state, VPC, interfaces, and attached SGs.""" + try: + response = ec2_client.describe_instances(InstanceIds=[instance_id]) + instance = response["Reservations"][0]["Instances"][0] + + instance_state = instance["State"]["Name"] + vpc_id = instance["VpcId"] + network_interfaces = instance["NetworkInterfaces"] + + interfaces = [] + for interface in network_interfaces: + try: + interfaces.append( + { + "NetworkInterfaceId": interface["NetworkInterfaceId"], + "SecurityGroups": [sg["GroupId"] for sg in interface["Groups"]], + } + ) + except KeyError as e: + logger.error(f"Malformed interface data: {str(e)}") + continue + + return instance_state, vpc_id, interfaces + + except ClientError as e: + logger.error(f"AWS API error while retrieving instance details: {str(e)}") + raise + except IndexError as e: + logger.error(f"Instance {instance_id} not found or no instances returned: {str(e)}") + raise + except KeyError as e: + logger.error(f"Unexpected response format from AWS API: {str(e)}") + raise + except Exception as e: + logger.error(f"Unexpected error while retrieving instance details: {str(e)}") + raise + +# Check if we are the self-fencing node +def get_self_power_status(conn, instance_id): + try: + instance = conn.instances.filter(Filters=[{"Name": "instance-id", "Values": [instance_id]}]) + state = list(instance)[0].state["Name"] + if state == "running": + logger.debug(f"Captured my ({instance_id}) state and it {state.upper()} - returning OK - Proceeding with fencing") + return "ok" + else: + logger.debug(f"Captured my ({instance_id}) state it is {state.upper()} - returning Alert - Unable to fence other nodes") + return "alert" + + except ClientError: + fail_usage("Failed: Incorrect Access Key or Secret Key.") + except EndpointConnectionError: + fail_usage("Failed: Incorrect Region.") + except IndexError: + return "fail" + +# Create backup tags for each network interface +def create_backup_tag(ec2_client, instance_id, interfaces, timestamp): + """Create tags on the instance to backup original security groups for each network interface. + If the security groups list is too long, it will be split across multiple tags.""" + try: + # Create tags for each network interface + for idx, interface in enumerate(interfaces, 1): + interface_id = interface["NetworkInterfaceId"] + security_groups = interface["SecurityGroups"] + + # Initialize variables for chunking + sg_chunks = [] + current_chunk = [] + + # Strip 'sg-' prefix from all security groups first + stripped_sgs = [sg[3:] if sg.startswith('sg-') else sg for sg in security_groups] + + for sg in stripped_sgs: + # Create a test chunk with the new security group + test_chunk = current_chunk + [sg] + + # Create a test backup object with this chunk + test_backup = { + "n": { + "i": interface_id, + "s": test_chunk, + "c": { + "i": len(sg_chunks), + "t": 1 # Temporary value, will update later + } + }, + "t": timestamp + } + + # Check if adding this SG would exceed the character limit + if len(json.dumps(test_backup)) > 254: + # Current chunk is full, add it to chunks and start a new one + if current_chunk: # Only add if not empty + sg_chunks.append(current_chunk) + current_chunk = [sg] + else: + # Edge case: single SG exceeds limit (shouldn't happen with normal SG IDs) + logger.warning(f"Security group ID {sg} is unusually long") + sg_chunks.append([sg]) + else: + # Add SG to current chunk + current_chunk = test_chunk + + # Add the last chunk if it has any items + if current_chunk: + sg_chunks.append(current_chunk) + + # Update total chunks count and create tags + for chunk_idx, sg_chunk in enumerate(sg_chunks): + + sg_backup = { + "n": { # NetworkInterface shortened to n + "i": interface_id, # ni shortened to i + "s": sg_chunk, # sg shortened to s, with 'sg-' prefix stripped + "c": { # ci shortened to c + "i": chunk_idx, + "t": len(sg_chunks) + } + }, + "t": timestamp # ts shortened to t + } + tag_value = json.dumps(sg_backup) + tag_key = f"Original_SG_Backup_{instance_id}_{timestamp}_{idx}_{chunk_idx}" + + # Create the tag + ec2_client.create_tags( + Resources=[instance_id], + Tags=[{"Key": tag_key, "Value": tag_value}], + ) + + # Verify the tag was created + response = ec2_client.describe_tags( + Filters=[ + {"Name": "resource-id", "Values": [instance_id]}, + {"Name": "key", "Values": [tag_key]} + ] + ) + + if not response["Tags"]: + logger.error(f"Failed to verify creation of backup tag '{tag_key}' for instance {instance_id}") + raise Exception("Backup tag creation could not be verified") + + created_tag_value = response["Tags"][0]["Value"] + if created_tag_value != tag_value: + logger.error(f"Created tag value does not match expected value for instance {instance_id}") + raise Exception("Backup tag value mismatch") + + logger.info(f"Backup tag '{tag_key}' chunk {chunk_idx + 1}/{len(sg_chunks)} created and verified for interface {interface_id}.") + except ClientError as e: + logger.error(f"AWS API error while creating/verifying backup tag: {str(e)}") + raise + except Exception as e: + logger.error(f"Unexpected error while creating/verifying backup tag: {str(e)}") + raise + + +def modify_security_groups(ec2_client, instance_id, sg_list, timestamp, mode="remove", options=None): + """ + Modifies security groups on network interfaces based on the specified mode. + In 'remove' mode: Removes all SGs in sg_list from each interface + In 'keep_only' mode: Keeps only the SGs in sg_list and removes all others + + Args: + ec2_client: The boto3 EC2 client + instance_id: The ID of the EC2 instance + sg_list: List of security group IDs to remove or keep + timestamp: Unix timestamp for backup tag + mode: Either "remove" or "keep_only" to determine operation mode + + Raises: + ClientError: If AWS API calls fail + Exception: For other unexpected errors + """ + try: + # Get instance details + state, _, interfaces = get_instance_details(ec2_client, instance_id) + + # Create a backup tag before making any changes + try: + create_backup_tag(ec2_client, instance_id, interfaces, timestamp) + try: + set_lastfence_tag(ec2_client, instance_id, timestamp) + except Exception as e: + if "--ignore-tag-write-failure" in options: + logger.warning(f"Failed to set lastfence tag but continuing due to --ignore-tag-write-failure: {str(e)}") + logger.info("Will rely on security group state for fencing status") + else: + logger.error(f"Failed to set lastfence tag: {str(e)}") + raise + except Exception as e: + if "--ignore-tag-write-failure" in options: + logger.warning(f"Failed to create backup tag but continuing due to --ignore-tag-write-failure: {str(e)}") + logger.info("Will rely on security group state for fencing status") + else: + logger.error(f"Failed to create backup tag: {str(e)}") + raise + + changed_any = False + for interface in interfaces: + try: + original_sgs = interface["SecurityGroups"] + + if mode == "remove": + # Exclude any SGs that are in sg_list + updated_sgs = [sg for sg in original_sgs if sg not in sg_list] + operation_desc = f"removing {sg_list}" + else: # keep_only mode + # Set interface to only use the specified security groups + updated_sgs = sg_list + operation_desc = f"keeping only {sg_list}" + + # Skip if we'd end up with zero SGs (only in remove mode) + if mode == "remove" and not updated_sgs: + logger.info( + f"Skipping interface {interface['NetworkInterfaceId']}: " + f"removal of {sg_list} would leave 0 SGs." + ) + continue + + # Skip if no changes needed + if updated_sgs == original_sgs: + continue + + logger.info( + f"Updating interface {interface['NetworkInterfaceId']} from {original_sgs} " + f"to {updated_sgs} ({operation_desc})" + ) + + try: + ec2_client.modify_network_interface_attribute( + NetworkInterfaceId=interface["NetworkInterfaceId"], + Groups=updated_sgs + ) + changed_any = True + except ClientError as e: + logger.error( + f"Failed to modify security groups for interface " + f"{interface['NetworkInterfaceId']}: {str(e)}" + ) + continue + + except KeyError as e: + logger.error(f"Malformed interface data: {str(e)}") + continue + + # If we didn't modify anything, raise an error + if not changed_any: + if mode == "remove": + error_msg = f"Security Groups {sg_list} not removed from any interface. Either not found, or removal left 0 SGs." + else: + error_msg = f"Security Groups {sg_list} not found on any interface. No changes made." + logger.error(error_msg) + raise Exception("Failed to modify security groups: " + error_msg) + + # Wait a bit for changes to propagate + time.sleep(5) + + except ClientError as e: + logger.error(f"AWS API error: {str(e)}") + raise + except Exception as e: + logger.error(f"Unexpected error: {str(e)}") + raise + +def restore_security_groups(ec2_client, instance_id): + """ + Restores the original security groups from backup tags to each network interface. + Each network interface's original security groups are stored in a separate backup tag. + All backup tags share the same timestamp as the lastfence tag for validation. + + The process: + 1. Get lastfence tag timestamp + 2. Find all backup tags with matching timestamp + 3. Create a map of interface IDs to their original security groups + 4. Restore each interface's security groups from the map + 5. Clean up matching backup tags and lastfence tag + + Args: + ec2_client: The boto3 EC2 client + instance_id: The ID of the EC2 instance + + Raises: + ClientError: If AWS API calls fail + Exception: For other unexpected errors + SystemExit: If required tags are missing or no changes were made + """ + try: + # Get the lastfence tag first + lastfence_response = ec2_client.describe_tags( + Filters=[ + {"Name": "resource-id", "Values": [instance_id]}, + {"Name": "key", "Values": ["lastfence"]} + ] + ) + + if not lastfence_response["Tags"]: + logger.error(f"No lastfence tag found for instance {instance_id}") + sys.exit(EC_GENERIC_ERROR) + + lastfence_timestamp = lastfence_response["Tags"][0]["Value"] + + # Get all backup tags for this instance + backup_response = ec2_client.describe_tags( + Filters=[ + {"Name": "resource-id", "Values": [instance_id]}, + {"Name": "key", "Values": [f"Original_SG_Backup_{instance_id}*"]} + ] + ) + + if not backup_response["Tags"]: + logger.error(f"No backup tags found for instance {instance_id}") + sys.exit(EC_GENERIC_ERROR) + + # Find and combine backup tags with matching timestamp + matching_backups = {} + interface_chunks = {} + + for tag in backup_response["Tags"]: + try: + backup_data = json.loads(tag["Value"]) + backup_timestamp = backup_data.get("t") # Using shortened timestamp field + + if not backup_timestamp or str(backup_timestamp) != str(lastfence_timestamp): + continue + + logger.info(f"Found matching backup tag {tag['Key']}") + interface_data = backup_data.get("n") # Using shortened NetworkInterface field + + if not interface_data or "i" not in interface_data: # Using shortened interface id field + continue + + interface_id = interface_data["i"] # Using shortened interface id field + chunk_info = interface_data.get("c", {}) # Using shortened chunk info field + chunk_index = chunk_info.get("i", 0) + total_chunks = chunk_info.get("t", 1) + + # Initialize tracking for this interface if needed + if interface_id not in interface_chunks: + interface_chunks[interface_id] = { + "total": total_chunks, + "chunks": {}, + "security_groups": [] + } + + # Add this chunk's security groups + interface_chunks[interface_id]["chunks"][chunk_index] = interface_data["s"] # Using shortened security groups field + + # If we have all chunks for this interface, combine them + if len(interface_chunks[interface_id]["chunks"]) == total_chunks: + # Combine chunks and restore 'sg-' prefix + combined_sgs = [] + for i in range(total_chunks): + chunk_sgs = interface_chunks[interface_id]["chunks"][i] + # Add back 'sg-' prefix if not already present + restored_sgs = ['sg-' + sg if not sg.startswith('sg-') else sg for sg in chunk_sgs] + combined_sgs.extend(restored_sgs) + matching_backups[interface_id] = combined_sgs + + except (json.JSONDecodeError, KeyError) as e: + logger.error(f"Failed to parse backup data for tag {tag['Key']}: {str(e)}") + continue + + if not matching_backups: + logger.error("No complete backup data found with matching timestamp") + sys.exit(EC_GENERIC_ERROR) + + # Get current interfaces + _, _, current_interfaces = get_instance_details(ec2_client, instance_id) + + # Use the combined matching_backups as our backup_sg_map + backup_sg_map = matching_backups + + changed_any = False + for interface in current_interfaces: + try: + interface_id = interface["NetworkInterfaceId"] + if interface_id not in backup_sg_map: + logger.warning( + f"No backup data found for interface {interface_id}. Skipping." + ) + continue + + original_sgs = backup_sg_map[interface_id] + current_sgs = interface["SecurityGroups"] + + if original_sgs == current_sgs: + logger.info( + f"Interface {interface_id} already has original security groups. Skipping." + ) + continue + + logger.info( + f"Restoring interface {interface_id} from {current_sgs} " + f"to original security groups {original_sgs}" + ) + + try: + ec2_client.modify_network_interface_attribute( + NetworkInterfaceId=interface_id, + Groups=original_sgs + ) + changed_any = True + except ClientError as e: + logger.error( + f"Failed to restore security groups for interface " + f"{interface_id}: {str(e)}" + ) + continue + + except KeyError as e: + logger.error(f"Malformed interface data: {str(e)}") + continue + + if not changed_any: + logger.error("No security groups were restored. All interfaces skipped.") + sys.exit(EC_GENERIC_ERROR) + + # Wait for changes to propagate + time.sleep(5) + + # Clean up only the matching backup tags and lastfence tag after successful restore + try: + # Delete all backup tags that match the lastfence timestamp + tags_to_delete = [{"Key": "lastfence"}] + deleted_tag_keys = [] + for tag in backup_response["Tags"]: + try: + backup_data = json.loads(tag["Value"]) + if str(backup_data.get("t")) == str(lastfence_timestamp): # Using shortened timestamp field + tags_to_delete.append({"Key": tag["Key"]}) + deleted_tag_keys.append(tag["Key"]) + except (json.JSONDecodeError, KeyError): + continue + + if len(tags_to_delete) > 1: # More than just the lastfence tag + ec2_client.delete_tags( + Resources=[instance_id], + Tags=tags_to_delete + ) + logger.info(f"Removed matching backup tags {deleted_tag_keys} and lastfence tag from instance {instance_id}") + except ClientError as e: + logger.warning(f"Failed to remove tags: {str(e)}") + # Continue since the restore operation was successful + + except ClientError as e: + logger.error(f"AWS API error: {str(e)}") + raise + except Exception as e: + logger.error(f"Unexpected error: {str(e)}") + raise + +# Shutdown instance +def shutdown_instance(ec2_client, instance_id): + """Shutdown the instance and confirm the state transition.""" + try: + logger.info(f"Initiating shutdown for instance {instance_id}...") + ec2_client.stop_instances(InstanceIds=[instance_id], Force=True) + + while True: + try: + state, _, _ = get_instance_details(ec2_client, instance_id) + logger.info(f"Current instance state: {state}") + if state == "stopping": + logger.info( + f"Instance {instance_id} is transitioning to 'stopping'. Proceeding without waiting further." + ) + break + except ClientError as e: + logger.error(f"Failed to get instance state during shutdown: {str(e)}") + fail_usage(f"AWS API error while checking instance state: {str(e)}") + except Exception as e: + logger.error(f"Unexpected error while checking instance state: {str(e)}") + fail_usage(f"Failed to check instance state: {str(e)}") + + except ClientError as e: + logger.error(f"AWS API error during instance shutdown: {str(e)}") + fail_usage(f"Failed to shutdown instance: {str(e)}") + except Exception as e: + logger.error(f"Unexpected error during instance shutdown: {str(e)}") + fail_usage(f"Failed to shutdown instance due to unexpected error: {str(e)}") + + +# Perform the fencing action +def get_nodes_list(conn, options): + """Get list of nodes and their status.""" + logger.debug("Starting monitor operation") + result = {} + try: + if "--filter" in options: + filter_key = options["--filter"].split("=")[0].strip() + filter_value = options["--filter"].split("=")[1].strip() + filter = [{"Name": filter_key, "Values": [filter_value]}] + logging.debug("Filter: {}".format(filter)) + + for instance in conn.instances.filter(Filters=filter if 'filter' in vars() else []): + instance_name = "" + for tag in instance.tags or []: + if tag.get("Key") == "Name": + instance_name = tag["Value"] + try: + result[instance.id] = (instance_name, status[instance.state["Name"]]) + except KeyError as e: + if options.get("--original-action") == "list-status": + logger.error("Unknown status \"{}\" returned for {} ({})".format(instance.state["Name"], instance.id, instance_name)) + result[instance.id] = (instance_name, "unknown") + except Exception as e: + logger.error("Failed to get node list: %s", e) + return result + +def set_lastfence_tag(ec2_client, instance_id, timestamp): + """Set a lastfence tag on the instance with the timestamp.""" + try: + ec2_client.create_tags( + Resources=[instance_id], + Tags=[{"Key": "lastfence", "Value": str(timestamp)}] + ) + logger.info(f"Set lastfence tag with timestamp {timestamp} on instance {instance_id}") + except Exception as e: + logger.error(f"Failed to set lastfence tag: {str(e)}") + raise + +def set_power_status(conn, options): + """Set power status of the instance.""" + timestamp = int(time.time()) # Unix timestamp + ec2_client = conn.meta.client + instance_id = options["--plug"] + sg_to_remove = options.get("--secg", "").split(",") if options.get("--secg") else [] + + # Perform self-check if skip-race not set + if "--skip-race-check" not in options: + self_instance_id = get_instance_id() + if self_instance_id == instance_id: + fail_usage("Self-fencing detected. Exiting.") + + try: + # Only verify instance is running for 'off' action + if options["--action"] == "off": + instance_state, _, _ = get_instance_details(ec2_client, instance_id) + if instance_state != "running": + fail_usage(f"Instance {instance_id} is not running. Exiting.") + + if options["--action"] == "on": + if not "--unfence-ignore-restore" in options: + restore_security_groups(ec2_client, instance_id) + else: + logger.info("Ignored Restoring security groups as --unfence-ignore-restore is set") + elif options["--action"] == "off": + if sg_to_remove: + mode = "keep_only" if "--invert-sg-removal" in options else "remove" + try: + modify_security_groups(ec2_client, instance_id, sg_to_remove, timestamp, mode, options) + if "--onfence-poweroff" in options: + shutdown_instance(ec2_client, instance_id) + except Exception as e: + if isinstance(e, ClientError): + logger.error("AWS API error: %s", e) + fail_usage(str(e)) + elif "--ignore-tag-write-failure" in options: + # If we're ignoring tag failures, only fail if the security group modifications failed + if "Failed to modify security groups" in str(e): + logger.error("Failed to modify security groups: %s", e) + fail(EC_STATUS) + else: + logger.warning("Ignoring error due to ignore-tag-write-failure: %s", e) + else: + logger.error("Failed to set power status: %s", e) + fail(EC_STATUS) + except Exception as e: + logger.error("Unexpected error in set_power_status: %s", e) + fail(EC_STATUS) + + +# Define fencing agent options +def define_new_opts(): + all_opt["port"]["help"] = "-n, --plug=[id] AWS Instance ID to perform action on " + all_opt["port"]["shortdesc"] = "AWS Instance ID to perform action on " + + all_opt["region"] = { + "getopt": "r:", + "longopt": "region", + "help": "-r, --region=[region] AWS region (e.g., us-east-1)", + "shortdesc": "AWS Region.", + "required": "0", + "order": 1, + } + all_opt["access_key"] = { + "getopt": "a:", + "longopt": "access-key", + "help": "-a, --access-key=[key] AWS access key.", + "shortdesc": "AWS Access Key.", + "required": "0", + "order": 2, + } + all_opt["secret_key"] = { + "getopt": "s:", + "longopt": "secret-key", + "help": "-s, --secret-key=[key] AWS secret key.", + "shortdesc": "AWS Secret Key.", + "required": "0", + "order": 3, + } + all_opt["secg"] = { + "getopt": ":", + "longopt": "secg", + "help": "--secg=[sg1,sg2,...] Comma-separated list of Security Groups to remove.", + "shortdesc": "Security Groups to remove.", + "required": "0", + "order": 4, + } + all_opt["skip_race_check"] = { + "getopt": "", + "longopt": "skip-race-check", + "help": "--skip-race-check Skip race condition check.", + "shortdesc": "Skip race condition check.", + "required": "0", + "order": 6, + } + all_opt["invert-sg-removal"] = { + "getopt": "", + "longopt": "invert-sg-removal", + "help": "--invert-sg-removal Remove all security groups except the specified one(s).", + "shortdesc": "Remove all security groups except specified..", + "required": "0", + "order": 7, + } + all_opt["unfence-ignore-restore"] = { + "getopt": "", + "longopt": "unfence-ignore-restore", + "help": "--unfence-ignore-restore Do not restore security groups from tag when unfencing (off).", + "shortdesc": "Remove all security groups except specified..", + "required": "0", + "order": 8, + + } + all_opt["filter"] = { + "getopt": ":", + "longopt": "filter", + "help": "--filter=[key=value] Filter (e.g. vpc-id=[vpc-XXYYZZAA])", + "shortdesc": "Filter for list-action", + "required": "0", + "order": 9 + } + all_opt["boto3_debug"] = { + "getopt": "b:", + "longopt": "boto3_debug", + "help": "-b, --boto3_debug=[option] Boto3 and Botocore library debug logging", + "shortdesc": "Boto Lib debug", + "required": "0", + "default": "False", + "order": 10 + } + all_opt["onfence-poweroff"] = { + "getopt": "", + "longopt": "onfence-poweroff", + "help": "--onfence-poweroff Power off the machine async upon fence (this is a network fencing agent...)", + "shortdesc": "Power off the machine async..", + "required": "0", + "order": 11 + } + all_opt["ignore-tag-write-failure"] = { + "getopt": "", + "longopt": "ignore-tag-write-failure", + "help": "--ignore-tag-write-failure Continue to fence even if backup tag fails. This ensures prioriization of fencing over AWS backplane access", + "shortdesc": "Continue to fence even if backup tag fails..", + "required": "0", + "order": 12 + } + + +def main(): + conn = None + + device_opt = [ + "no_password", + "region", + "access_key", + "secret_key", + "secg", + "port", + "skip_race_check", + "invert-sg-removal", + "unfence-ignore-restore", + "filter", + "boto3_debug", + "onfence-poweroff", + "ignore-tag-write-failure" +] + + atexit.register(atexit_handler) + + define_new_opts() + + try: + processed_input = process_input(device_opt) + options = check_input(device_opt, processed_input) + except Exception as e: + logger.error(f"Failed to process input options: {str(e)}") + sys.exit(EC_GENERIC_ERROR) + + run_delay(options) + + docs = { + "shortdesc": "Fence agent for AWS (Amazon Web Services) Net", + "longdesc": ( + "fence_aws_vpc is a Network and Power Fencing agent for AWS VPC that works by " + "manipulating security groups. It uses the boto3 library to connect to AWS.\n\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" + " " + "NOTE: If onfence-poweroff is set, the agent won't be able to power on the node again, it will have to be powered on manually or with other automation." + ), + "vendorurl": "http://www.amazon.com" + } + show_docs(options, docs) + + if "--onfence-poweroff" not in options and options.get("--action", "") == "reboot": + options["--action"] = "off" + + # Configure logging + if "--debug-file" in options: + for handler in logger.handlers: + if isinstance(handler, logging.FileHandler): + logger.removeHandler(handler) + lh = logging.FileHandler(options["--debug-file"]) + logger.addHandler(lh) + lhf = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + lh.setFormatter(lhf) + lh.setLevel(logging.DEBUG) + + # Configure boto3 logging + if options.get("--boto3_debug", "").lower() not in ["1", "yes", "on", "true"]: + boto3.set_stream_logger('boto3', logging.INFO) + boto3.set_stream_logger('botocore', logging.CRITICAL) + logging.getLogger('botocore').propagate = False + logging.getLogger('boto3').propagate = False + else: + log_format = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') + logging.getLogger('botocore').propagate = False + logging.getLogger('boto3').propagate = False + fdh = logging.FileHandler('/var/log/fence_aws_vpc_boto3.log') + fdh.setFormatter(log_format) + logging.getLogger('boto3').addHandler(fdh) + logging.getLogger('botocore').addHandler(fdh) + logging.debug("Boto debug level is %s and sending debug info to /var/log/fence_aws_vpc_boto3.log", + options.get("--boto3_debug")) + + # Establish AWS connection + region = options.get("--region") + access_key = options.get("--access-key") + secret_key = options.get("--secret-key") + + try: + conn = boto3.resource( + "ec2", + region_name=region, + aws_access_key_id=access_key, + aws_secret_access_key=secret_key, + ) + except Exception as e: + if not options.get("--action", "") in ["metadata", "manpage", "validate-all"]: + fail_usage("Failed: Unable to connect to AWS: " + str(e)) + else: + pass + + # Operate the fencing device using the fence library's fence_action + result = fence_action(conn, options, set_power_status, get_power_status, get_nodes_list) + sys.exit(result) + + +if __name__ == "__main__": + main() + diff --git a/agents/aws_vpc_net/readme.md b/agents/aws_vpc_net/readme.md new file mode 100644 index 00000000..de1a12e5 --- /dev/null +++ b/agents/aws_vpc_net/readme.md @@ -0,0 +1,461 @@ +# Fence AWS VPC Network Agent Design Document + +## Overview + +The fence_aws_vpc_net agent is a network and power fencing agent for AWS VPC that operates by manipulating security groups. This document outlines the design and architecture of the agent. + +## Class Diagram + +```mermaid +classDiagram + class FenceAWSVPCNet { + -logger: Logger + -conn: boto3.resource + -options: dict + +main() + +define_new_opts() + +process_input() + +check_input() + +get_power_status() + +set_power_status() + } + + class InstanceOperations { + +get_instance_id() + +get_instance_details() + +shutdown_instance() + +get_nodes_list() + } + + class SecurityGroupOperations { + +modify_security_groups() + +create_backup_tag() + +restore_security_groups() + -validate_sg_changes() + } + + class TagOperations { + +set_lastfence_tag() + +create_backup_tag() + +restore_from_backup() + -handle_chunked_tags() + } + + class LoggingManager { + +configure_logging() + +configure_boto3_logging() + +handle_debug_file() + } + + FenceAWSVPCNet --> InstanceOperations + FenceAWSVPCNet --> SecurityGroupOperations + FenceAWSVPCNet --> TagOperations + FenceAWSVPCNet --> LoggingManager + SecurityGroupOperations --> TagOperations +``` + +## Sequence Diagrams + +### Fence Operation (Power Off) + +```mermaid +sequenceDiagram + participant Client + participant FenceAgent + participant AWS + participant SecurityGroups + participant Tags + + Client->>FenceAgent: Execute fence operation + FenceAgent->>AWS: Validate AWS credentials + AWS-->>FenceAgent: Credentials valid + + opt skip-race-check not set + FenceAgent->>AWS: Get self instance ID + AWS-->>FenceAgent: Instance ID + FenceAgent->>FenceAgent: Check for self-fencing + end + + FenceAgent->>AWS: Get instance details + AWS-->>FenceAgent: Instance details + + alt Instance is running + FenceAgent->>SecurityGroups: Backup current security groups + SecurityGroups-->>FenceAgent: Backup created + + alt ignore-tag-write-failure not set + FenceAgent->>Tags: Create lastfence tag + Tags-->>FenceAgent: Tag created + end + + FenceAgent->>SecurityGroups: Modify security groups + SecurityGroups-->>FenceAgent: Groups modified + + opt onfence-poweroff enabled + FenceAgent->>AWS: Initiate shutdown + AWS-->>FenceAgent: Shutdown initiated + end + + FenceAgent-->>Client: Success + else Instance not running + FenceAgent-->>Client: Fail - Instance not running + end +``` + +### Unfence Operation (Power On) + +```mermaid +sequenceDiagram + participant Client + participant FenceAgent + participant AWS + participant SecurityGroups + participant Tags + + Client->>FenceAgent: Execute unfence operation + FenceAgent->>AWS: Validate AWS credentials + AWS-->>FenceAgent: Credentials valid + + alt unfence-ignore-restore not set + FenceAgent->>Tags: Get lastfence tag + Tags-->>FenceAgent: Lastfence tag + + FenceAgent->>Tags: Get backup tags + Tags-->>FenceAgent: Backup tags + + alt Valid backup found + FenceAgent->>SecurityGroups: Restore original security groups + SecurityGroups-->>FenceAgent: Groups restored + + FenceAgent->>Tags: Cleanup backup tags + Tags-->>FenceAgent: Tags cleaned + + FenceAgent-->>Client: Success + else No valid backup + FenceAgent-->>Client: Fail - No valid backup found + end + else + FenceAgent-->>Client: Success - Restore skipped + end +``` + +## Component Details + +### 1. Main Controller (FenceAWSVPCNet) +- **Purpose**: Main entry point and orchestration +- **Key Responsibilities**: + - Process command line options + - Initialize AWS connection + - Execute fence operations + - Handle logging and errors + - Manage self-fencing prevention + - Support tag write failure handling + +### 2. Instance Operations +- **Purpose**: Handle EC2 instance operations +- **Key Responsibilities**: + - Get instance details and metadata + - Handle instance power operations + - Validate instance states + - List and filter instances + - Handle instance shutdown + +### 3. Security Group Operations +- **Purpose**: Manage security group operations +- **Key Responsibilities**: + - Modify security groups (remove or keep-only modes) + - Handle chunked backup operations + - Restore security groups from backups + - Validate security group changes + - Support partial success scenarios + +### 4. Tag Operations +- **Purpose**: Manage AWS resource tagging +- **Key Responsibilities**: + - Create and manage backup tags + - Handle chunked tag data + - Manage lastfence tags + - Clean up tags after operations + - Support tag write failure scenarios + +### 5. Logging Manager +- **Purpose**: Handle logging configuration +- **Key Responsibilities**: + - Configure application logging + - Manage boto3 debug logging + - Handle debug file output + - Control log propagation + +## Success and Failure Paths + +### Success Paths + +1. **Normal Fence Operation (Without ignore-tag-write-failure)** +``` +Start +├── Validate AWS credentials +├── Check for self-fencing (if enabled) +├── Check instance is running +├── Backup security groups (with chunking) +│ ├── Create backup tags for each interface +│ └── Verify backup tag creation +├── Create lastfence tag +├── Modify security groups +│ ├── Remove specified groups +│ └── Verify modifications +├── [Optional] Shutdown instance +└── Success +``` + +2. **Fence Operation (With ignore-tag-write-failure)** +``` +Start +├── Validate AWS credentials +├── Check for self-fencing (if enabled) +├── Check instance is running +├── Attempt backup tag creation +│ ├── Success: Create backup tags +│ └── Failure: Log warning and continue +├── Attempt lastfence tag creation +│ ├── Success: Create tag +│ └── Failure: Log warning and continue +├── Modify security groups +│ ├── Remove specified groups +│ ├── Verify modifications +│ └── Check all interfaces modified +│ ├── All modified: Success +│ └── Partial: Fail with modification error +├── [Optional] Shutdown instance +└── Success (if security groups modified) +``` + +3. **Normal Unfence Operation** +``` +Start +├── Validate AWS credentials +├── [Skip if unfence-ignore-restore] +│ ├── Find lastfence tag +│ ├── Find backup tags +│ ├── Restore security groups +│ └── Clean up tags +└── Success +``` + +### Failure Paths + +1. **Authentication Failures** +``` +Start +├── Invalid AWS credentials +│ ├── Missing credentials +│ ├── Invalid access key +│ ├── Invalid secret key +│ └── Invalid region +└── Fail with auth error +``` + +2. **Instance State Failures** +``` +Start +├── Instance not found +│ └── Fail with instance error +├── Instance not in required state +│ └── Fail with state error +└── Self-fencing detected + └── Fail with self-fencing error +``` + +3. **Security Group Operation Failures (Without ignore-tag-write-failure)** +``` +Start +├── Backup creation fails +│ ├── Tag size too large +│ ├── API error +│ └── Fail with backup error +├── Security group modification fails +│ ├── Permission denied +│ ├── Invalid group ID +│ ├── Rate limit exceeded +│ └── Fail with modification error +└── Restoration fails + ├── Missing backup data + ├── Invalid backup format + ├── Modification error + └── Fail with restore error +``` + +4. **Security Group Operation Failures (With ignore-tag-write-failure)** +``` +Start +├── Backup creation fails +│ ├── Log warning +│ └── Continue to modifications +├── Security group modification attempt +│ ├── Success: All interfaces modified +│ │ └── Continue to completion +│ ├── Partial success +│ │ ├── Verify fencing state +│ │ │ ├── Sufficient interfaces modified +│ │ │ │ └── Continue to completion +│ │ │ └── Insufficient modifications +│ │ │ └── Fail with partial error +│ │ └── Log warning +│ └── Complete failure +│ └── Fail with modification error +├── [Optional] Shutdown attempt +│ ├── Success +│ │ └── Continue to completion +│ └── Failure +│ └── Log warning (non-fatal) +└── Final state determined by SG modifications +``` + +5. **Tag Operation Failures (Without ignore-tag-write-failure)** +``` +Start +├── Tag creation fails +│ ├── Size limit exceeded +│ ├── API error +│ └── Fail with tag error +├── Tag retrieval fails +│ ├── Missing tags +│ ├── Invalid format +│ └── Fail with retrieval error +└── Tag cleanup fails + └── Warning (non-fatal) +``` + +6. **Tag Operation Failures (With ignore-tag-write-failure)** +``` +Start +├── Backup tag creation fails +│ ├── Log warning +│ └── Continue operation +├── Lastfence tag creation fails +│ ├── Log warning +│ └── Continue operation +├── Tag retrieval fails +│ ├── Check security group state +│ │ ├── Groups properly modified +│ │ │ └── Continue operation +│ │ └── Groups not modified +│ │ └── Fail with SG error +│ └── Log warning +└── Tag cleanup fails + └── Warning (non-fatal) +``` + +## Error Handling + +### Error Categories +1. **AWS API Errors** + - ConnectionError + - ClientError + - EndpointConnectionError + - NoRegionError + - Tag size limitations + - API rate limiting + +2. **Validation Errors** + - Invalid parameters + - Missing required options + - Invalid security group configurations + - Malformed tag data + +3. **State Errors** + - Instance state conflicts + - Security group conflicts + - Self-fencing detection + - Partial operation completion + +### Error Recovery +- Automatic retries for transient AWS API errors +- Chunked tag handling for large security group lists +- Support for continuing operation despite tag failures +- Rollback of security group changes on partial failures +- Preservation of backup tags for manual recovery +- Detailed logging for troubleshooting + +## Configuration Options + +### Required Options +- `--plug`: AWS Instance ID +- AWS credentials (via options or environment) + +### Optional Options +- `--region`: AWS region +- `--access-key`: AWS access key +- `--secret-key`: AWS secret key +- `--secg`: Security groups to remove/keep +- `--skip-race-check`: Skip self-fencing check +- `--invert-sg-removal`: Keep only specified security groups +- `--unfence-ignore-restore`: Skip restore on unfence +- `--onfence-poweroff`: Power off on fence +- `--ignore-tag-write-failure`: Continue despite tag failures +- `--filter`: Filter instances for list operation +- `--boto3_debug`: Enable boto3 debug logging + +## Logging and Monitoring + +### Log Levels +- ERROR: Operation failures and AWS API errors +- WARNING: Non-critical issues and tag operation failures +- INFO: Operation progress and success +- DEBUG: Detailed operation data and API responses + +### Key Metrics +- Operation success/failure rates +- Tag operation success rates +- Security group modification status +- AWS API call latency +- Error frequency and types +- Tag size and chunking metrics + +## Security Considerations + +### Authentication +- AWS credential management +- IAM role requirements +- Access key security +- Instance metadata security + +### Operation Safety +- Self-fencing prevention +- Backup verification +- Security group validation +- State verification +- Tag operation integrity +- Partial success handling + +## Best Practices + +1. **Operation Safety** + - Always verify instance state + - Use self-fencing prevention + - Validate security group changes + - Maintain accurate backups + - Handle tag operation failures gracefully + +2. **Error Handling** + - Implement proper rollbacks + - Use chunked tag operations + - Maintain detailed logs + - Preserve recovery data + - Handle edge cases + - Support partial success scenarios + +3. **Performance** + - Minimize API calls + - Implement retries + - Handle rate limiting + - Optimize tag operations + - Use efficient security group modifications + +4. **Maintenance** + - Regular backup cleanup + - Log rotation + - Configuration updates + - Security updates + - Monitor tag usage + - Clean up orphaned tags + diff --git a/fence-agents.spec.in b/fence-agents.spec.in index f8ef5f27..293ac50a 100644 --- a/fence-agents.spec.in +++ b/fence-agents.spec.in @@ -1,1322 +1,1335 @@ ############################################################################### ############################################################################### ## ## Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved. ## ## This copyrighted material is made available to anyone wishing to use, ## modify, copy, or redistribute it subject to the terms and conditions ## of the GNU General Public License v.2. ## ############################################################################### ############################################################################### %global rcver @rcver@ %global alphatag @alphatag@ %global numcomm @numcomm@ %global dirty @dirty@ Name: fence-agents Summary: Set of unified programs capable of host isolation ("fencing") Version: @version@ Release: @specver@%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist} License: GPL-2.0-or-later AND LGPL-2.0-or-later Group: System Environment/Base URL: https://github.com/ClusterLabs/fence-agents Source0: %{name}-%{version}%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}.tar.bz2 %define boto3_br @boto3_br@ # skipped: pve, raritan, rcd-serial, virsh %global allfenceagents %(cat < 1500 BuildRequires: python3-suds-community %else BuildRequires: python3-suds %endif %if 0%{?fedora} || 0%{?centos} || 0%{?rhel} BuildRequires: openwsman-python3 %if %{boto3_br} BuildRequires: python3-boto3 %endif %else BuildRequires: python3-openwsman %if %{boto3_br} BuildRequires: python3-boto3 %endif %endif # fence-virt %if 0%{?suse_version} %define nss_devel mozilla-nss-devel %define nspr_devel mozilla-nspr-devel %define systemd_units systemd %else %define nss_devel nss-devel %define nspr_devel nspr-devel %define systemd_units systemd-units %endif BuildRequires: corosynclib-devel libvirt-devel BuildRequires: libxml2-devel %{nss_devel} %{nspr_devel} BuildRequires: flex bison libuuid-devel BuildRequires: %{systemd_units} # turn off the brp-python-bytecompile script # (for F28+ or equivalent, the latter is the preferred form) %global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompilespace:.*$!!g') #undefine __brp_python_bytecompile %prep %setup -q -n %{name}-%{version}%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}} %autopatch -p1 # prevent compilation of something that won't get used anyway sed -i.orig 's|FENCE_ZVM=1|FENCE_ZVM=0|' configure.ac %build export PYTHON="%{__python3}" ./autogen.sh %{configure} \ %if %{defined _tmpfilesdir} SYSTEMD_TMPFILES_DIR=%{_tmpfilesdir} \ --with-fencetmpdir=/run/fence-agents %endif CFLAGS="$(echo '%{optflags}')" make %{_smp_mflags} %install rm -rf %{buildroot} make install DESTDIR=%{buildroot} mkdir -p %{buildroot}/%{_unitdir}/ install -m 0644 agents/virt/fence_virtd.service %{buildroot}/%{_unitdir}/ # bytecompile Python source code in a non-standard location %if 0%{?fedora} || 0%{?centos} || 0%{?rhel} %py_byte_compile %{__python3} %{buildroot}%{_datadir}/fence %endif # XXX unsure if /usr/sbin/fence_* should be compiled as well ## tree fix up # fix libfence permissions chmod 0755 %{buildroot}%{_datadir}/fence/*.py # remove docs rm -rf %{buildroot}/usr/share/doc/fence-agents # remove .a files rm -f %{buildroot}/%{_libdir}/%{name}/*.*a rm -f %{buildroot}/%{_libdir}/fence-virt/*.*a %post ccs_update_schema > /dev/null 2>&1 ||: # https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd if [ $1 -eq 1 ] ; then # Initial installation /bin/systemctl daemon-reload >/dev/null 2>&1 || : fi %preun # https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd if [ $1 -eq 0 ] ; then # Package removal, not upgrade /bin/systemctl --no-reload disable fence_virtd.service &> /dev/null || : /bin/systemctl stop fence_virtd.service &> /dev/null || : fi %postun # https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Systemd /bin/systemctl daemon-reload &> /dev/null || : if [ $1 -ge 1 ] ; then # Package upgrade, not uninstall /bin/systemctl try-restart fence_virtd.service &> /dev/null || : fi %triggerun -- fence_virtd < 0.3.0-1 # https://fedoraproject.org/wiki/Packaging:ScriptletSnippets#Packages_migrating_to_a_systemd_unit_file_from_a_SysV_initscript /usr/bin/systemd-sysv-convert --save fence_virtd &> /dev/null || : /sbin/chkconfig --del fence_virtd &> /dev/null || : /bin/systemctl daemon-reload >/dev/null 2>&1 || : /bin/systemctl try-restart fence_virtd.service &> /dev/null || : %description A collection of executables to handle isolation ("fencing") of possibly misbehaving hosts by the means of remote power management, blocking network, storage, or similar. They operate through a unified interface (calling conventions) devised for the original Red Hat clustering solution. %package common License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Common base for Fence Agents Requires: python3-pexpect python3-pycurl BuildArch: noarch %description common A collection of executables to handle isolation ("fencing") of possibly misbehaving hosts by the means of remote power management, blocking network, storage, or similar. This package contains support files including the Python fencing library. %files common %doc doc/COPYING.* doc/COPYRIGHT doc/README.licence %{_datadir}/fence %exclude %{_datadir}/fence/azure_fence.* %exclude %{_datadir}/fence/__pycache__/azure_fence.* %exclude %{_datadir}/fence/XenAPI.* %exclude %{_datadir}/fence/__pycache__/XenAPI.* %{_datadir}/cluster %exclude %{_datadir}/cluster/fence_mpath_check* %exclude %{_datadir}/cluster/fence_scsi_check* %{_datadir}/pkgconfig/%{name}.pc %exclude %{_sbindir}/* %exclude %{_mandir}/man8/* %if %{defined _tmpfilesdir} %{_tmpfilesdir}/%{name}.conf %endif %if %{defined _tmpfilesdir} %dir %attr (1755, root, root) /run/%{name} %else %dir %attr (1755, root, root) %{_var}/run/%{name} %endif %package all License: GPL-2.0-or-later AND LGPL-2.0-or-later AND Apache-2.0 Summary: Set of unified programs capable of host isolation ("fencing") Requires: %{allfenceagents} Provides: fence-agents = %{version}-%{release} Obsoletes: fence-agents < 3.1.13 %description all A collection of executables to handle isolation ("fencing") of possibly misbehaving hosts by the means of remote power management, blocking network, storage, or similar. This package serves as a catch-all for all supported fence agents. %files all %ifarch x86_64 %package aliyun License: GPL-2.0-or-later AND LGPL-2.0-or-later AND Apache-2.0 AND BSD-3-Clause AND MIT Group: System Environment/Base Summary: Fence agent for Alibaba Cloud (Aliyun) Requires: fence-agents-common >= %{version}-%{release} Requires: python3-jmespath >= 0.9.0 Obsoletes: %{name} < %{version}-%{release} %description aliyun The fence-agents-aliyun package contains a fence agent for Alibaba Cloud (Aliyun) instances. %files aliyun %defattr(-,root,root,-) %{_sbindir}/fence_aliyun %{_mandir}/man8/fence_aliyun.8* %endif %package alom License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for SUN ALOM Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description alom Fence agent for SUN ALOM. %files alom %{_sbindir}/fence_alom %{_mandir}/man8/fence_alom.8* %package amt License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Intel AMT devices Requires: amtterm Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description amt Fence agent for AMT compatibile devices that are accessed via 3rd party software. %files amt %{_sbindir}/fence_amt %{_mandir}/man8/fence_amt.8* %package amt-ws License: Apache-2.0 Summary: Fence agent for Intel AMT (WS-Man) devices Requires: fence-agents-common = %{version}-%{release} %if 0%{?fedora} || 0%{?centos} || 0%{?rhel} Requires: openwsman-python3 %else Requires: python3-openwsman %endif BuildArch: noarch %description amt-ws Fence agent for AMT (WS-Man) devices. %files amt-ws %{_sbindir}/fence_amt_ws %{_mandir}/man8/fence_amt_ws.8* %package apc License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for APC devices Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description apc Fence agent for APC devices that are accessed via telnet or SSH. %files apc %{_sbindir}/fence_apc %{_mandir}/man8/fence_apc.8* %package apc-snmp License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agents for APC devices (SNMP) Requires: net-snmp-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description apc-snmp Fence agents for APC devices that are accessed via the SNMP protocol. %files apc-snmp %{_sbindir}/fence_apc_snmp %{_mandir}/man8/fence_apc_snmp.8* %{_sbindir}/fence_tripplite_snmp %{_mandir}/man8/fence_tripplite_snmp.8* %package aws License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Amazon AWS Requires: fence-agents-common = %{version}-%{release} Requires: python3-boto3 BuildArch: noarch Obsoletes: fence-agents < 3.1.13 %description aws Fence agent for Amazon AWS instances. %files aws %{_sbindir}/fence_aws %{_mandir}/man8/fence_aws.8* +%package aws-vpc-net +License: GPL-2.0-or-later AND LGPL-2.0-or-later +Summary: Fence agent for Amazon AWS VPC network and power fencer +Requires: fence-agents-common = %{version}-%{release} +Requires: python3-boto3 +BuildArch: noarch +Obsoletes: fence-agents < 3.1.13 +%description aws-vpc-net +Fence agent for Amazon AWS instances that fences by modifying aws sec groups +%files aws-vpc-net +%{_sbindir}/fence_aws_vpc_net +%{_mandir}/man8/fence_aws_vpc_net.8* + %package azure-arm License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Azure Resource Manager Requires: fence-agents-common = %{version}-%{release} %if 0%{?rhel} && 0%{?rhel} < 9 Requires: python3-azure-sdk %else Requires: python3-azure-common Requires: python3-azure-identity Requires: python3-azure-mgmt-compute Requires: python3-azure-mgmt-network Requires: python3-msrestazure %endif BuildArch: noarch Obsoletes: fence-agents < 3.1.13 %description azure-arm Fence agent for Azure Resource Manager instances. %files azure-arm %{_sbindir}/fence_azure_arm %{_datadir}/fence/azure_fence.py* %if 0%{?fedora} || 0%{?centos} || 0%{?rhel} %{_datadir}/fence/__pycache__/azure_fence.* %endif %{_mandir}/man8/fence_azure_arm.8* %package bladecenter License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM BladeCenter Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description bladecenter Fence agent for IBM BladeCenter devices that are accessed via telnet or SSH. %files bladecenter %{_sbindir}/fence_bladecenter %{_mandir}/man8/fence_bladecenter.8* %package brocade License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Brocade switches Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description brocade Fence agent for Brocade devices that are accessed via telnet or SSH. %files brocade %{_sbindir}/fence_brocade %{_mandir}/man8/fence_brocade.8* %package cdu License: GPL-3.0-only Summary: Fence agent for a Sentry Switch CDU Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description cdu Fence agent for Sentry Switch CDU power switch. %files cdu %{_sbindir}/fence_cdu %{_mandir}/man8/fence_cdu.8* %package cisco-mds License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Cisco MDS 9000 series Requires: net-snmp-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description cisco-mds Fence agent for Cisco MDS 9000 series devices that are accessed via the SNMP protocol. %files cisco-mds %{_sbindir}/fence_cisco_mds %{_mandir}/man8/fence_cisco_mds.8* %package cisco-ucs License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Cisco UCS series Requires: python3-pycurl Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description cisco-ucs Fence agent for Cisco UCS series devices that are accessed via the SNMP protocol. %files cisco-ucs %{_sbindir}/fence_cisco_ucs %{_mandir}/man8/fence_cisco_ucs.8* %ifarch x86_64 ppc64le %package compute License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Nova compute nodes Requires: python3-requests Requires: python3-novaclient Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description compute Fence agent for Nova compute nodes. %files compute %{_sbindir}/fence_compute %{_sbindir}/fence_evacuate %{_mandir}/man8/fence_compute.8* %{_mandir}/man8/fence_evacuate.8* %endif %package cyberpower-ssh License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for CyberPower network PDUs Requires: openssh-clients Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description cyberpower-ssh %files cyberpower-ssh %{_sbindir}/fence_cyberpower_ssh %{_mandir}/man8/fence_cyberpower_ssh.8* %package docker License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Docker Requires: python3-pycurl Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description docker Fence agent for Docker images that are accessed over HTTP. %files docker %{_sbindir}/fence_docker %{_mandir}/man8/fence_docker.8* %package drac License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Dell DRAC Requires: telnet Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description drac Fence agent for Dell DRAC IV series devices that are accessed via telnet. %files drac %{_sbindir}/fence_drac %{_mandir}/man8/fence_drac.8* %package drac5 License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Dell DRAC 5 Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description drac5 Fence agent for Dell DRAC 5 series devices that are accessed via telnet or SSH. %files drac5 %{_sbindir}/fence_drac5 %{_mandir}/man8/fence_drac5.8* %package eaton-snmp License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Eaton network power switches Requires: net-snmp-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description eaton-snmp Fence agent for Eaton network power switches that are accessed via the SNMP protocol. %files eaton-snmp %{_sbindir}/fence_eaton_snmp %{_mandir}/man8/fence_eaton_snmp.8* %package eaton-ssh License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Eaton network power switches Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description eaton-ssh Fence agent for Eaton network power switches that are accessed via the serial protocol tunnel over SSH. %files eaton-ssh %{_sbindir}/fence_eaton_ssh %{_mandir}/man8/fence_eaton_ssh.8* %package ecloud License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for eCloud and eCloud VPC Requires: python3-requests Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ecloud Fence agent for eCloud and eCloud VPC from ANS Group Limited %files ecloud %{_sbindir}/fence_ecloud %{_mandir}/man8/fence_ecloud.8* %package emerson License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Emerson devices (SNMP) Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description emerson Fence agent for Emerson devices that are accessed via the SNMP protocol. %files emerson %{_sbindir}/fence_emerson %{_mandir}/man8/fence_emerson.8* %package eps License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for ePowerSwitch 8M+ power switches Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description eps Fence agent for ePowerSwitch 8M+ power switches that are accessed via the HTTP(s) protocol. %files eps %{_sbindir}/fence_eps* %{_mandir}/man8/fence_eps*.8* %package gce License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for GCE (Google Cloud Engine) Requires: fence-agents-common = %{version}-%{release} %if 0%{?fedora} || 0%{?centos} || 0%{?rhel} Requires: python3-google-api-client %else Requires: python3-google-api-python-client %endif BuildArch: noarch Obsoletes: fence-agents < 3.1.13 %description gce Fence agent for GCE (Google Cloud Engine) instances. %files gce %{_sbindir}/fence_gce %{_mandir}/man8/fence_gce.8* %package hds-cb License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Hitachi Compute Blade systems Requires: telnet Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description hds-cb Fence agent for Hitachi Compute Blades that are accessed via telnet. %files hds-cb %{_sbindir}/fence_hds_cb %{_mandir}/man8/fence_hds_cb.8* %package heuristics-ping License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Pseudo fence agent to affect other agents based on ping-heuristics Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch Obsoletes: fence-agents < 3.1.13 %description heuristics-ping Fence pseudo agent used to affect other agents based on ping-heuristics. %files heuristics-ping %{_sbindir}/fence_heuristics_ping %{_mandir}/man8/fence_heuristics_ping.8* %package hpblade License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for HP BladeSystem devices Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description hpblade Fence agent for HP BladeSystem devices that are accessed via telnet or SSH. %files hpblade %{_sbindir}/fence_hpblade %{_mandir}/man8/fence_hpblade.8* %package ibmblade License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM BladeCenter Requires: net-snmp-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ibmblade Fence agent for IBM BladeCenter devices that are accessed via the SNMP protocol. %files ibmblade %{_sbindir}/fence_ibmblade %{_mandir}/man8/fence_ibmblade.8* %package ibmz License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM z LPARs Requires: python3-requests Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ibmz Fence agent for IBM z LPARs that are accessed via the HMC Web Services REST API. %files ibmz %{_sbindir}/fence_ibmz %{_mandir}/man8/fence_ibmz.8* %package ibm-powervs License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM PowerVS Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ibm-powervs Fence agent for IBM PowerVS that are accessed via REST API. %files ibm-powervs %{_sbindir}/fence_ibm_powervs %{_mandir}/man8/fence_ibm_powervs.8* %package ibm-vpc License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM Cloud VPC Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ibm-vpc Fence agent for IBM Cloud VPC that are accessed via REST API. %files ibm-vpc %{_sbindir}/fence_ibm_vpc %{_mandir}/man8/fence_ibm_vpc.8* %package ifmib License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for devices with IF-MIB interfaces Requires: net-snmp-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ifmib Fence agent for IF-MIB interfaces that are accessed via the SNMP protocol. %files ifmib %{_sbindir}/fence_ifmib %{_mandir}/man8/fence_ifmib.8* %package ilo2 License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agents for HP iLO2 devices Requires: gnutls-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ilo2 Fence agents for HP iLO2 devices that are accessed via the HTTP(s) protocol. %files ilo2 %{_sbindir}/fence_ilo %{_sbindir}/fence_ilo2 %{_mandir}/man8/fence_ilo.8* %{_mandir}/man8/fence_ilo2.8* %package ilo-moonshot License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for HP iLO Moonshot devices Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ilo-moonshot Fence agent for HP iLO Moonshot devices that are accessed via telnet or SSH. %files ilo-moonshot %{_sbindir}/fence_ilo_moonshot %{_mandir}/man8/fence_ilo_moonshot.8* %package ilo-mp License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for HP iLO MP devices Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ilo-mp Fence agent for HP iLO MP devices that are accessed via telnet or SSH. %files ilo-mp %{_sbindir}/fence_ilo_mp %{_mandir}/man8/fence_ilo_mp.8* %package ilo-ssh License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agents for HP iLO devices over SSH Requires: openssh-clients Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ilo-ssh Fence agents for HP iLO devices that are accessed via telnet or SSH. %files ilo-ssh %{_sbindir}/fence_ilo_ssh %{_mandir}/man8/fence_ilo_ssh.8* %{_sbindir}/fence_ilo3_ssh %{_mandir}/man8/fence_ilo3_ssh.8* %{_sbindir}/fence_ilo4_ssh %{_mandir}/man8/fence_ilo4_ssh.8* %{_sbindir}/fence_ilo5_ssh %{_mandir}/man8/fence_ilo5_ssh.8* %package intelmodular License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for devices with Intel Modular interfaces Requires: net-snmp-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description intelmodular Fence agent for Intel Modular interfaces that are accessed via the SNMP protocol. %files intelmodular %{_sbindir}/fence_intelmodular %{_mandir}/man8/fence_intelmodular.8* %package ipdu License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM iPDU network power switches Requires: net-snmp-utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ipdu Fence agent for IBM iPDU network power switches that are accessed via the SNMP protocol. %files ipdu %{_sbindir}/fence_ipdu %{_mandir}/man8/fence_ipdu.8* %package ipmilan License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agents for devices with IPMI interface Requires: /usr/bin/ipmitool Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ipmilan Fence agents for devices with IPMI interface. %files ipmilan %{_sbindir}/fence_ipmilan %{_mandir}/man8/fence_ipmilan.8* %{_sbindir}/fence_idrac %{_mandir}/man8/fence_idrac.8* %{_sbindir}/fence_ilo3 %{_mandir}/man8/fence_ilo3.8* %{_sbindir}/fence_ilo4 %{_mandir}/man8/fence_ilo4.8* %{_sbindir}/fence_ilo5 %{_mandir}/man8/fence_ilo5.8* %{_sbindir}/fence_ipmilanplus %{_mandir}/man8/fence_ipmilanplus.8* %{_sbindir}/fence_imm %{_mandir}/man8/fence_imm.8* %ifarch x86_64 ppc64le %package ironic License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for OpenStack's Ironic (Bare Metal as a service) Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ironic Fence agent for OpenStack's Ironic (Bare Metal as a service) service. %files ironic %{_sbindir}/fence_ironic %{_mandir}/man8/fence_ironic.8* %endif %package kdump License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for use with kdump crash recovery service Requires: fence-agents-common = %{version}-%{release} # this cannot be noarch since it's compiled %description kdump Fence agent for use with kdump crash recovery service. %files kdump %{_sbindir}/fence_kdump %{_libexecdir}/fence_kdump_send %{_mandir}/man8/fence_kdump.8* %{_mandir}/man8/fence_kdump_send.8* %package kubevirt License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for KubeVirt platform Requires: python3-openshift >= 0.12.1 Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description kubevirt Fence agent for KubeVirt platform. %files kubevirt %{_sbindir}/fence_kubevirt %{_mandir}/man8/fence_kubevirt.8* %package ldom License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Sun LDom virtual machines Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ldom Fence agent for APC devices that are accessed via telnet or SSH. %files ldom %{_sbindir}/fence_ldom %{_mandir}/man8/fence_ldom.8* %package lpar License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM LPAR Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description lpar Fence agent for IBM LPAR devices that are accessed via telnet or SSH. %files lpar %{_sbindir}/fence_lpar %{_mandir}/man8/fence_lpar.8* %package mpath License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for reservations over Device Mapper Multipath Requires: device-mapper-multipath Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description mpath Fence agent for SCSI persistent reservation over Device Mapper Multipath. %files mpath %{_sbindir}/fence_mpath %{_datadir}/cluster/fence_mpath_check* %{_mandir}/man8/fence_mpath.8* %package netio License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Koukaam NETIO devices Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description netio Fence agent for Koukaam NETIO devices that are accessed via telnet or SSH. %files netio %{_sbindir}/fence_netio %{_mandir}/man8/fence_netio.8* %package nutanix-ahv License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Nutanix AHV Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch Obsoletes: fence-agents < 3.1.13 %description nutanix-ahv Fence agent for Nutanix AHV clusters. %files nutanix-ahv %{_sbindir}/fence_nutanix_ahv %{_mandir}/man8/fence_nutanix_ahv.8* %ifarch x86_64 ppc64le %package openstack License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for OpenStack's Nova service Requires: python3-requests Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description openstack Fence agent for OpenStack's Nova service. %files openstack %{_sbindir}/fence_openstack %{_mandir}/man8/fence_openstack.8* %endif %package ovh License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for OVH provider %if 0%{?suse_version} > 1500 Requires: python3-suds-community %else Requires: python3-suds %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ovh Fence agent for OVH hosting provider. %files ovh %{_sbindir}/fence_ovh %{_mandir}/man8/fence_ovh.8* %package ovm License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Oracle VM provider Requires: python3-requests Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description ovm Fence agent for Oracle VM provider. %files ovm %{_sbindir}/fence_ovm %{_mandir}/man8/fence_ovm.8* # skipped from allfenceagents %package pve License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for PVE Requires: python3-pycurl Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description pve Fence agent for PVE. %files pve %{_sbindir}/fence_pve %{_mandir}/man8/fence_pve.8* # skipped from allfenceagents %package raritan License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Raritan Dominion PX Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description raritan Fence agent for Raritan Dominion PX. %files raritan %{_sbindir}/fence_raritan %{_mandir}/man8/fence_raritan.8* # skipped from allfenceagents %package rcd-serial License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for RCD serial Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description rcd-serial Fence agent for RCD serial. %files rcd-serial %{_sbindir}/fence_rcd_serial %{_mandir}/man8/fence_rcd_serial.8* %package redfish License: GPL-2.0-or-later AND LGPL-2.0-or-later Group: System Environment/Base Summary: Fence agent for Redfish Requires: fence-agents-common >= %{version}-%{release} Requires: python3-requests Obsoletes: fence-agents < 3.1.13 %description redfish The fence-agents-redfish package contains a fence agent for Redfish %files redfish %defattr(-,root,root,-) %{_sbindir}/fence_redfish %{_mandir}/man8/fence_redfish.8* %package rhevm License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for RHEV-M Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description rhevm Fence agent for RHEV-M via REST API. %files rhevm %{_sbindir}/fence_rhevm %{_mandir}/man8/fence_rhevm.8* %package rsa License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM RSA II Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description rsa Fence agent for IBM RSA II devices that are accessed via telnet or SSH. %files rsa %{_sbindir}/fence_rsa %{_mandir}/man8/fence_rsa.8* %package rsb License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Fujitsu RSB Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description rsb Fence agent for Fujitsu RSB devices that are accessed via telnet or SSH. %files rsb %{_sbindir}/fence_rsb %{_mandir}/man8/fence_rsb.8* %package sanbox2 License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for QLogic SANBox2 FC switches Requires: telnet Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description sanbox2 Fence agent for QLogic SANBox2 switches that are accessed via telnet. %files sanbox2 %{_sbindir}/fence_sanbox2 %{_mandir}/man8/fence_sanbox2.8* %package sbd License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for SBD (storage-based death) Requires: sbd Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description sbd Fence agent for SBD (storage-based death). %files sbd %{_sbindir}/fence_sbd %{_mandir}/man8/fence_sbd.8* %package scsi License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for SCSI persistent reservations Requires: sg3_utils Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description scsi Fence agent for SCSI persistent reservations. %files scsi %{_sbindir}/fence_scsi %{_datadir}/cluster/fence_scsi_check %{_datadir}/cluster/fence_scsi_check_hardreboot %{_mandir}/man8/fence_scsi.8* %package vbox License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for VirtualBox Requires: openssh-clients Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description vbox Fence agent for VirtualBox dom0 accessed via SSH. %files vbox %{_sbindir}/fence_vbox %{_mandir}/man8/fence_vbox.8* # skipped from allfenceagents %package virsh License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for virtual machines based on libvirt Requires: openssh-clients /usr/bin/virsh Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description virsh Fence agent for virtual machines that are accessed via SSH. %files virsh %{_sbindir}/fence_virsh %{_mandir}/man8/fence_virsh.8* %package vmware License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for VMWare with VI Perl Toolkit or vmrun Requires: python3-pexpect Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description vmware Fence agent for VMWare accessed with VI Perl Toolkit or vmrun. %files vmware %{_sbindir}/fence_vmware %{_mandir}/man8/fence_vmware.8* %package vmware-rest License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for VMWare with REST API Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch Obsoletes: fence-agents < 3.1.13 %description vmware-rest Fence agent for VMWare with REST API. %files vmware-rest %{_sbindir}/fence_vmware_rest %{_mandir}/man8/fence_vmware_rest.8* %package vmware-soap License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for VMWare with SOAP API v4.1+ %if 0%{?suse_version} > 1500 Requires: python3-suds-community %else Requires: python3-suds %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description vmware-soap Fence agent for VMWare with SOAP API v4.1+. %files vmware-soap %{_sbindir}/fence_vmware_soap %{_mandir}/man8/fence_vmware_soap.8* %package vmware-vcloud License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for VMWare vCloud Director Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch Obsoletes: fence-agents < 3.1.13 %description vmware-vcloud Fence agent for VMWare vCloud Director. %files vmware-vcloud %{_sbindir}/fence_vmware_vcloud %{_mandir}/man8/fence_vmware_vcloud.8* %package wti License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for WTI Network power switches Requires: openssh-clients %if 0%{?fedora} < 33 || (0%{?rhel} && 0%{?rhel} < 9) || (0%{?centos} && 0%{?centos} < 9) || 0%{?suse_version} Recommends: telnet %endif Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description wti Fence agent for WTI network power switches that are accessed via telnet or SSH. %files wti %{_sbindir}/fence_wti %{_mandir}/man8/fence_wti.8* %package xenapi License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for Citrix XenServer over XenAPI Requires: python3-pexpect Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description xenapi Fence agent for Citrix XenServer accessed over XenAPI. %files xenapi %{_sbindir}/fence_xenapi %{_datadir}/fence/XenAPI.py* %if 0%{?fedora} || 0%{?centos} || 0%{?rhel} %{_datadir}/fence/__pycache__/XenAPI.* %endif %{_mandir}/man8/fence_xenapi.8* %package zvm License: GPL-2.0-or-later AND LGPL-2.0-or-later Summary: Fence agent for IBM z/VM over IP Requires: fence-agents-common = %{version}-%{release} BuildArch: noarch %description zvm Fence agent for IBM z/VM over IP. %files zvm %{_sbindir}/fence_zvmip %{_mandir}/man8/fence_zvmip.8* # fence-virt %package -n fence-virt Summary: A pluggable fencing framework for virtual machines Requires(post): systemd-sysv %{systemd_units} Requires(preun): %{systemd_units} Requires(postun): %{systemd_units} %description -n fence-virt Fencing agent for virtual machines. %files -n fence-virt %doc agents/virt/docs/* %{_sbindir}/fence_virt %{_sbindir}/fence_xvm %{_mandir}/man8/fence_virt.* %{_mandir}/man8/fence_xvm.* %package -n fence-virtd Summary: Daemon which handles requests from fence-virt %description -n fence-virtd This package provides the host server framework, fence_virtd, for fence_virt. The fence_virtd host daemon is resposible for processing fencing requests from virtual machines and routing the requests to the appropriate physical machine for action. %files -n fence-virtd %{_sbindir}/fence_virtd %{_unitdir}/fence_virtd.service %config(noreplace) %{_sysconfdir}/fence_virt.conf %dir %{_libdir}/fence-virt %{_libdir}/fence-virt/vsock.so %{_mandir}/man5/fence_virt.conf.* %{_mandir}/man8/fence_virtd.* %package -n fence-virtd-multicast Summary: Multicast listener for fence-virtd Requires: fence-virtd %description -n fence-virtd-multicast Provides multicast listener capability for fence-virtd. %files -n fence-virtd-multicast %{_libdir}/fence-virt/multicast.so %package -n fence-virtd-serial Summary: Serial VMChannel listener for fence-virtd Requires: libvirt >= 0.6.2 Requires: fence-virtd %description -n fence-virtd-serial Provides serial VMChannel listener capability for fence-virtd. %files -n fence-virtd-serial %{_libdir}/fence-virt/serial.so %package -n fence-virtd-tcp Summary: TCP listener for fence-virtd Requires: fence-virtd %description -n fence-virtd-tcp Provides TCP listener capability for fence-virtd. %files -n fence-virtd-tcp %{_libdir}/fence-virt/tcp.so %package -n fence-virtd-libvirt Summary: Libvirt backend for fence-virtd Requires: libvirt >= 0.6.0 Requires: fence-virtd %description -n fence-virtd-libvirt Provides fence_virtd with a connection to libvirt to fence virtual machines. Useful for running a cluster of virtual machines on a desktop. %files -n fence-virtd-libvirt %{_libdir}/fence-virt/virt.so %package -n fence-virtd-cpg Summary: CPG/libvirt backend for fence-virtd Requires: corosynclib Requires: fence-virtd %description -n fence-virtd-cpg Provides fence_virtd with a connection to libvirt to fence virtual machines. Uses corosync CPG to keep track of VM locations to allow for non-local VMs to be fenced when VMs are located on corosync cluster nodes. %files -n fence-virtd-cpg %{_libdir}/fence-virt/cpg.so %changelog * @date@ Autotools generated version - @version@-@specver@-@numcomm@.@alphatag@.@dirty@ - Autotools generated version diff --git a/tests/data/metadata/fence_aws_vpc_net.xml b/tests/data/metadata/fence_aws_vpc_net.xml new file mode 100644 index 00000000..63607ce6 --- /dev/null +++ b/tests/data/metadata/fence_aws_vpc_net.xml @@ -0,0 +1,196 @@ + + +fence_aws_vpc is a Network and Power Fencing agent for AWS VPC that works by manipulating security groups. 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 NOTE: If onfence-poweroff is set, the agent won't be able to power on the node again, it will have to be powered on manually or with other automation. +http://www.amazon.com + + + + + Fencing action + + + + + AWS Instance ID to perform action on + + + + + AWS Instance ID to perform action on + + + + + AWS Region. + + + + + AWS Access Key. + + + + + AWS Secret Key. + + + + + Security Groups to remove. + + + + + Skip race condition check. + + + + + Remove all security groups except specified.. + + + + + Remove all security groups except specified.. + + + + + Remove all security groups except specified.. + + + + + Remove all security groups except specified.. + + + + + Filter for list-action + + + + + Boto Lib debug + + + + + Power off the machine async.. + + + + + Power off the machine async.. + + + + + Continue to fence even if backup tag fails.. + + + + + Continue to fence even if backup tag fails.. + + + + + Disable logging to stderr. Does not affect --verbose or --debug-file or logging to syslog. + + + + + Verbose mode. Multiple -v flags can be stacked on the command line (e.g., -vvv) to increase verbosity. + + + + + Level of debugging detail in output. Defaults to the number of --verbose flags specified on the command line, or to 1 if verbose=1 in a stonith device configuration (i.e., on stdin). + + + + + Write debug information to given file + + + + Write debug information to given file + + + + + Display version information and exit + + + + + Display help and exit + + + + + Separator for plug parameter when specifying more than 1 plug + + + + + Separator for CSV created by 'list' operation + + + + + Wait X seconds before fencing is started + + + + + Disable timeout (true/false) (default: true when run from Pacemaker 2.0+) + + + + + 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 + + + + + Sleep X seconds between status calls during a STONITH action + + + + + Count of attempts to retry power on + + + + + + + + + + + + + + +