Bug 1440292 - Validate API URL to respond with proper error message
Summary: Validate API URL to respond with proper error message
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: ovirt-engine-sdk-python
Classification: oVirt
Component: Core
Version: 4.1.3
Hardware: Unspecified
OS: Unspecified
unspecified
low
Target Milestone: ovirt-4.1.3
: 4.1.5
Assignee: Ondra Machacek
QA Contact: Petr Kubica
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2017-04-07 19:45 UTC by Reto Gantenbein
Modified: 2017-07-06 13:18 UTC (History)
6 users (show)

Fixed In Version: python-ovirt-engine-sdk4-4.1.5
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2017-07-06 13:18:53 UTC
oVirt Team: Infra
Embargoed:
rule-engine: ovirt-4.1+
lsvaty: testing_ack+


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
oVirt gerrit 75402 0 master MERGED Improve error message for wrong content type 2020-12-31 20:17:00 UTC
oVirt gerrit 75433 0 master MERGED Improve error message for wrong content type 2020-12-31 20:17:03 UTC
oVirt gerrit 75435 0 master MERGED Improve error message for wrong content type 2020-12-31 20:17:03 UTC
oVirt gerrit 75485 0 sdk_4.1 MERGED Improve error message for wrong content type 2020-12-31 20:17:37 UTC
oVirt gerrit 75487 0 sdk_4.1 MERGED Improve error message for wrong content type 2020-12-31 20:17:03 UTC
oVirt gerrit 75488 0 sdk_4.1 MERGED Improve error message for wrong content type 2020-12-31 20:17:03 UTC
oVirt gerrit 75755 0 master MERGED Check content type only when really needed 2020-12-31 20:17:03 UTC
oVirt gerrit 76460 0 sdk_4.1 MERGED Check content type only when really needed 2020-12-31 20:17:38 UTC
oVirt gerrit 77907 0 master MERGED Fix checking of fault response 2020-12-31 20:17:01 UTC
oVirt gerrit 77912 0 sdk_4.1 MERGED Fix checking of fault response 2020-12-31 20:17:39 UTC

Description Reto Gantenbein 2017-04-07 19:45:28 UTC
Description of problem:
When using the 'ovirt' Ansible modules for the first time, I made a mistake by not specifying the full URL in the corresponding option. This resulted in a rather generic error message:

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Exception: Can't read first node
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "Can't read first node"}

After searching the Ansible project for a hint, I stepped over [1] which mentioned this error message with a differently related HTTP 404 error. This made me aware of the wrong URL being the cause of my error message.


Version-Release number of selected component (if applicable):
- ansible 2.3.0.0 (detached HEAD f15e1f25ae)
- ovirt-engine-sdk-python 4.1.3


How reproducible:
Always


Steps to Reproduce:
Define a ovirt_auth task in Ansible with https://<ovirt-host>/ (missing the 'ovirt-engine/api' context root) 


Actual results:
"Can't read first node" python error


Expected results:
Error message indicating a HTTP error or wrong URL format


Additional info:
[1]: https://github.com/ansible/ansible/issues/19801

Comment 1 Juan Hernández 2017-04-10 08:36:47 UTC
Currently we are trying to parse the returned document as XML, but when the URL is incorrect the server will most likely return an HTML error message. Trying to parse that HTML as XML is what causes the "Can't read first node" message. We should probably check the "Conten-Type" header returned by the server, and generate a better error message in that case. That error message could include a hint about the URL. For example, we could return an error message like this, if the value of the 'url' parameter is not the typical one:

  The server returned content type 'text/html', but we expected 'text/xml'.
  Are you sure you are using the correct 'url' parameter? The typical one is
  '/ovirt-engine/api', but you are using '/'.

What we should not do, in my opinion, is forbid the use of other URLs.

If we decided to check the returned 'Content-Type' header then we need to be careful, as it may have multiple valid values:

  text/xml
  text/xml; charset=utf-8
  application/xml
  application/xml; charset=utf-8

Currently the server always returns 'application/xml', but that may change in the future.

Comment 2 Juan Hernández 2017-04-20 15:27:24 UTC
The current fix didn't take into account that the server doesn't return any content type for responses that don't have a body. For example, the following code will trigger a 404 error, without a response body, and without a content type:

   vm_service = vms_service.vm_service('doesnotexist')
   vm_service.get()

With the current fix that generates the following trackeback:

  Traceback (most recent call last):
    File "...", line 41, in <module>
      vm_service.get()
    File ".../ovirtsdk4/services.py", line 30596, in get
      response = self._connection.send(request)
    File ".../ovirtsdk4/__init__.py", line 295, in send
      return self.__send(request)
    File ".../ovirtsdk4/__init__.py", line 408, in __send
      self._check_content_type(self.__XML_CONTENT_TYPE_RE, 'XML', content_type)
    File ".../ovirtsdk4/__init__.py", line 689, in _check_content_type
      if expected_re.match(actual) is None:
  TypeError: expected string or buffer

Comment 3 Petr Kubica 2017-06-06 14:23:33 UTC
used: python-ovirt-engine-sdk4-4.1.4-1.el7ev.x86_64
tested url: "https://<engine-url>/ugly"

The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_RjJ0si/ansible_module_ovirt_datacenters.py", line 210, in main
    ret = clusters_module.create()
  File "/tmp/ansible_RjJ0si/ansible_modlib.zip/ansible/module_utils/ovirt.py", line 537, in create
    entity = self.search_entity(search_params)
  File "/tmp/ansible_RjJ0si/ansible_modlib.zip/ansible/module_utils/ovirt.py", line 757, in search_entity
    entity = search_by_attributes(self._service, name=self._module.params['name'])
  File "/tmp/ansible_RjJ0si/ansible_modlib.zip/ansible/module_utils/ovirt.py", line 229, in search_by_attributes
    search=' and '.join('{}={}'.format(k, v) for k, v in kwargs.items())
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/services.py", line 4401, in list
    return self._internal_get(headers, query, wait)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 202, in _internal_get
    return future.wait() if wait else future
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 53, in wait
    return self._code(response)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 199, in callback
    self._check_fault(response)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/service.py", line 123, in _check_fault
    body = reader.Reader.read(response.body)
  File "/usr/lib64/python2.7/site-packages/ovirtsdk4/reader.py", line 297, in read
    cursor = xml.XmlReader(io.BytesIO(source.encode('utf-8')))
Exception: Can't read first node

fatal: [<engine-url>]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "invocation": {
        "module_args": {
            "comment": null, 
            "compatibility_version": "4.0", 
            "description": null, 
            "fetch_nested": false, 
            "local": true, 
            "mac_pool": null, 
            "name": "mydatacenter", 
            "nested_attributes": [], 
            "poll_interval": 3, 
            "quota_mode": "enabled", 
            "state": "present", 
            "timeout": 180, 
            "wait": true
        }
    }, 
    "msg": "Can't read first node"
}

Comment 4 Red Hat Bugzilla Rules Engine 2017-06-06 14:23:40 UTC
Target release should be placed once a package build is known to fix a issue. Since this bug is not modified, the target version has been reset. Please use target milestone to plan a fix for a oVirt release.

Comment 5 Petr Kubica 2017-06-14 12:11:56 UTC
Verified in python-ovirt-engine-sdk4-4.1.5-1.el7ev.x86_64

Error: The response content type 'text/html; charset=iso-8859-1' isn't the expected XML. Is the path '/ugly' included in the 'url' parameter correct? The typical one is '/ovirt-engine/api'


Note You need to log in before you can comment on or make changes to this bug.