Python OpenStack SDK does not return Hypervisor hostname

Monty Taylor mordred at inaugust.com
Thu Jun 25 13:50:04 UTC 2020



> On Jun 25, 2020, at 8:34 AM, Monty Taylor <mordred at inaugust.com> wrote:
> 
> 
> 
>> On Jun 23, 2020, at 6:46 PM, Sean Mooney <smooney at redhat.com> wrote:
>> 
>> On Wed, 2020-06-24 at 00:37 +0100, Sean Mooney wrote:
>>> On Tue, 2020-06-23 at 13:12 -0700, Anil Jangam wrote:
>>>> I have written a client code as follows.
>>>> 
>>>> # Get Hypervisor details
>>>> try:
>>>>   print(f"+----------------------------------------------------------+")
>>>>   print(f"| Hypervisor details                                       |")
>>>>   print(f"+----------------------------------------------------------+")
>>>>   for hypervisor in conn.list_hypervisors():
>>>>       print(f"Hypervisor is: {hypervisor}")
>>>>       print(f"Hypervisor status:      {hypervisor.status}")
>>>>       print(f"Hypervisor vcpus:       {hypervisor.vcpus_used}")
>>>>       print(f"Hypervisor type:        {hypervisor.hypervisor_type}")
>>>>       print(f"Hypervisor id:          {hypervisor.id}")
>>>>       print(f"Hypervisor state:       {hypervisor.state}")
>>>>       print(f"Hypervisor host IP:     {hypervisor.host_ip}")
>>>>       print(f"Hypervisor running VMs: {hypervisor.running_vms}")
>>>>       print(f"Hypervisor running VMs: {hypervisor.vcpus}")
>>>>       print(f"Hypervisor hostname:    {hypervisor.hypervisor_hostname}")
>>>> 
>>>>       print(f"")
>>>> except EndpointNotFound as exp:
>>>>   print("Error: {}".format(exp))
>>>>   print(f"")
>>>> 
>>>> When I print the 'hypervisor' object itself, most of the values are printed
>>>> as shown below, however when I try to access
>>>> 'hypervisor.hypervisor_hostname', it throws an exception.
>>>> 
>>>> +----------------------------------------------------------+
>>>>> Hypervisor details                                       |
>>>> 
>>>> +----------------------------------------------------------+
>>>> Hypervisor is: openstack.compute.v2.hypervisor.Hypervisor(status=enabled,
>>>> service={'host': 'cl3-Compute3', 'disabled_reason': None, 'id':
>>>> '34db399d-25b9-4004-98b9-2d8bbce7b228'}, vcpus_used=0,
>>>> hypervisor_type=QEMU, local_gb_used=0, vcpus=52,
>>>> hypervisor_hostname=cl3-Compute3, memory_mb_used=25600, memory_mb=262032,
>>>> current_workload=0, state=up, host_ip=192.168.10.116, cpu_info={'arch':
>>>> 'x86_64', 'model': 'Broadwell', 'vendor': 'Intel', 'features': ['pge',
>>>> 'avx', 'xsaveopt', 'clflush', 'sep', 'rtm', 'tsc_adjust', 'tsc-deadline',
>>>> 'dtes64', 'invpcid', 'tsc', 'fsgsbase', 'xsave', 'smap', 'vmx', 'erms',
>>>> 'xtpr', 'cmov', 'hle', 'smep', 'pcid', 'est', 'pat', 'monitor', 'smx',
>>>> 'pbe', 'lm', 'msr', 'adx', '3dnowprefetch', 'nx', 'fxsr', 'syscall', 'tm',
>>>> 'sse4.1', 'pae', 'sse4.2', 'pclmuldq', 'acpi', 'fma', 'vme', 'popcnt',
>>>> 'mmx', 'osxsave', 'cx8', 'mce', 'de', 'rdtscp', 'ht', 'dca', 'lahf_lm',
>>>> 'abm', 'rdseed', 'pdcm', 'mca', 'pdpe1gb', 'apic', 'sse', 'f16c', 'pse',
>>>> 'ds', 'invtsc', 'pni', 'tm2', 'avx2', 'aes', 'sse2', 'ss', 'ds_cpl',
>>>> 'arat', 'bmi1', 'bmi2', 'ssse3', 'fpu', 'cx16', 'pse36', 'mtrr', 'movbe',
>>>> 'rdrand', 'x2apic'], 'topology': {'cores': 14, 'cells': 2, 'threads': 2,
>>>> 'sockets': 1}}, running_vms=0, free_disk_gb=852,
>>>> hypervisor_version=2012000, disk_available_least=849, local_gb=852,
>>>> free_ram_mb=236432, id=1130407d-5afd-41f9-bc0c-2d7babda3ce7,
>>>> location=Munch({'cloud': 'defaults', 'region_name': 'RegionOne', 'zone':
>>>> None, 'project': Munch({'id': '6d4f1b107bbf4b94832f7ef72df61ef2', 'name':
>>>> '5g', 'domain_id': None, 'domain_name': 'default'})}))
>>>> Hypervisor status: enabled
>>>> Hypervisor vcpus: 0
>>>> Hypervisor type:     QEMU
>>>> Hypervisor id: 1130407d-5afd-41f9-bc0c-2d7babda3ce7
>>>> Hypervisor state: up
>>>> Hypervisor host IP: 192.168.10.116
>>>> Hypervisor running VMs: 0
>>>> Hypervisor running VMs: 52
>>>> Traceback (most recent call last):
>>>> File "/Users/workspace/testprogs/python/opsviz/ops_worker.py", line 321,
>>>> in <module>
>>>>   main()
>>>> File "/Users/workspace/testprogs/python/opsviz/ops_worker.py", line 317,
>>>> in main
>>>>   print_servers()
>>>> File "/Users/workspace/testprogs/python/opsviz/ops_worker.py", line 115,
>>>> in print_servers
>>>>   print(f"Hypervisor hostname: {hypervisor.hypervisor_hostname}")
>>>> File
>>>> "/Users/inventory/lib/python3.7/site-packages/openstack/resource.py", line
>>>> 588, in __getattribute__
>>>>   raise e
>>>> File
>>>> "/Users/inventory/lib/python3.7/site-packages/openstack/resource.py", line
>>>> 582, in __getattribute__
>>>>   return object.__getattribute__(self, name)
>>>> AttributeError: 'Hypervisor' object has no attribute 'hypervisor_hostname'
>>>> 
>>>> Is there anything wrong with the use of the API? How do I get the
>>>> hypervisor hostname in my application code?
>>> 
>>> looking at the fields that are in the hypervior object you are not hitting the /os-hypervisors
>>> list hyperviors endpoint but are instead hittig the /os-hypervisors/detail endpoint which inluded extra info
>>> both shoudl contain hypervisor_hostname
>>> https://docs.openstack.org/api-ref/compute/?expanded=list-hypervisors-details-detail
>>> is the doc for that api.
>>> 
>>> by default this is an admin only api.
>>> sean at pop-os:~$ openstack --os-cloud sean hypervisor list
>>> Policy doesn't allow os_compute_api:os-hypervisors:list-detail to be performed. (HTTP 403) (Request-ID: req-fbc50741-
>>> 5a73-4329-a00e-11eef79011ac)
>>> 
>>> so the fact that you are geting any results indicates that you are using admin creditals so you should recive the full
>>> responce and looking at the raw hypervisor print output i has the info so i would guess that its jut missing a
>>> property.
>>> 
>>> looking at https://github.com/openstack/openstacksdk/blob/master/openstack/compute/v2/hypervisor.py#L39
>>> it would appear that hypervisor_hostname is being stored in the name property.
>>> 
>>> im not sure why some of the fields where renamed
>>> https://github.com/openstack/openstacksdk/blob/master/openstack/compute/v2/hypervisor.py#L52-L57
>>> that feels like a poor desigin choice as it basically means the upstream api docs are not enough to use the sdk
>>> you need to girue out what then mapped the fields too.
>>> 
>>> the object also obviously contains the raw values too or they would not print when you print the object.
>>> 
>>> that is because that is falling back to the base resouce __repr__ function 
>>> 
>> https://github.com/openstack/openstacksdk/blob/8b5d4fe7985d3f9319b23121e290ef96dc801863/openstack/resource.py#L540-L552
>>> which prints the raw values.
>>> 
>>> at least i think that is what happening i have not looked at the sdk closely before.
>> it looks like it was renamed in patchest 2 of https://review.opendev.org/#/c/298900/2/openstack/compute/v2/hypervisor.py
>> and there is no discussion of why any of the new names were chosen in the proxy object and the api break was not called
>> out in the commit or a release note but since this was done 4 years ago im guessing it was before the sdk was considerd
>> stable or had reached its 1.0 so it was prably overlooked.
> 
> It predates me for sure.
> 
> I know in general the sdk api for resources is that things should have an id and a name and where some resources have decided to call their id field something different they get coerced because it’s super confusing to users to have to know that ‘id’ is called something else in some resources. This was probably done with that in mind.
> 
> That said - I also agree about it being confusing the other direction. We have a capability for aliasing fields in SDK that should be usable here. We’re using it on heat stacks, for instance, to allow sdk users to use id and name but still have stack_id and stack_name work.
> 
> I’ll get up a patch in just a sec.

https://review.opendev.org/738026 Provide hypervisor_hostname in Hypervisor object

Should do the trick.

> 
>> 
>> im not sure  if ths is something that can be fix and how widespread the problemn is but really the upstream names from
>> the api responce should also work IMO and this seams like an sdk bug to me.

In this case it’s pretty easy and seems like a good idea to provide both.

That said - there are MANY places in SDK where we rename upstream names. Sometimes it’s because upstream names are impossible to represent in attribute names ("os-extended-volumes:volumes_attached”)  Sometimes it’s because of confusing REST naming inconsistencies (hostId vs host_status). Sometimes it’s just to keep things consistent across services for SDK users (boolean flags are all verb-prefixed, so it’s is_locked and has_config_drive)

In general, the SDK has an API. It goes well out of its way to make sure that api works across releases and across services. That API may not always match the REST API for a given version of a different service, and not matching is frequently a conscious choice.

But that’s just for context - in this case I think it’s more than reasonable to provide hypervisor_hostname on the Hypervisor resource object.

>>> 
>>> 
>>> 
>>>> 
>>>> Thank you.




More information about the openstack-discuss mailing list