Description of problem: In a VMWare vSphere environment with VMware Integrated OpenStack (VIO), VM's that are managed by VIO have names in the following format: "<VM short name> (VIO UUID)". This means that when using the 'fence_vmware_rest' fencing agent hostnames are reported back with the VIO UUID included, for example: "host01 (f3285ba4-6246-4284-bbd8-5964c2564518),(<vSphere UUID>)". The inclusion of the VIO UUID appears to cause the agent to fail with "ERROR: Failed: Unable to obtain correct plug status or plug is not available" when specifying the VM hostname/short name. The 'fence_vmware_soap' agent does work when specify the vSphere UUID, but this is not an option in environments where SOAP is not available or not allowed. Version-Release number of selected component (if applicable): fence-agents-vmware-rest-4.2.1-41.el7_9.3.x86_64 How reproducible: Always Steps to Reproduce: # fence_vmware_rest -a 'host01.example.com' -l 'svc_abcde' -p 'PASSWORD' --ipport=443 -o status --shell-timeout=30 --plug=fencinghost01.example.com 2020-11-09 17:08:23,965 ERROR: Failed: Unable to obtain correct plug status or plug is not available Actual results: 'fence_vmware_rest' agent fails when VIO UUID is included in the vSphere VM name. Expected results: 'fence_vmware_rest' agent handles the VIO UUID by stripping it and using the VM hostname/short name.
I read over some of the REST API docs today and checked the API responses from the BRQ vCenter to see what we do and don't get. It's frustrating to say the least. The list outputs don't display the VM UUID in any form (which we've already established in another BZ). Running a GET on a particular VM also doesn't seem to give us the UUID. Another really bad limitation: The filterspec in `vcenter/vm?filter` calls doesn't appear to allow wildcards. You have to specify a list of exactly whatever term you want to match. Here is the best workaround I've come up with. Every VM seems to have a unique ID, which is the value of the 'vm' key of the response dict. In the following example, the ID is vm-1038. {'value': [{'memory_size_MiB': 16384, 'vm': 'vm-1038', 'name': 'ocp4-hl8r8-master-1', 'power_state': 'POWERED_OFF', 'cpu_count': 4}]} We could make a small modification to the fence agent to allow users to pass VM IDs rather than names. We could choose the lookup type in one of at least two ways: 1. Create a new boolean option that says the plug is a VM ID instead of a VM name. This keeps the number of API calls in the fence agent the same. We would build our API call based on whether the "plug_is_id" option is set or not. (Pick a different option name.) 2. Try to look up a plug as a VM ID first and then fall back to looking up the plug as a name if that fails. This requires a tad less work on the user's part but potentially doubles the amount of work on the fence agent's part. I'd prefer option #1 unless you all think of a better approach or find an API mechanism that I didn't find. Something like this (rough draft, seems to work fine): ~~~ def get_power_status(conn, options): if options["--plug_is_id"]: options["id"] = options["--plug"] try: res = send_command(conn, "vcenter/vm/{}".format(urllib.quote(options["--plug"])))["value"]["power_state"] except Exception as e: logging.debug("Failed: {}".format(e)) fail(EC_STATUS) result = res else: try: res = send_command(conn, "vcenter/vm?filter.names={}".format(urllib.quote(options["--plug"])))["value"] except Exception as e: logging.debug("Failed: {}".format(e)) fail(EC_STATUS) if len(res) == 0: fail(EC_STATUS) options["id"] = res[0]["vm"] result = res[0]["power_state"] return state[result] ~~~
Ah, looks like all we have to do is quote the VM name that's of the format `<vm_name> (<vm_uuid>)`. Oyvind will have details. I had a mistake in my command line when I tried that simple approach. Thanks, all.