java/buildconf/apidoc/html/macros.txt | 5
java/buildconf/apidoc/jsp/macros.txt | 5
java/buildconf/apidoc/singlepage/macros.txt | 79 +++
java/code/src/com/redhat/rhn/common/db/datasource/xml/Errata_queries.xml | 10
java/code/src/com/redhat/rhn/common/db/datasource/xml/config_queries.xml | 61 ++
java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java | 239
+++++++++-
java/code/src/com/redhat/rhn/manager/action/ActionManager.java | 65 ++
web/conf/rhn_web.conf | 2
8 files changed, 458 insertions(+), 8 deletions(-)
New commits:
commit 4bbcadff178a8ee783be7c6be15a9a7e090c5888
Author: Brad Buckingham <bbuckingham(a)redhat.com>
Date: Tue Jun 2 12:30:16 2009 -0400
501224 - api - enhance system.listSystemEvents to include more detail on events
executed
Currently, when a user looks at the event history in the UI, they see
more information than they can currently obtain with the API.
For example,
- for a package action (e.g. install/remove/upgrade/verify)
- user can see the pkgs that were involved in the event
- for an errata update
- user can see the advisory name & synopsis
- for a config file deploy/upload
- user can see the file name and possibly revision info
- for a config file compare/diff
- user can see the files compared and the differences found
The above information is not returned in the API; therefore, enhancing the
system.listSystemEvents to include an optional 'additional_info' array
that will include this information when it is available.
One thing to note is that these details are stored in different tables
depending on the action that was executed. As a result, we have to
perform different queries depending on the action type; therefore, rather
than use a basic serializer, the api handler itself will gather the results
and populate the data to be returned.
diff --git a/java/buildconf/apidoc/html/macros.txt
b/java/buildconf/apidoc/html/macros.txt
index 87c3b8b..f7a70d2 100644
--- a/java/buildconf/apidoc/html/macros.txt
+++ b/java/buildconf/apidoc/html/macros.txt
@@ -22,6 +22,11 @@
<ul>
<li>
#end
+#macro(prop_array_begin_desc $key $desc)
+ <li>array "$key" - $desc
+ <ul>
+ <li>
+#end
#macro(prop_array_end)
</li>
</ul>
diff --git a/java/buildconf/apidoc/jsp/macros.txt b/java/buildconf/apidoc/jsp/macros.txt
index 87c3b8b..f7a70d2 100644
--- a/java/buildconf/apidoc/jsp/macros.txt
+++ b/java/buildconf/apidoc/jsp/macros.txt
@@ -22,6 +22,11 @@
<ul>
<li>
#end
+#macro(prop_array_begin_desc $key $desc)
+ <li>array "$key" - $desc
+ <ul>
+ <li>
+#end
#macro(prop_array_end)
</li>
</ul>
diff --git a/java/buildconf/apidoc/singlepage/macros.txt
b/java/buildconf/apidoc/singlepage/macros.txt
new file mode 100644
index 0000000..f7a70d2
--- /dev/null
+++ b/java/buildconf/apidoc/singlepage/macros.txt
@@ -0,0 +1,79 @@
+
+#set($date="dateTime.iso8601")
+
+#macro( serializer $serializer )
+ <li> $serializer </li>
+#end
+#macro( prop $type $value )
+ <li> $type "$value"</li>
+#end
+#macro( prop_desc $type $value $desc )
+ <li> $type "$value" - $desc </li>
+#end
+#macro(prop_array $key $type $desc)
+ <li>array "$key"
+ <ul>
+ <li>$type $desc</li>
+ </ul>
+ </li>
+#end
+#macro(prop_array_begin $key)
+ <li>array "$key"
+ <ul>
+ <li>
+#end
+#macro(prop_array_begin_desc $key $desc)
+ <li>array "$key" - $desc
+ <ul>
+ <li>
+#end
+#macro(prop_array_end)
+ </li>
+ </ul>
+ </li>
+#end
+#macro( struct $type )
+ struct - $type
+ <ul>
+#end
+#macro( struct_end )
+ </ul>
+#end
+#macro( array)
+array:
+ <ul>
+ <li>
+#end
+#macro(array_end)
+</li></ul>
+#end
+#macro(array_single $type $desc)
+array:
+<ul>
+ <li>$type - $desc</li>
+</ul>
+#end
+#macro(options)
+ <ul>
+#end
+#macro(item $item)
+ <li>$item</li>
+#end
+#macro(item_desc $item, $desc)
+ <li>$item - $desc</li>
+#end
+#macro(options_end)
+ </ul>
+#end
+#macro(param $type $value)
+ $type $value
+#end
+#macro(param_desc $type $value $desc)
+ $type $value - $desc
+#end
+#macro(session_key)
+ #param("string", "sessionKey")
+#end
+#macro(return_int_success)
+ int - 1 on success, exception thrown otherwise.
+#end
diff --git a/java/code/src/com/redhat/rhn/common/db/datasource/xml/Errata_queries.xml
b/java/code/src/com/redhat/rhn/common/db/datasource/xml/Errata_queries.xml
index 6f8915f..78a3e84 100644
--- a/java/code/src/com/redhat/rhn/common/db/datasource/xml/Errata_queries.xml
+++ b/java/code/src/com/redhat/rhn/common/db/datasource/xml/Errata_queries.xml
@@ -1175,6 +1175,14 @@ SELECT 1
</query>
</mode>
-
+<mode name="errata_associated_with_action">
+ <query params="aid">
+SELECT E.id, E.advisory, E.synopsis
+ FROM rhnErrata E,
+ rhnActionErrataUpdate AEU
+ WHERE E.id = AEU.errata_id
+ AND AEU.action_id = :aid
+ </query>
+</mode>
</datasource_modes>
diff --git a/java/code/src/com/redhat/rhn/common/db/datasource/xml/config_queries.xml
b/java/code/src/com/redhat/rhn/common/db/datasource/xml/config_queries.xml
index 6ea33fb..256a68c 100644
--- a/java/code/src/com/redhat/rhn/common/db/datasource/xml/config_queries.xml
+++ b/java/code/src/com/redhat/rhn/common/db/datasource/xml/config_queries.xml
@@ -2152,6 +2152,67 @@ SELECT CC.id, CR.revision AS config_revision,
</elaborator>
</mode>
+<mode name="upload_action_status">
+ <query params="aid">
+SELECT CFN.path,
+ CFF.name AS FAILURE_REASON
+ FROM rhnConfigFileFailure CFF,
+ rhnConfigFileName CFN,
+ rhnActionConfigFileName ACFN
+ WHERE ACFN.action_id = :aid
+ AND ACFN.config_file_name_id = CFN.id
+ AND ACFN.failure_id = CFF.id (+)
+ORDER BY CFN.path
+ </query>
+</mode>
+
+<mode name="config_action_revisions">
+ <query params="aid">
+SELECT CFN.path,
+ CR.id,
+ CR.revision,
+ ACR.id AS ACTION_REVISION_ID,
+ CFF.name AS FAILURE_REASON
+ FROM rhnConfigFileFailure CFF,
+ rhnConfigFileName CFN,
+ rhnConfigFile CF,
+ rhnConfigRevision CR,
+ rhnActionConfigRevision ACR
+ WHERE ACR.action_id = :aid
+ AND ACR.config_revision_id = CR.id
+ AND CR.config_file_id = CF.id
+ AND CF.config_file_name_id = CFN.id
+ AND ACR.failure_id = CFF.id (+)
+ORDER BY UPPER(CFN.path)
+ </query>
+</mode>
+
+<mode name="diff_action_revisions">
+ <query params="aid">
+SELECT CFN.path,
+ CR.id,
+ CR.id AS REVISION_ID,
+ CR.revision,
+ ACR.id AS ACTION_REVISION_ID,
+ CFF.name AS FAILURE_REASON,
+ ACRR.result AS DIFF,
+ rhn_config_channel.action_diff_revision_status(ACR.id) AS STATUS
+ FROM rhnConfigFileFailure CFF,
+ rhnConfigFileName CFN,
+ rhnConfigFile CF,
+ rhnConfigRevision CR,
+ rhnActionConfigRevision ACR,
+ rhnActionConfigRevisionResult ACRR
+ WHERE ACR.action_id = :aid
+ AND ACR.config_revision_id = CR.id
+ AND CR.config_file_id = CF.id
+ AND CF.config_file_name_id = CFN.id
+ AND ACRR.action_config_revision_id = ACR.id
+ AND ACR.failure_id = CFF.id (+)
+ORDER BY UPPER(CFN.path)
+ </query>
+</mode>
+
<callable-mode name="create_new_config_channel">
<query params="org_id_in, type_in, name_in, label_in,
description_in">
{:channelId = call rhn_config.insert_channel( :org_id_in, :type_in, :name_in,
:label_in, :description_in)}
diff --git a/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java
b/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java
index aa5a3ab..ed29fd5 100644
--- a/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java
+++ b/java/code/src/com/redhat/rhn/frontend/xmlrpc/system/SystemHandler.java
@@ -16,6 +16,7 @@ package com.redhat.rhn.frontend.xmlrpc.system;
import java.net.URI;
import java.net.URISyntaxException;
+import java.sql.Blob;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -35,6 +36,7 @@ import com.redhat.rhn.FaultException;
import com.redhat.rhn.common.client.ClientCertificate;
import com.redhat.rhn.common.conf.Config;
import com.redhat.rhn.common.db.datasource.DataResult;
+import com.redhat.rhn.common.hibernate.HibernateFactory;
import com.redhat.rhn.common.hibernate.LookupException;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.validator.ValidatorError;
@@ -1645,26 +1647,251 @@ public class SystemHandler extends BaseHandler {
* @param sessionKey The sessionKey containing the logged in user
* @param sid The id of the server you are wanting to lookup
* @return Returns an array of maps representing a system
- * @since 10.3
+ * @since 10.8
*
- * @xmlrpc.doc List all system events for given server. This is *all* events for the
- * server since it was registered. This may require the caller to
+ * @xmlrpc.doc List all system events for given server. This includes *all* events
+ * for the server since it was registered. This may require the caller to
* filter the results to fetch the specific events they are looking for.
*
* @xmlrpc.param #param("string", "sessionKey")
* @xmlrpc.param #param("int", "serverId") - ID of system.
* @xmlrpc.returntype
* #array()
- * $ServerActionSerializer
+ * #struct("action")
+ * #prop_desc("int", "failed_count", "Number of
times action failed.")
+ * #prop_desc("string", "modified", "Date modified.
(Deprecated by
+ * modified_date)")
+ * #prop_desc($date, "modified_date", "Date modified.")
+ * #prop_desc("string", "created", "Date created.
(Deprecated by
+ * created_date)")
+ * #prop_desc($date, "created_date", "Date created.")
+ * #prop("string", "action_type")
+ * #prop_desc("int", "successful_count",
+ * "Number of times action was successful.")
+ * #prop_desc("string", "earliest_action",
"Earliest date this action
+ * will occur.")
+ * #prop_desc("int", "archived", "If this action is
archived. (1 or 0)")
+ * #prop("string", "scheduler_user")
+ * #prop_desc("string", "prerequisite",
"Pre-requisite action. (optional)")
+ * #prop_desc("string", "name", "Name of this
action.")
+ * #prop_desc("int", "id", "Id of this
action.")
+ * #prop_desc("string", "version", "Version of
action.")
+ * #prop_desc("string", "completion_time", "The
date/time the event was
+ * completed. Format ->YYYY-MM-dd hh:mm:ss.ms
+ * Eg ->2007-06-04 13:58:13.0. (optional)
+ * (Deprecated by completed_date)")
+ * #prop_desc($date, "completed_date", "The date/time the
event was completed.
+ * (optional)")
+ * #prop_desc("string", "pickup_time", "The
date/time the action was picked
+ * up. Format ->YYYY-MM-dd hh:mm:ss.ms
+ * Eg ->2007-06-04 13:58:13.0. (optional)
+ * (Deprecated by pickup_date)")
+ * #prop_desc($date, "pickup_date", "The date/time the action
was picked up.
+ * (optional)")
+ * #prop_desc("string", "result_msg", "The result
string after the action
+ * executes at the client machine. (optional)")
+ * #prop_array_begin_desc("additional_info", "This array
contains additional
+ * information for the event, if available.")
+ * #struct("info")
+ * #prop_desc("string", "detail", "The
detail provided depends on the
+ * specific event. For example, for a package event, this will be
the
+ * package name, for an errata event, this will be the advisory
name
+ * and synopsis, for a config file event, this will be path and
+ * optional revision information...etc.")
+ * #prop_desc("string", "result", "The
result (if included) depends
+ * on the specific event. For example, for a package or errata
event,
+ * no result is included, for a config file event, the result might
+ * include an error (if one occurred, such as the file was missing)
+ * or in the case of a config file comparison it might include the
+ * differenes found.")
+ * #struct_end()
+ * #prop_array_end()
+ * #struct_end()
* #array_end()
*/
- public List<ServerAction> listSystemEvents(String sessionKey, Integer sid) {
+ public List listSystemEvents(String sessionKey, Integer sid) {
+
List retval = new LinkedList();
// Get the logged in user and server
User loggedInUser = getLoggedInUser(sessionKey);
Server server = lookupServer(loggedInUser, sid);
- return ActionFactory.listServerActionsForServer(server);
+ List<ServerAction> sActions =
ActionFactory.listServerActionsForServer(server);
+
+ // In order to support bug 501224, this method is being updated to populate
+ // the result vs having the serializer do so. The reason is that in order to
+ // support this bug, we want to be able to return some additional detail for the
+ // various events in the system history; however, those details are stored in
+ // different database tables depending upon the event type. This includes
+ // information like, the specific errata applied, pkgs installed/removed/
+ // upgraded/verified, config files uploaded, deployed or compared...etc.
+
+ List<Map> results = new ArrayList<Map>();
+ for (ServerAction sAction : sActions) {
+
+ Map result = new HashMap();
+
+ Action action = sAction.getParentAction();
+
+ if (action.getFailedCount() != null) {
+ result.put("failed_count", action.getFailedCount());
+ }
+ if (action.getActionType().getName() != null) {
+ result.put("action_type", action.getActionType().getName());
+ }
+ if (action.getSuccessfulCount() != null) {
+ result.put("successful_count", action.getSuccessfulCount());
+ }
+ if (action.getEarliestAction() != null) {
+ result.put("earliest_action",
action.getEarliestAction().toString());
+ }
+ if (action.getArchived() != null) {
+ result.put("archived", action.getArchived());
+ }
+ if (action.getSchedulerUser().getLogin() != null) {
+ result.put("scheduler_user",
action.getSchedulerUser().getLogin());
+ }
+ if (action.getPrerequisite() != null) {
+ result.put("prerequisite", action.getPrerequisite());
+ }
+ if (action.getName() != null) {
+ result.put("name", action.getName());
+ }
+ if (action.getId() != null) {
+ result.put("id", action.getId());
+ }
+ if (action.getVersion() != null) {
+ result.put("version", action.getVersion().toString());
+ }
+
+ if (sAction.getCompletionTime() != null) {
+ result.put("completion_time",
sAction.getCompletionTime().toString());
+ }
+ if (sAction.getPickupTime() != null) {
+ result.put("pickup_time", sAction.getPickupTime().toString());
+ }
+ if (sAction.getModified() != null) {
+ result.put("modified", sAction.getModified().toString());
+ result.put("modified_date", sAction.getModified());
+ }
+ if (sAction.getCreated() != null) {
+ result.put("created", sAction.getCreated().toString());
+ result.put("created_date", sAction.getCreated());
+ }
+ if (sAction.getCompletionTime() != null) {
+ result.put("completed_date", sAction.getCompletionTime());
+ }
+ if (sAction.getPickupTime() != null) {
+ result.put("pickup_date", sAction.getPickupTime());
+ }
+ if (sAction.getResultMsg() != null) {
+ result.put("result_msg", sAction.getResultMsg());
+ }
+
+ // depending on the event type, we need to retrieve additional information
+ // and store that information in the result
+ ActionType type = action.getActionType();
+ List<Map<String, String>> additionalInfo = new
ArrayList<Map<String, String>>();
+
+ if (type.equals(ActionFactory.TYPE_PACKAGES_REMOVE) ||
+ type.equals(ActionFactory.TYPE_PACKAGES_UPDATE) ||
+ type.equals(ActionFactory.TYPE_PACKAGES_VERIFY)) {
+
+ // retrieve the list of package names associated with the action...
+
+ DataResult pkgs = ActionManager.getPackageList(action.getId(), null);
+ for (Iterator itr = pkgs.iterator(); itr.hasNext();) {
+ Map pkg = (Map) itr.next();
+ String detail = (String) pkg.get("nvre");
+
+ Map<String, String> info = new HashMap<String,
String>();
+ info.put("detail", detail);
+ additionalInfo.add(info);
+ }
+ }
+ else if (type.equals(ActionFactory.TYPE_ERRATA)) {
+
+ // retrieve the errata that were associated with the action...
+ DataResult errata = ActionManager.getErrataList(action.getId());
+ for (Iterator itr = errata.iterator(); itr.hasNext();) {
+ Map erratum = (Map) itr.next();
+ String detail = (String) erratum.get("advisory");
+ detail += " (" + (String) erratum.get("synopsis")
+ ")";
+
+ Map<String, String> info = new HashMap<String,
String>();
+ info.put("detail", detail);
+ additionalInfo.add(info);
+ }
+ }
+ else if (type.equals(ActionFactory.TYPE_CONFIGFILES_UPLOAD) ||
+ type.equals(ActionFactory.TYPE_CONFIGFILES_MTIME_UPLOAD)) {
+
+ // retrieve the details associated with the action...
+ DataResult files =
ActionManager.getConfigFileUploadList(action.getId());
+ for (Iterator itr = files.iterator(); itr.hasNext();) {
+ Map file = (Map) itr.next();
+
+ Map<String, String> info = new HashMap<String,
String>();
+ info.put("detail", (String) file.get("path"));
+ String error = (String) file.get("failure_reason");
+ if (error != null) {
+ info.put("result", error);
+ }
+ additionalInfo.add(info);
+ }
+ }
+ else if (type.equals(ActionFactory.TYPE_CONFIGFILES_DEPLOY)) {
+
+ // retrieve the details associated with the action...
+ DataResult files =
ActionManager.getConfigFileDeployList(action.getId());
+ for (Iterator itr = files.iterator(); itr.hasNext();) {
+ Map file = (Map) itr.next();
+
+ Map<String, String> info = new HashMap<String,
String>();
+ String path = (String) file.get("path");
+ path += " (rev. " + (Long) file.get("revision") +
")";
+ info.put("detail", path);
+ String error = (String) file.get("failure_reason");
+ if (error != null) {
+ info.put("result", error);
+ }
+ additionalInfo.add(info);
+ }
+ }
+ else if (type.equals(ActionFactory.TYPE_CONFIGFILES_DIFF)) {
+
+ // retrieve the details associated with the action...
+ DataResult files = ActionManager.getConfigFileDiffList(action.getId());
+ for (Iterator itr = files.iterator(); itr.hasNext();) {
+ Map file = (Map) itr.next();
+
+ Map<String, String> info = new HashMap<String,
String>();
+ String path = (String) file.get("path");
+ path += " (rev. " + (Long) file.get("revision") +
")";
+ info.put("detail", path);
+
+ String error = (String) file.get("failure_reason");
+ if (error != null) {
+ info.put("result", error);
+ }
+ else {
+ // if there wasn't an error, check to see if there was a
difference
+ // detected...
+ Blob blob = (Blob) file.get("diff");
+ if (blob != null) {
+ String diff = HibernateFactory.blobToString(blob);
+ info.put("result", diff);
+ }
+ }
+ additionalInfo.add(info);
+ }
+ }
+ if (additionalInfo.size() > 0) {
+ result.put("additional_info", additionalInfo);
+ }
+ results.add(result);
+ }
+ return results;
}
/**
diff --git a/java/code/src/com/redhat/rhn/manager/action/ActionManager.java
b/java/code/src/com/redhat/rhn/manager/action/ActionManager.java
index 612c3b4..c8c3de5 100644
--- a/java/code/src/com/redhat/rhn/manager/action/ActionManager.java
+++ b/java/code/src/com/redhat/rhn/manager/action/ActionManager.java
@@ -763,6 +763,71 @@ public class ActionManager extends BaseManager {
dr.setTotalSize(dr.size());
return dr;
}
+
+ /**
+ * Returns the list of errata associated with a specific action.
+ * @param aid The action id for the action in question
+ * @return Return a list containing the errata for the action.
+ */
+ public static DataResult getErrataList(Long aid) {
+ SelectMode m = ModeFactory.getMode("Errata_queries",
+ "errata_associated_with_action");
+
+ Map params = new HashMap();
+ params.put("aid", aid);
+
+ DataResult dr = m.execute(params);
+ dr.setTotalSize(dr.size());
+ return dr;
+ }
+
+ /**
+ * Returns the list of details associated with a config file upload action.
+ * @param aid The action id for the action in question
+ * @return Return a list containing the errata for the action.
+ */
+ public static DataResult getConfigFileUploadList(Long aid) {
+ SelectMode m = ModeFactory.getMode("config_queries",
"upload_action_status");
+
+ Map params = new HashMap();
+ params.put("aid", aid);
+
+ DataResult dr = m.execute(params);
+ dr.setTotalSize(dr.size());
+ return dr;
+ }
+
+ /**
+ * Returns the list of details associated with a config file deploy action.
+ * @param aid The action id for the action in question
+ * @return Return a list containing the details for the action.
+ */
+ public static DataResult getConfigFileDeployList(Long aid) {
+ SelectMode m = ModeFactory.getMode("config_queries",
"config_action_revisions");
+
+ Map params = new HashMap();
+ params.put("aid", aid);
+
+ DataResult dr = m.execute(params);
+ dr.setTotalSize(dr.size());
+ return dr;
+ }
+
+ /**
+ * Returns the list of details associated with a config file diff action.
+ * @param aid The action id for the action in question
+ * @return Return a list containing the details for the action.
+ */
+ public static DataResult getConfigFileDiffList(Long aid) {
+ SelectMode m = ModeFactory.getMode("config_queries",
"diff_action_revisions");
+
+ Map params = new HashMap();
+ params.put("aid", aid);
+
+ DataResult dr = m.execute(params);
+ dr.setTotalSize(dr.size());
+ return dr;
+ }
/**
* Retrieves the systems that have completed a given action
diff --git a/web/conf/rhn_web.conf b/web/conf/rhn_web.conf
index c6d86de..a9a640d 100644
--- a/web/conf/rhn_web.conf
+++ b/web/conf/rhn_web.conf
@@ -228,7 +228,7 @@ web.config_delim_end = |}
web.version = 0.5
# the version of API
-web.apiversion = 10.7
+web.apiversion = 10.8
# maximum size for a config file
web.maximum_config_file_size = 131072