Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.

Bug 1117278

Summary: [python-sdk] Unable to delete storageconnection object
Product: [Retired] oVirt Reporter: Gadi Ickowicz <gickowic>
Component: ovirt-engine-apiAssignee: Daniel Erez <derez>
Status: CLOSED CURRENTRELEASE QA Contact: Raz Tamir <ratamir>
Severity: high Docs Contact:
Priority: unspecified    
Version: 3.5CC: acanan, ajia, amureini, bugs, gklein, iheim, juan.hernandez, nlevinki, rbalakri, yeylon
Target Milestone: ---   
Target Release: 3.5.0   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard: storage
Fixed In Version: ovirt-3.5.0_rc2 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-10-17 12:43:28 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: Storage RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
engine logs none

Description Gadi Ickowicz 2014-07-08 12:42:09 UTC
Created attachment 916355 [details]
engine logs

Description of problem:
Unable to delete storage connection object from python-sdk (when not passing a Host to the delet() function):

>>> api.storageconnections.get(id=c.get_id()).delete()
send: 'GET /api/storageconnections/85afd2fb-fcdd-4b99-a863-9c6143614ce7 HTTP/1.1\r\nHost: 127.0.0.1\r\nAccept-Encoding: identity\r\nSession-TTL: 60\r\nPrefer: persistent-auth\r\nAccept: application/xml\r\nFilter:
False\r\ncookie: JSESSIONID=TG6Gr8H8jhdev-sjcK-99qgn.undefined\r\nContent-type: application/xml\r\nAuthorization: Basic YWRtaW5AaW50ZXJuYWw6MQ==\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Date: Tue, 08 Jul 2014 11:12:44 GMT
header: Pragma: No-cache
header: Cache-Control: no-cache
header: Expires: Thu, 01 Jan 1970 02:00:00 IST
header: JSESSIONID: TG6Gr8H8jhdev-sjcK-99qgn.undefined
header: Content-Type: application/xml
header: Content-Length: 310
header: Vary: Accept-Encoding
header: Connection: close
body:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<storage_connection href="/api/storageconnections/85afd2fb-fcdd-4b99-a863-9c6143614ce7" id="85afd2fb-fcdd-4b99-a863-9c6143614ce7">
    <address>1.1.1.1</address>
    <type>iscsi</type>
    <port>3260</port>
    <target>555</target>
</storage_connection>

send: 'DELETE /api/storageconnections/85afd2fb-fcdd-4b99-a863-9c6143614ce7 HTTP/1.1\r\nHost: 127.0.0.1\r\nAccept-Encoding: identity\r\nContent-Length: 8\r\nSession-TTL: 60\r\nPrefer: persistent-auth\r\nAccept: app
lication/xml\r\nFilter: False\r\ncookie: JSESSIONID=TG6Gr8H8jhdev-sjcK-99qgn.undefined\r\nContent-type: application/xml\r\nAuthorization: Basic YWRtaW5AaW50ZXJuYWw6MQ==\r\n\r\n'
send: '<host/>\n'
reply: 'HTTP/1.1 404 Not Found\r\n'
header: Date: Tue, 08 Jul 2014 11:12:44 GMT
header: JSESSIONID: TG6Gr8H8jhdev-sjcK-99qgn.undefined
header: Content-Type: application/xml
header: Content-Length: 142
header: Vary: Accept-Encoding
header: Connection: close
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/lib/python2.6/site-packages/ovirtsdk/infrastructure/brokers.py", line 10461, in delete
    headers={"Correlation-Id":correlation_id}
  File "/usr/lib/python2.6/site-packages/ovirtsdk/infrastructure/proxy.py", line 68, in delete
    return self.request('DELETE', url, body, headers)
  File "/usr/lib/python2.6/site-packages/ovirtsdk/infrastructure/proxy.py", line 118, in request
    persistent_auth=self._persistent_auth)
  File "/usr/lib/python2.6/site-packages/ovirtsdk/infrastructure/proxy.py", line 146, in __doRequest
    persistent_auth=persistent_auth
  File "/usr/lib/python2.6/site-packages/ovirtsdk/web/connection.py", line 134, in doRequest
    raise RequestError, response
RequestError: 
status: 404
reason: Not Found
detail: Entity not found: null

Version-Release number of selected component (if applicable):
ovirt-engine-sdk-python-3.5.0.0-1.20140605.git1267422.el6.noarch
ovirt-engine-3.5.0-0.0.master.20140629172257.git0b16ed7.el6.noarch


How reproducible:
100%

Steps to Reproduce:
See command from python console above

Actual results:
Fails to delete storage connection with 404 not found error

Expected results:
Should delete the storage connection

Additional info:
Fails in engine with the following error:
2014-07-08 14:16:41,432 ERROR [org.ovirt.engine.api.restapi.resource.AbstractBackendResource] (ajp--127.0.0.1-8702-3) Operation Failed: Entity not found: null

Comment 1 Juan Hernández 2014-07-08 12:48:52 UTC
This happens because the definition of the delete operation of this resource includes a parameter of type Host. The generator of the Python SDK only expects parameters of type Action for delete operations, and when that parameter isn't given it creates an empty instance. In this case it creates an empty instance of the Host entity, that results in sending the following request:

  DELETE /api/storageconnections/85afd2fb-fcdd-4b99-a863-9c6143614ce
  <host/>

This empty <host/> element triggers a NPE in the RESTAPI.

In my opinion we should change the storage connections delete operation so that it takes an Action as parameter, like all other delete operations. This action can contain a Host, so we still can pass a host as parameter. This is a small backwards compatibility breakage, but one that is justified.

We should also add validations in the storage connections resource to validate that when a host is provided its id or name is provided as well, as trying to access that is what is triggering the NPE.

Comment 2 Allon Mureinik 2014-07-08 13:44:44 UTC
(In reply to Juan Hernández from comment #1)
> In my opinion we should change the storage connections delete operation so
> that it takes an Action as parameter, like all other delete operations. This
> action can contain a Host, so we still can pass a host as parameter. This is
> a small backwards compatibility breakage, but one that is justified.
Agreed.

Comment 4 Raz Tamir 2014-10-02 06:01:37 UTC
What is the new/correct way to delete this object after this patch?

Comment 5 Juan Hernández 2014-10-02 08:17:22 UTC
If you are using directly the REST API it should be like this:

  #!/bin/sh -ex

  url="https://ovirt.example.com/ovirt-engine/api"
  user="admin@internal"
  password="******"
  storageconnectionid="..."

  curl \
  --verbose \
  --insecure \
  --request DELETE \
  --user "${user}:${password}" \
  --header "Content-Type: application/xml" \
  --header "Accept: application/xml" \
  --data "\
  <action/>
  " \
  "${url}/storageconnections/${storageconnectionid}"

If you are using the Python SDK:

  #!/usr/bin/python

  import ovirtsdk.api
  import ovirtsdk.xml

  api = ovirtsdk.api.API(
    url="https://ovirt.example.com/ovirt-engine/api",
    username="admin@internal",
    password="******",
    ca_file="/etc/pki/ovirt-engine/ca.pem",
  )

  storageconnectionid = "..."

  action = ovirtsdk.xml.params.Action()
  api.storageconnections.get(id=storageconnectionid).delete(action)

  api.disconnect()

If you also want to disconnect the storage then you will need to provide the reference to the host that will perform the operation. With a shell script you just need to change the submitted data:

  <action>
    <host>
      <name>myhost</myhost>
    </host>
  </action>

Or using the host id:

  <action>
    <host id="..."/>
  </action>

With the Python SDK change the way the Action object is created:

  action = ovirtsdk.xml.params.Action(
    host=ovirtsdk.xml.params.Host(name="myhost")
  )

Or using the host id:

  action = ovirtsdk.xml.params.Action(
    host=ovirtsdk.xml.params.Host(id="...")
  )

Comment 6 Raz Tamir 2014-10-02 08:31:29 UTC
Verified - follow the steps in comment 5

Comment 7 Sandro Bonazzola 2014-10-17 12:43:28 UTC
oVirt 3.5 has been released and should include the fix for this issue.