diff --git a/fence/agents/azure_arm/fence_azure_arm.py b/fence/agents/azure_arm/fence_azure_arm.py index ac49b861..2b11050d 100644 --- a/fence/agents/azure_arm/fence_azure_arm.py +++ b/fence/agents/azure_arm/fence_azure_arm.py @@ -1,144 +1,143 @@ #!@PYTHON@ -tt import sys, re, pexpect import logging import atexit sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay def get_nodes_list(compute_client, options): result = {} if compute_client: rgName = options["--resourceGroup"] vms = compute_client.virtual_machines.list(rgName) try: for vm in vms: result[vm.name] = ("", None) except Exception as e: fail_usage("Failed: %s" % e) return result def get_power_status(compute_client, options): logging.info("getting power status for VM " + options["--plug"]) if compute_client: rgName = options["--resourceGroup"] vmName = options["--plug"] powerState = "unknown" try: vmStatus = compute_client.virtual_machines.get(rgName, vmName, "instanceView") except Exception as e: fail_usage("Failed: %s" % e) for status in vmStatus.instance_view.statuses: if status.code.startswith("PowerState"): powerState = status.code break logging.info("Found power state of VM: " + powerState) if powerState == "PowerState/running": return "on" return "off" def set_power_status(compute_client, options): logging.info("setting power status for VM " + options["--plug"] + " to " + options["--action"]) if compute_client: rgName = options["--resourceGroup"] vmName = options["--plug"] if (options["--action"]=="off"): logging.info("Deallocating " + vmName + "in resource group " + rgName) compute_client.virtual_machines.deallocate(rgName, vmName) elif (options["--action"]=="on"): logging.info("Starting " + vmName + "in resource group " + rgName) compute_client.virtual_machines.start(rgName, vmName) def define_new_opts(): all_opt["resourceGroup"] = { "getopt" : ":", "longopt" : "resourceGroup", "help" : "--resourceGroup=[name] Name of the resource group", "shortdesc" : "Name of resource group.", "required" : "1", "order" : 2 } all_opt["tenantId"] = { "getopt" : ":", "longopt" : "tenantId", "help" : "--tenantId=[name] Id of the Azure Active Directory tenant", "shortdesc" : "Id of Azure Active Directory tenant.", "required" : "1", "order" : 3 } all_opt["subscriptionId"] = { "getopt" : ":", "longopt" : "subscriptionId", "help" : "--subscriptionId=[name] Id of the Azure subscription", "shortdesc" : "Id of the Azure subscription.", "required" : "1", "order" : 4 } # Main agent method def main(): compute_client = None device_opt = ["resourceGroup", "login", "passwd", "tenantId", "subscriptionId","port"] atexit.register(atexit_handler) define_new_opts() all_opt["power_timeout"]["default"] = "150" all_opt["login"]["help"] = "-l, --username=[appid] Application ID" all_opt["passwd"]["help"] = "-p, --password=[authkey] Authentication key" options = check_input(device_opt, process_input(device_opt)) docs = {} docs["shortdesc"] = "Fence agent for Azure Resource Manager" docs["longdesc"] = "Used to deallocate virtual machines and to report power state of virtual machines running in Azure. It uses Azure SDK for Python to connect to Azure.\ \n.P\n\ For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal\ \n.P\n\ Username and password are application ID and authentication key from \"App registrations\"." docs["vendorurl"] = "http://www.microsoft.com" show_docs(options, docs) run_delay(options) try: from azure.common.credentials import ServicePrincipalCredentials from azure.mgmt.compute import ComputeManagementClient tenantid = options["--tenantId"] servicePrincipal = options["--username"] spPassword = options["--password"] subscriptionId = options["--subscriptionId"] credentials = ServicePrincipalCredentials( client_id = servicePrincipal, secret = spPassword, tenant = tenantid ) compute_client = ComputeManagementClient( credentials, subscriptionId ) except ImportError: fail_usage("Azure Resource Manager Python SDK not found or not accessible") except Exception as e: fail_usage("Failed: %s" % re.sub("^, ", "", str(e))) # Operate the fencing device result = fence_action(compute_client, options, set_power_status, get_power_status, get_nodes_list) sys.exit(result) if __name__ == "__main__": - main() - \ No newline at end of file + main() \ No newline at end of file diff --git a/fence/agents/azure_arm/fence_azure_arm_network.py b/fence/agents/azure_arm/fence_azure_arm_network.py index d77c6ade..6a6b0760 100644 --- a/fence/agents/azure_arm/fence_azure_arm_network.py +++ b/fence/agents/azure_arm/fence_azure_arm_network.py @@ -1,215 +1,215 @@ #!@PYTHON@ -tt import sys, re, pexpect import logging import atexit sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing import fail, fail_usage, EC_TIMED_OUT, run_delay import time import azure_fence_lib #import ptvsd def get_azure_config(options): config = azure_fence_lib.AzureConfiguration() config.RGName = options.get("--resourceGroup") config.VMName = options.get("--plug") config.SubscriptionId = options.get("--subscriptionId") config.Cloud = options.get("--cloud") config.UseMSI = options.get("--useMSI") config.Tenantid = options.get("--tenantId") config.ApplicationId = options.get("--username") config.ApplicationKey = options.get("--password") config.Verbose = options.get("--verbose") return config def get_nodes_list(clients, options): logging.info("{get_nodes_list}") result = {} if clients: compute_client = clients[0] network_client = clients[1] rgName = options["--resourceGroup"] logging.info("{get_nodes_list} listing virtual machines") vms = compute_client.virtual_machines.list(rgName) logging.info("{get_nodes_list} listing virtual machines done") try: for vm in vms: allOk = True for nicRef in vm.network_profile.network_interfaces: logging.info("{get_nodes_list} testing network interface %s" % nicRef.id) nicresource = azure_fence_lib.get_azure_resource(nicRef.id) nic = network_client.network_interfaces.get(nicresource.ResourceGroupName, nicresource.ResourceName) if nic.ip_configurations: for ipConfig in nic.ip_configurations: logging.info("{get_nodes_list} testing network interface ip config") fenceSubnet = azure_fence_lib.get_fence_subnet_for_config(ipConfig, network_client) testOk = azure_fence_lib.test_fence_subnet(fenceSubnet, nic, network_client) if not testOk: allOk = False if allOk: logging.info("{get_nodes_list} Virtual machine %s can be fenced" % vm.name) result[vm.name] = ("", None) except Exception as e: fail_usage("{get_nodes_list} Failed: %s" % e) else: fail_usage("{get_nodes_list} No Azure clients configured. Contact support") return result def get_power_status(clients, options): logging.info("{get_power_status} getting power status for VM %s" % (options["--plug"])) result = azure_fence_lib.FENCE_STATE_ON if clients: compute_client = clients[0] network_client = clients[1] rgName = options["--resourceGroup"] vmName = options["--plug"] result = azure_fence_lib.get_power_status_impl(compute_client, network_client, rgName, vmName) else: fail_usage("{get_power_status} No Azure clients configured. Contact support") logging.info("{get_power_status} result is %s" % result) return result def set_power_status(clients, options): logging.info("{set_power_status} setting power status for VM " + options["--plug"] + " to " + options["--action"]) if clients: compute_client = clients[0] network_client = clients[1] rgName = options["--resourceGroup"] vmName = options["--plug"] try: if (options["--action"]=="off"): azure_fence_lib.set_power_status_off(compute_client, network_client, rgName, vmName) elif (options["--action"]=="on"): azure_fence_lib.set_power_status_on(compute_client, network_client, rgName, vmName) except Exception as e: fail_usage("Failed: %s" % e) else: fail_usage("No Azure clients configured. Contact support") logging.info("{set_power_status} done") def define_new_opts(): all_opt["resourceGroup"] = { "getopt" : ":", "longopt" : "resourceGroup", "help" : "--resourceGroup=[name] Name of the resource group", "shortdesc" : "Name of resource group.", "required" : "1", "order" : 2 } all_opt["tenantId"] = { "getopt" : ":", "longopt" : "tenantId", "help" : "--tenantId=[name] Id of the Azure Active Directory tenant", "shortdesc" : "Id of Azure Active Directory tenant.", "required" : "0", "order" : 3 } all_opt["subscriptionId"] = { "getopt" : ":", "longopt" : "subscriptionId", "help" : "--subscriptionId=[name] Id of the Azure subscription", "shortdesc" : "Id of the Azure subscription.", "required" : "1", "order" : 4 } all_opt["useMSI"] = { "getopt" : ":", "longopt" : "useMSI", "help" : "--useMSI=[value] Determines if Managed Service Identity should be used instead of username and password. If this parameter is specified, parameters tenantId, login and passwd are not allowed.", "shortdesc" : "Determines if Managed Service Identity should be used.", "required" : "0", "order" : 5 } all_opt["cloud"] = { "getopt" : ":", "longopt" : "cloud", "help" : "--cloud=[value] Name of the cloud you want to use. Supported values are china, germany or usgov. Do not use this parameter if you want to use public Azure", "shortdesc" : "Name of the cloud you want to use.", "required" : "0", "order" : 6 } # Main agent method def main(): - logging.getLogger().setLevel(logging.INFO) + #logging.getLogger().setLevel(logging.INFO) # handler = logging.StreamHandler(sys.stdout) # handler.setFormatter(logging.Formatter(fmt='%(asctime)s %(levelname)-8s %(message)s',datefmt='%a, %d %b %Y %H:%M:%S')) # logging.getLogger().addHandler(handler) compute_client = None network_client = None device_opt = None credentials = None atexit.register(atexit_handler) define_new_opts() all_opt["power_timeout"]["default"] = "150" all_opt["login"]["help"] = "-l, --username=[appid] Application ID" all_opt["passwd"]["help"] = "-p, --password=[authkey] Authentication key" msi_opt = ["resourceGroup","subscriptionId","port","useMSI","login","passwd","tenantId","cloud","no_login","no_password"] msiOptions = process_input(msi_opt) if "--action" in msiOptions and (msiOptions["--action"] == "meta-data" or msiOptions["--action"] == "metadata"): logging.info("{main} Checking params metadata") device_opt = msi_opt elif "--useMSI" in msiOptions: logging.info("{main} Checking params MSI") device_opt = ["resourceGroup", "subscriptionId","port","useMSI","no_login","no_password"] else: logging.info("{main} Checking params Service Principal") device_opt = ["resourceGroup", "login", "passwd", "tenantId", "subscriptionId","port","cloud"] options = check_input(device_opt, msiOptions) docs = {} docs["shortdesc"] = "Fence agent for Azure Resource Manager" docs["longdesc"] = "Used to deallocate virtual machines and to report power state of virtual machines running in Azure. It uses Azure SDK for Python to connect to Azure.\ \n.P\n\ For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal\ \n.P\n\ Username and password are application ID and authentication key from \"App registrations\"." docs["vendorurl"] = "http://www.microsoft.com" show_docs(options, docs) run_delay(options) try: #if options["--action"] != "metadata": # ptvsd.enable_attach('my_secret') # ptvsd.wait_for_attach() from azure.mgmt.compute import ComputeManagementClient from azure.mgmt.network import NetworkManagementClient config = get_azure_config(options) compute_client = azure_fence_lib.get_azure_compute_client(config) network_client = azure_fence_lib.get_azure_network_client(config) except ImportError as ie: fail_usage("Azure Resource Manager Python SDK not found or not accessible: %s" % re.sub("^, ", "", str(ie))) except Exception as e: fail_usage("Failed: %s" % re.sub("^, ", "", str(e))) # Operate the fencing device result = fence_action([compute_client,network_client], options, set_power_status, get_power_status, get_nodes_list) sys.exit(result) if __name__ == "__main__": main() diff --git a/tests/data/metadata/fence_azure_arm_network.xml b/tests/data/metadata/fence_azure_arm_network.xml index 5d58128f..663ef637 100644 --- a/tests/data/metadata/fence_azure_arm_network.xml +++ b/tests/data/metadata/fence_azure_arm_network.xml @@ -1,157 +1,157 @@ - - -Used to deallocate virtual machines and to report power state of virtual machines running in Azure. It uses Azure SDK for Python to connect to Azure. -.P -For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal -.P -Username and password are application ID and authentication key from "App registrations". -http://www.microsoft.com - - - - - Fencing action - - - - - Application ID - - - - - Authentication key - - - - - Script to run to retrieve password - - - - - Authentication key - - - - - Script to run to retrieve password - - - - - Physical plug number on device, UUID or identification of machine - - - - - Physical plug number on device, UUID or identification of machine - - - - - Application ID - - - - - Name of resource group. - - - - - Id of Azure Active Directory tenant. - - - - - Id of the Azure subscription. - - - - - Determines if Managed Service Identity should be used. - - - - - Name of the cloud you want to use. - - - - - 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 - - - - - - - - - - - - - - \ No newline at end of file + + +Used to deallocate virtual machines and to report power state of virtual machines running in Azure. It uses Azure SDK for Python to connect to Azure. +.P +For instructions to setup credentials see: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal +.P +Username and password are application ID and authentication key from "App registrations". +http://www.microsoft.com + + + + + Fencing action + + + + + Application ID + + + + + Authentication key + + + + + Script to run to retrieve password + + + + + Authentication key + + + + + Script to run to retrieve password + + + + + Physical plug number on device, UUID or identification of machine + + + + + Physical plug number on device, UUID or identification of machine + + + + + Application ID + + + + + Name of resource group. + + + + + Id of Azure Active Directory tenant. + + + + + Id of the Azure subscription. + + + + + Determines if Managed Service Identity should be used. + + + + + Name of the cloud you want to use. + + + + + 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 + + + + + + + + + + + + + +