/*
* Embedded Jopr Project
* Copyright (C) 2006-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.jboss.on.embedded.manager.pc;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.configuration.ConfigurationAgentService;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUtility;
import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService;
import org.rhq.core.clientapi.agent.inventory.CreateResourceRequest;
import org.rhq.core.clientapi.agent.inventory.CreateResourceResponse;
import org.rhq.core.clientapi.agent.inventory.DeleteResourceRequest;
import org.rhq.core.clientapi.agent.inventory.DeleteResourceResponse;
import org.rhq.core.clientapi.agent.inventory.ResourceFactoryAgentService;
import org.rhq.core.clientapi.agent.operation.OperationAgentService;
import org.rhq.core.clientapi.server.configuration.ConfigurationUpdateResponse;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.operation.OperationDefinition;
import org.rhq.core.domain.resource.CreateResourceStatus;
import org.rhq.core.domain.resource.DeleteResourceStatus;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pc.PluginContainer;
import org.jboss.seam.core.Events;
import org.jboss.on.embedded.manager.ResourceManager;
/**
* @author Jason Dobies
*/
public class PluginContainerResourceManager implements ResourceManager
{
// ResourceTypes --------------------------------------------
private static final Log LOG = LogFactory.getLog(PluginContainerResourceManager.class);
private static final String DISCOVERY_ERROR = "Error occurred during discovery";
private static final String NO_SERVERS_FOUND = "Service cannot be created since no servers are found in the platform";
private static final String CANNOT_CREATE_REQUEST = "Unable to create a request for saving the resource";
private static final String CANNOT_BE_NULL = "Resource cannot be null";
private static final String GET_RESOURCE_ERROR = "Error retrieving configuration for resource: ";
private static final String REMOVE_RESOURCE_ERROR = "Error while deleting service: ";
private static final String CREATE_RESOURCE_ERROR = "Error while creating service of type [";
private static final String UPDATE_RESOURCE_ERROR = "Error while updating service: ";
private static final String INVOKE_OPERATION_ERROR = "Error invoking operation on resource [";
// Public --------------------------------------------
public void discoverResources()
{
LOG.info("Discovering Resources...");
try
{
getInventoryService().executeServerScanImmediately();
getInventoryService().executeServiceScanImmediately();
}
catch (Exception e)
{
LOG.error(DISCOVERY_ERROR, e);
throw new RuntimeException(DISCOVERY_ERROR, e);
}
Resource platform = getInventoryService().getPlatform();
if (platform.getChildResources().isEmpty())
{
LOG.error(NO_SERVERS_FOUND);
return;
}
}
public void discoverServicesAsync()
{
try
{
getInventoryService().executeServiceScanDeferred();
}
catch (Exception e)
{
LOG.error(DISCOVERY_ERROR, e);
throw new RuntimeException(DISCOVERY_ERROR, e);
}
}
public void discoverServicesSync()
{
try
{
getInventoryService().executeServiceScanImmediately();
}
catch (Exception e)
{
LOG.error(DISCOVERY_ERROR, e);
throw new RuntimeException(DISCOVERY_ERROR, e);
}
}
// ResourceManager Implementation --------------------------------------------
// @TODO need to check this. In tests this causes NPE, something might have changed and we might need a different way to do this
public ResourceType getResourceType(String resourceTypeName)
{
ResourceType resourceType = null;
Set<ResourceType> allTypes = getPluginContainer().getPluginManager().getMetadataManager().getAllTypes();
for (ResourceType type : allTypes)
{
if (type.getName().equals(resourceTypeName))
{
resourceType = type;
}
}
return resourceType;
}
public Set<ResourceType> getAllResourceTypes()
{
return getPluginContainer().getPluginManager().getMetadataManager().getAllTypes();
}
@NotNull
public Set<Resource> getResources(ResourceType resourceType, Resource rootResource)
{
// Use a TreeSet to ensure the Set is sorted via Resource.compareTo() (i.e. by name).
Set<Resource> childResources = new TreeSet<Resource>();
// If we're looking for a platform, let's return it.
if (resourceType.getCategory() == ResourceCategory.PLATFORM)
{
childResources.add(getInventoryService().getPlatform());
}
else
{
fillWithChildResources(childResources, rootResource, resourceType);
}
return childResources;
}
private void fillWithChildResources(Set<Resource> matchingResources, Resource root, ResourceType type)
{
for (Resource childResource : root.getChildResources())
{
if (childResource.getResourceType().equals(type))
{
matchingResources.add(childResource);
}
// This could probably go in an else clause, but it should be fine being called all the time.
fillWithChildResources(matchingResources, childResource, type); // recurse
}
}
public Resource getResource(Integer id)
{
Resource result = null;
if (id != null)
{
result = getResource(getInventoryService().getPlatform(), id);
}
return result;
}
public Resource getPlatform()
{
return getInventoryService().getPlatform();
}
private Resource getResource(@NotNull Resource resource, @NotNull Integer id)
{
Resource result = null;
// first of all check the passed in resource itself
if (resource.getId() == id)
{
result = resource;
}
else
{
for (Resource childResource : resource.getChildResources())
{
result = getResource(childResource, id);
if (result != null)
{
break;
}
if (childResource.getId() == id)
{
result = childResource;
break;
}
}
}
return result;
}
public Configuration getResourceConfiguration(Resource resource)
{
if (resource == null)
{
throw new IllegalArgumentException(CANNOT_BE_NULL);
}
Configuration configuration;
try
{
configuration = getConfigService().loadResourceConfiguration(resource.getId());
}
catch (PluginContainerException e)
{
LOG.error(GET_RESOURCE_ERROR + resource, e);
throw new RuntimeException(e);
}
ConfigurationUtility.normalizeConfiguration(configuration,
resource.getResourceType().getResourceConfigurationDefinition());
return configuration;
}
public DeleteResourceResponse removeResource(Resource resource)
{
DeleteResourceResponse response;
try
{
DeleteResourceRequest deleteRequest = new DeleteResourceRequest(1, resource.getId());
response = getResourceFactoryService().executeDeleteResourceImmediately(deleteRequest);
if (response.getStatus() == DeleteResourceStatus.SUCCESS)
{
discoverServicesSync();
}
}
catch (PluginContainerException e)
{
LOG.error(REMOVE_RESOURCE_ERROR + resource, e);
throw new RuntimeException(e);
}
return response;
}
public CreateResourceResponse createResource(String resourceName, ResourceType resourceType, Resource parentResource, Configuration pluginConfiguration, Configuration resourceConfiguration)
{
CreateResourceResponse response;
CreateResourceRequest request = new CreateResourceRequest(1, parentResource.getId(), resourceName, resourceType.getName(), resourceType.getPlugin(), pluginConfiguration, resourceConfiguration);
response = createResource(resourceType, parentResource, request);
return response;
}
public CreateResourceResponse createResource(String resourceName, ResourceType resourceType, Resource parentResource, Configuration pluginConfiguration, ResourcePackageDetails packageDetails)
{
CreateResourceResponse response;
CreateResourceRequest request = new CreateResourceRequest(1, parentResource.getId(), resourceName, resourceType.getName(), resourceType.getPlugin(), pluginConfiguration, packageDetails);
response = createResource(resourceType, parentResource, request);
return response;
}
// tries to create a resource using the specified CreateResourceRequest
// if successful it will try to refresh the inventory by calling discoverServicesSync
private CreateResourceResponse createResource(ResourceType resourceType, Resource parentResource, CreateResourceRequest request)
{
CreateResourceResponse response;
try
{
response = getResourceFactoryService().executeCreateResourceImmediately(request);
if (response.getStatus() == CreateResourceStatus.SUCCESS)
{
discoverServicesSync();
}
}
catch (PluginContainerException e)
{
LOG.error(CREATE_RESOURCE_ERROR + resourceType, e);
throw new RuntimeException(e);
}
catch (Exception e)
{
LOG.error(CANNOT_CREATE_REQUEST + e);
throw new RuntimeException(CANNOT_CREATE_REQUEST, e);
}
return response;
}
public ConfigurationUpdateResponse updateResource(Resource resource, Configuration configuration)
{
ConfigurationUpdateResponse response;
try
{
ConfigurationUpdateRequest request = new ConfigurationUpdateRequest(0, configuration, resource.getId());
response = getConfigService().executeUpdateResourceConfigurationImmediately(request);
if (response.getStatus() == ConfigurationUpdateStatus.SUCCESS)
{
// As ccrouch recalls, we do a service scan to pickup any change to the updated Resource's name.
discoverServicesSync();
Events.instance().raiseEvent(ResourceManager.RESOURCE_UPDATED_EVENT, resource);
}
}
catch (PluginContainerException e)
{
LOG.error(UPDATE_RESOURCE_ERROR);
throw new RuntimeException(UPDATE_RESOURCE_ERROR, e);
}
return response;
}
public Availability getAvailability(Resource resource)
{
return getInventoryService().getCurrentAvailability(resource);
}
@NotNull
public List<OperationDefinition> getOperationsForResource(Resource resource)
{
List<OperationDefinition> operationDefinitions = new ArrayList();
if (resource != null)
{
ResourceType resourceType = resource.getResourceType();
operationDefinitions.addAll(resourceType.getOperationDefinitions());
}
return operationDefinitions;
}
public void invokeOperation(Resource resource, OperationDefinition operation, Configuration parameters, String jobId)
{
try
{
getOperationService().invokeOperation(jobId, resource.getId(), operation.getName(), parameters);
}
catch (PluginContainerException e)
{
LOG.error(INVOKE_OPERATION_ERROR + resource, e);
throw new RuntimeException(e);
}
}
protected ConfigurationAgentService getConfigService()
{
return getPluginContainer().getConfigurationAgentService();
}
protected DiscoveryAgentService getInventoryService()
{
return getPluginContainer().getDiscoveryAgentService();
}
protected OperationAgentService getOperationService()
{
return getPluginContainer().getOperationAgentService();
}
protected ResourceFactoryAgentService getResourceFactoryService()
{
return getPluginContainer().getResourceFactoryAgentService();
}
protected PluginContainer getPluginContainer()
{
return PluginContainer.getInstance();
}
}