Bug 2024931

Summary: Fencing agent fence_vmware_rest is unable to handle names with VIO UUID's included
Product: Red Hat Enterprise Linux 8 Reporter: ttuffin
Component: fence-agentsAssignee: Oyvind Albrigtsen <oalbrigt>
Status: CLOSED NOTABUG QA Contact: cluster-qe <cluster-qe>
Severity: low Docs Contact:
Priority: unspecified    
Version: 8.6CC: cluster-maint, nwahl, pdwyer, pzimek, sbradley
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-02-28 08:36:09 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description ttuffin 2021-11-19 14:47:08 UTC
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.

Comment 3 Reid Wahl 2021-12-02 10:36:50 UTC
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]
~~~

Comment 4 Reid Wahl 2021-12-02 10:53:56 UTC
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.