Bug 556956 - server.channel.software.list_subscribed_systems API call fails when there is an unentitled system subscribed to the channel
Summary: server.channel.software.list_subscribed_systems API call fails when there is ...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Satellite 5
Classification: Red Hat
Component: Server
Version: 530
Hardware: All
OS: Linux
high
high
Target Milestone: ---
Assignee: Justin Sherrill
QA Contact: Garik Khachikyan
URL:
Whiteboard:
Depends On:
Blocks: sat531-api
TreeView+ depends on / blocked
 
Reported: 2010-01-19 22:27 UTC by Xixi
Modified: 2018-10-27 15:43 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2010-03-03 14:17:52 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2010:0128 0 normal SHIPPED_LIVE Red Hat Network Satellite bug fix update 2010-03-03 14:17:49 UTC

Description Xixi 2010-01-19 22:27:34 UTC
Description of problem:
The RHN API call server.channel.software.list_subscribed_systems fails with a
traceback whenever there is an unentitled system subscribed to the channel it's querying.

Traceback (most recent call last):
  File "./reproducer.py", line 22, in ?
    subsystems = getSubSystems()
  File "./reproducer.py", line 19, in getSubSystems
    subsystems = server.channel.software.list_subscribed_systems(session,channel_label)
  File "/usr/lib/python2.3/xmlrpclib.py", line 1029, in __call__
    return self.__send(self.__name, args)
  File "/usr/lib/python2.3/xmlrpclib.py", line 1316, in __request
    verbose=self.__verbose
  File "/usr/lib/python2.3/xmlrpclib.py", line 1080, in request
    return self._parse_response(h.getfile(), sock)
  File "/usr/lib/python2.3/xmlrpclib.py", line 1219, in _parse_response
    return u.close()
  File "/usr/lib/python2.3/xmlrpclib.py", line 740, in close
    raise ResponseError()
xmlrpclib.ResponseError: <xmlrpclib.ResponseError instance at 0xb7d08e4c>

or

Traceback (most recent call last):
 File "./test.py", line 22, in <module>
   subsystems = getSubSystems()
 File "./test.py", line 19, in getSubSystems
   subsystems = server.channel.software.list_subscribed_systems(session,channel_label)
 File "/usr/lib/python2.6/xmlrpclib.py", line 1199, in __call__
   return self.__send(self.__name, args)
 File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
   verbose=self.__verbose
 File "/usr/lib/python2.6/xmlrpclib.py", line 1253, in request
   return self._parse_response(h.getfile(), sock)
 File "/usr/lib/python2.6/xmlrpclib.py", line 1387, in _parse_response
   p.feed(response)
 File "/usr/lib/python2.6/xmlrpclib.py", line 601, in feed
   self._parser.Parse(data, 0)
xml.parsers.expat.ExpatError: XML or text declaration not at start of entity: line 1, column 4260

Version-Release number of selected component (if applicable):
Red Hat Network (RHN) Satellite 5.3.0

How reproducible:
Always.

Steps to Reproduce:
1. Have a satellite with at least 2 systems subscribed to a channel - 1 unentitled the other entitled.
2. Use subsystems = server.channel.software.list_subscribed_systems(session,channel_label) to get listing of subscribed systems to the channel.

Actual results:
traceback (above) and tomcat error in catalina.out:
...
Jan 19, 2010 5:19:53 PM redstone.xmlrpc.XmlRpcDispatcher writeError
WARNING: java.lang.NullPointerException: null
...

Expected results:
No error (or handle it gracefully), returns results.

Additional info:
The issue appears to be caused by systems_subscribed_to_channel returning null for selectable when a system is not entitled.
Internal reproducer info to follow.

Comment 1 Xixi 2010-01-19 22:32:11 UTC
*With all systems entitled under channel*:

[388553]$ ./reproducer.py
{'selectable': 1, 'id': 1000010003, 'name': 'system-1'}
{'selectable': 1, 'id': 1000010025, 'name': 'system-2'}
{'selectable': 1, 'id': 1000010125, 'name': 'system-3'}
{'selectable': 1, 'id': 1000010105, 'name': 'system-4'}

*After un-entitling system-3*:

[388553]$ ./reproducer.py
Traceback (most recent call last):
 File "./reproducer.py", line 22, in ?
   subsystems = getSubSystems()
 File "./reproducer.py", line 19, in getSubSystems
   subsystems = server.channel.software.list_subscribed_systems(session,channel_label)
 File "/usr/lib/python2.3/xmlrpclib.py", line 1029, in __call__
   return self.__send(self.__name, args)
 File "/usr/lib/python2.3/xmlrpclib.py", line 1316, in __request
   verbose=self.__verbose
 File "/usr/lib/python2.3/xmlrpclib.py", line 1080, in request
   return self._parse_response(h.getfile(), sock)
 File "/usr/lib/python2.3/xmlrpclib.py", line 1219, in _parse_response
   return u.close()
 File "/usr/lib/python2.3/xmlrpclib.py", line 740, in close
   raise ResponseError()
xmlrpclib.ResponseError: <xmlrpclib.ResponseError instance at 0xb7d08e4c>

The query used by the API call is in System_queries - systems_subscribed_to_channel :

SELECT
      S.id as id,
      S.name as name,
         (SELECT 1
         FROM rhnServerFeaturesView SFV
        WHERE SFV.server_id = S.id
          AND SFV.label = 'ftr_system_grouping') AS selectable
 FROM rhnServerChannel SC,
      rhnServer S
WHERE S.org_id = 1
  AND S.id = SC.server_id
  AND SC.channel_id = 101
  AND EXISTS (SELECT 1 FROM rhnUserServerPerms USP WHERE USP.user_id = 1 AND USP.server_id = S.id)
ORDER BY UPPER(NVL(S.NAME, '(none)')), S.ID;

which returns:

       ID
----------
NAME
--------------------------------------------------------------------------------
SELECTABLE
----------
1000010003
system-1
        1

1000010025
system-2
        1

1000010125
system-3


1000010105
system-4
        1

So it appears with un-entitled systems 'selectable' returns as null in the underlying dataquery used by the API call, and that's causing the NullPointerException when writing response.  

Proposed fix: change the dataquery so it returns 0 in case of NULL?


Relevant code -

spacewalk-java-0.5.44/code/src/com/redhat/rhn/frontend/xmlrpc/channel/software/ChannelSoftwareHandler.java
...
   /**
    * Returns list of subscribed systems for the given channel label.
    * @param sessionKey WebSession containing User information.
    * @param label Label of the channel in question.
    * @return Returns an array of maps representing a system. Contains system id and
    * system name for each system subscribed to this channel.
    * @throws FaultException A FaultException is thrown if:
    *   - Logged in user is not a channel admin.
    *   - Channel does not exist.
    *
    * @xmlrpc.doc Returns list of subscribed systems for the given channel label
    * @xmlrpc.param #session_key()
    * @xmlrpc.param #param_desc("string", "channelLabel", "channel to query")
    * @xmlrpc.returntype
    *          #array()
    *              #struct("system")
    *                  #prop("int", "id")
    *                  #prop("string", "name")
    *              #struct_end()
    *           #array_end()
    */
   public Object[] listSubscribedSystems(String sessionKey, String label)
       throws FaultException {

       User user = getLoggedInUser(sessionKey);

       // Make sure user has access to the orgs channels
       if (!user.hasRole(RoleFactory.CHANNEL_ADMIN)) {
           throw new PermissionCheckFailureException();
       }

       // Get the channel.
       Channel channel = lookupChannelByLabel(user.getOrg(), label);

       DataResult dr = SystemManager.systemsSubscribedToChannel(channel, user);
       return dr.toArray();
   }
...

spacewalk-java-0.5.44/code/src/com/redhat/rhn/manager/system/SystemManager.java
...
   /**
    * Returns a DataResult containing the systems subscribed to a particular channel.
    * @param channel The channel in question
    * @param user The user making the call
    * @return Returns a DataResult of maps containing the ids and names of systems
    * subscribed to a channel.
    */
   public static DataResult systemsSubscribedToChannel(Channel channel, User user) {
       Map params = new HashMap();
       params.put("user_id", user.getId());
       params.put("cid", channel.getId());
       params.put("org_id", user.getOrg().getId());

       SelectMode m = ModeFactory.getMode("System_queries",
                          "systems_subscribed_to_channel", Map.class);
       return m.execute(params);
   }
...

...
<mode name="systems_subscribed_to_channel">
 <query params="org_id, cid, user_id">
SELECT
      S.id as id,
      S.name as name,
         (SELECT 1
         FROM rhnServerFeaturesView SFV
        WHERE SFV.server_id = S.id
          AND SFV.label = 'ftr_system_grouping') AS selectable
 FROM rhnServerChannel SC,
      rhnServer S
WHERE S.org_id = :org_id
  AND S.id = SC.server_id
  AND SC.channel_id = :cid
  AND EXISTS (SELECT 1 FROM rhnUserServerPerms USP WHERE USP.user_id = :user_id AND USP.server_id = S.id)
ORDER BY UPPER(NVL(S.NAME, '(none)')), S.ID
 </query>
 <elaborator name="system_overview" />
 <elaborator name="entitlements"/>
</mode>
...
<query name="entitlements" params="" multiple="t">
 SELECT SEV.server_id AS ID,
        SEV.label AS ENTITLEMENT,
        SEV.server_group_type_id,
        SEV.permanent AS entitlement_permanent,
        SEV.is_base AS entitlement_is_base
   FROM rhnServerEntitlementView SEV
  WHERE SEV.server_id IN (%s)
ORDER BY DECODE(SEV.is_base,'Y',1,'N',2), SEV.label
</query>
...

Comment 3 Justin Sherrill 2010-02-04 18:49:38 UTC
3088b972b25a41ad567f9b84b53cf3acac631ff8

Fixed in master.  Ended up just removing that item from the map.  Not the cleanest solution, but it works ok.

Comment 5 Tomas Lestach 2010-02-17 13:53:51 UTC
satellite.git: 10137f86712537156300d0fb9ab6782b9c2e5de5

Comment 7 Garik Khachikyan 2010-02-18 13:18:48 UTC
# VERIFIED

The following brewroot build(s) fixing the issue:
RHEL-4-RHNSAT5.3: http://brewweb.devel.redhat.com/brew/buildinfo?buildID=125979
RHEL-5-RHNSAT5.3: http://brewweb.devel.redhat.com/brew/buildinfo?buildID=125978

call of the channel.software.list_subscribed_systems for a channel that contains unentitled systems goes fine without any exceptions now.

Comment 9 errata-xmlrpc 2010-03-03 14:17:52 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHBA-2010-0128.html


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