/**
* Copyright (c) 2009--2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.manager.kickstart.cobbler;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.redhat.rhn.common.validator.ValidatorError;
import com.redhat.rhn.domain.kickstart.KickstartData;
import com.redhat.rhn.domain.kickstart.KickstartFactory;
import com.redhat.rhn.domain.kickstart.KickstartableTree;
import redstone.xmlrpc.XmlRpcFault;
/**
* This command finds profiles that have been changed on the cobbler server and syncs
* those changes to the satellite
* @version $Rev$
*/
public class CobblerProfileSyncCommand extends CobblerCommand {
private Logger log;
/**
* Command to sync unsynced Kickstart profiles to cobbler.
*/
public CobblerProfileSyncCommand() {
super();
log = Logger.getLogger(this.getClass());
}
/**
* Get a map of CobblerID -> profileMap from cobbler
* @return a list of cobbler profile names
*/
private Map<String, Map> getModifiedProfileNames() {
Map<String, Map> toReturn = new HashMap<String, Map>();
List<Map> profiles = (List<Map>)invokeXMLRPC("get_profiles", xmlRpcToken);
for (Map profile : profiles) {
toReturn.put((String)profile.get("uid"), profile);
}
return toReturn;
}
/**
* {@inheritDoc}
*/
@Override
public ValidatorError store() {
//First are there any profiles within spacewalk that aren't within cobbler
List<KickstartData> profiles = KickstartFactory.listAllKickstartData();
Map<String, Map> profileNames = getModifiedProfileNames();
for (KickstartData profile : profiles) {
/**
* workaround for bad data left in the DB (bz 525561)
*/
if (profile.getKickstartDefaults() == null) {
continue;
}
if (!profileNames.containsKey(profile.getCobblerId())) {
if (profile.getKickstartDefaults().getKstree().getCobblerId() == null) {
log.warn("Kickstart profile " + profile.getLabel() +
" could not be synced to cobbler, due to it's " +
"tree being unsynced. Please edit the tree url " +
"to correct this.");
}
else {
createProfile(profile);
profile.setModified(new Date());
}
}
}
log.debug(profiles);
log.debug(profileNames);
//Are there any profiles on cobbler that have changed
for (KickstartData profile : profiles) {
if (profileNames.containsKey(profile.getCobblerId())) {
Map cobProfile = profileNames.get(profile.getCobblerId());
log.debug(profile.getLabel() + ": " + cobProfile.get("mtime") +
" - " + profile.getModified().getTime());
if (((Double)cobProfile.get("mtime")).longValue() >
profile.getModified().getTime() / 1000) {
syncProfileToSpacewalk(cobProfile, profile);
}
}
}
return null;
}
private void createProfile(KickstartData profile) {
CobblerProfileCreateCommand creator = new CobblerProfileCreateCommand(profile);
creator.store();
}
/**
* Sync s the following things:
* Distro (if applicable)
*
* then overwrites the 'kickstart' attribute within the cobbler profile
* (in case they changed it to something spacewalk doesn't know about)
* @param cobblerProfile
* @param profile
*/
private void syncProfileToSpacewalk(Map cobblerProfile, KickstartData profile) {
log.debug("Syncing profile: " + profile.getLabel() + " known in cobbler as: " +
cobblerProfile.get("name"));
//Do we need to sync the distro?
Map distro = (Map) invokeXMLRPC("get_distro", cobblerProfile.get("distro"));
if (!distro.get("uid").equals(profile.getTree().getCobblerId()) &&
!distro.get("uid").equals(profile.getTree().getCobblerXenId())) {
//lookup the distro locally:
KickstartableTree tree = KickstartFactory.
lookupKickstartTreeByCobblerIdOrXenId((String)distro.get("uid"));
if (tree == null) {
log.error("Kickstartable tree was not found for Cobbler id:" +
(String)distro.get("uid"));
}
else {
profile.setTree(tree);
}
}
//Now re-set the filename in case someone set it incorrectly
try {
String handle = (String) invokeXMLRPC("get_profile_handle",
cobblerProfile.get("name"), xmlRpcToken);
invokeXMLRPC("modify_profile", handle, "kickstart", profile.buildCobblerFileName(),
xmlRpcToken);
invokeXMLRPC("save_profile", handle, xmlRpcToken);
//Lets update the modified date just to make sure
profile.setModified(new Date());
}
catch (RuntimeException re) {
if (re.getCause() instanceof XmlRpcFault) {
XmlRpcFault xrf = (XmlRpcFault)re.getCause();
if (xrf.getMessage().contains("unknown profile name")) {
log.error("Cobbler doesn't know about this profile any more!");
}
}
else {
throw re;
}
}
}
}