blob: 3bb6b2cecbd77f7465064e6615233b080af068a0 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ambari.server.api.services;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.state.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ServiceInfo responsible getting information about cluster.
*/
@Singleton
public class AmbariMetaInfo {
private List<StackInfo> stacksResult = new ArrayList<StackInfo>();
private File stackRoot;
private final static Logger LOG = LoggerFactory
.getLogger(AmbariMetaInfo.class);
private static final String SERVICES_FOLDER_NAME = "services";
private static final String SERVICE_METAINFO_FILE_NAME = "metainfo.xml";
private static final String SERVICE_CONFIG_FOLDER_NAME = "configuration";
private static final String SERVICE_CONFIG_FILE_NAME_POSTFIX = "-site.xml";
private static final String REPOSITORY_FILE_NAME = "repoinfo.xml";
private static final String REPOSITORY_FOLDER_NAME = "repos";
private static final String REPOSITORY_XML_MAIN_BLOCK_NAME = "os";
private static final String REPOSITORY_XML_ATTRIBUTE_OS_TYPE = "type";
private static final String REPOSITORY_XML_REPO_BLOCK_NAME = "repo";
private static final String REPOSITORY_XML_PROPERTY_BASEURL = "baseurl";
private static final String REPOSITORY_XML_PROPERTY_REPOID = "repoid";
private static final String REPOSITORY_XML_PROPERTY_REPONAME = "reponame";
private static final String REPOSITORY_XML_PROPERTY_MIRRORSLIST = "mirrorslist";
private static final String METAINFO_XML_MAIN_BLOCK_NAME = "metainfo";
private static final String METAINFO_XML_PROPERTY_VERSION = "version";
private static final String METAINFO_XML_PROPERTY_USER = "user";
private static final String METAINFO_XML_PROPERTY_COMMENT = "comment";
private static final String METAINFO_XML_PROPERTY_COMPONENT_MAIN = "component";
private static final String METAINFO_XML_PROPERTY_COMPONENT_NAME = "name";
private static final String METAINFO_XML_PROPERTY_COMPONENT_CATEGORY = "category";
private static final String PROPERTY_XML_MAIN_BLOCK_NAME = "property";
private static final String PROPERTY_XML_PROPERTY_NAME = "name";
private static final String PROPERTY_XML_PROPERTY_VALUE = "value";
private static final String PROPERTY_XML_PROPERTY_DESCRIPTION = "description";
private static final FilenameFilter FILENAME_FILTER = new FilenameFilter() {
@Override
public boolean accept(File dir, String s) {
if (s.equals(".svn") || s.equals(".git"))
return false;
return true;
}
};
/**
* Ambari Meta Info Object
*
* @param conf Configuration API to be used.
* @throws Exception
*/
@Inject
public AmbariMetaInfo(Configuration conf) throws Exception {
String stackPath = conf.getMetadataPath();
this.stackRoot = new File(stackPath);
}
@Inject
public AmbariMetaInfo(File stackRoot) throws Exception {
this.stackRoot = stackRoot;
}
/**
* Initialize the Ambari Meta Info
*
* @throws Exception throws exception if not able to parse the Meta data.
*/
public void init() throws Exception {
getConfigurationInformation(stackRoot);
}
/**
* Get component category
*
* @param stackName
* @param version
* @param serviceName
* @param componentName
* @return component component Info
*/
public ComponentInfo getComponentCategory(String stackName, String version,
String serviceName, String componentName) {
ComponentInfo component = null;
List<ComponentInfo> components = getComponentsByService(stackName, version,
serviceName);
if (components != null)
for (ComponentInfo cmp : components) {
if (cmp.getName().equals(componentName)) {
component = cmp;
break;
}
}
return component;
}
/**
* Get components by service
*
* @param stackName
* @param version
* @param serviceName
* @return
*/
public List<ComponentInfo> getComponentsByService(String stackName,
String version, String serviceName) {
List<ComponentInfo> componentsResult = null;
ServiceInfo service = getServiceInfo(stackName, version, serviceName);
if (service != null)
componentsResult = service.getComponents();
return componentsResult;
}
public Map<String, List<RepositoryInfo>> getRepository(String stackName,
String version) {
Map<String, List<RepositoryInfo>> reposResult = null;
StackInfo stack = getStackInfo(stackName, version);
if (stack != null) {
List<RepositoryInfo> repository = stack.getRepositories();
reposResult = new HashMap<String, List<RepositoryInfo>>();
for (RepositoryInfo repo : repository) {
if (!reposResult.containsKey(repo.getOsType())) {
reposResult.put(repo.getOsType(),
new ArrayList<RepositoryInfo>());
}
reposResult.get(repo.getOsType()).add(repo);
}
}
return reposResult;
}
/*
* function for given a stack name and version, is it a supported stack
*/
public boolean isSupportedStack(String stackName, String version) {
boolean exist = false;
StackInfo stack = getStackInfo(stackName, version);
if (stack == null)
exist = true;
return exist;
}
/*
* support isValidService(), isValidComponent for a given stack/version
*/
public boolean isValidService(String stackName, String version,
String serviceName) {
ServiceInfo service = getServiceInfo(stackName, version, serviceName);
return (service != null);
}
/*
* support isValidService(), isValidComponent for a given stack/version
*/
public boolean isValidServiceComponent(String stackName, String version,
String serviceName, String componentName) {
ServiceInfo service = getServiceInfo(stackName, version, serviceName);
if (service == null) {
return false;
}
for (ComponentInfo compInfo : service.getComponents()) {
if (compInfo.getName().equals(componentName)) {
return true;
}
}
return false;
}
/**
* Get the name of a service given the component name.
*
* @param stackName the stack name
* @param version the stack version
* @param componentName the component name
* @return the service name
*/
public String getComponentToService(String stackName, String version,
String componentName) {
if (LOG.isDebugEnabled()) {
LOG.debug("Looking for service for component"
+ ", stackName=" + stackName
+ ", stackVersion=" + version
+ ", componentName=" + componentName);
}
Map<String, ServiceInfo> services = getServices(stackName, version);
String retService = null;
if (services == null
|| services.isEmpty()) {
return retService;
}
boolean found = false;
for (Map.Entry<String, ServiceInfo> entry : services.entrySet()) {
for (ComponentInfo compInfo : entry.getValue().getComponents()) {
if (compInfo.getName().equals(componentName)) {
retService = entry.getKey();
found = true;
break;
}
}
if (found)
break;
}
return retService;
}
/**
* Get the service configs supported for a service in a particular stack
*
* @param stackName the stack name
* @param version the version of the stack
* @param serviceName the name of the service in the stack
* @return the config knobs supported for the service
*/
public Map<String, Map<String, String>> getSupportedConfigs(String stackName,
String version, String serviceName) {
Map<String, Map<String, String>> propertiesResult = new HashMap<String, Map<String, String>>();
ServiceInfo service = getServiceInfo(stackName, version, serviceName);
if (service != null)
if (serviceName.equals(service.getName())) {
List<PropertyInfo> properties = service.getProperties();
if (properties != null)
for (PropertyInfo propertyInfo : properties) {
Map<String, String> fileProperties = propertiesResult
.get(propertyInfo.getFilename());
if (fileProperties == null) {
fileProperties = new HashMap<String, String>();
fileProperties.put(propertyInfo.getName(),
propertyInfo.getValue());
propertiesResult.put(propertyInfo.getFilename(), fileProperties);
} else {
fileProperties.put(propertyInfo.getName(),
propertyInfo.getValue());
}
}
}
return propertiesResult;
}
/**
* Given a stack name and version return all the services with info
*
* @param stackName the stack name
* @param version the version of the stack
* @return the information of abt varios services that are supported in the
* stack
*/
public Map<String, ServiceInfo> getServices(String stackName, String version) {
Map<String, ServiceInfo> servicesInfoResult = new HashMap<String, ServiceInfo>();
List<ServiceInfo> services = null;
StackInfo stack = getStackInfo(stackName, version);
if (stack == null)
return null;
services = stack.getServices();
if (services != null)
for (ServiceInfo service : services) {
servicesInfoResult.put(service.getName(), service);
}
return servicesInfoResult;
}
public ServiceInfo getServiceInfo(String stackName, String version,
String serviceName) {
ServiceInfo serviceInfoResult = null;
List<ServiceInfo> services = null;
StackInfo stack = getStackInfo(stackName, version);
if (stack == null)
return null;
services = stack.getServices();
if (services != null)
for (ServiceInfo service : services) {
if (serviceName.equals(service.getName())) {
serviceInfoResult = service;
break;
}
}
return serviceInfoResult;
}
public List<ServiceInfo> getSupportedServices(String stackName, String version) {
List<ServiceInfo> servicesResulr = null;
StackInfo stack = getStackInfo(stackName, version);
if (stack != null)
servicesResulr = stack.getServices();
return servicesResulr;
}
public List<StackInfo> getSupportedStacks() {
return stacksResult;
}
public StackInfo getStackInfo(String stackName, String version) {
StackInfo stackInfoResult = null;
for (StackInfo stack : stacksResult) {
if (stackName.equals(stack.getName())
&& version.equals(stack.getVersion())) {
stackInfoResult = stack;
break;
}
}
return stackInfoResult;
}
private void getConfigurationInformation(File stackRoot) throws Exception {
if (LOG.isDebugEnabled()) {
LOG.debug("Loading stack information"
+ ", stackRoot=" + stackRoot.getAbsolutePath());
}
if (!stackRoot.isDirectory() && !stackRoot.exists())
throw new IOException("" + Configuration.METADETA_DIR_PATH
+ " should be a directory with stack"
+ ", stackRoot=" + stackRoot.getAbsolutePath());
File[] stacks = stackRoot.listFiles(FILENAME_FILTER);
for (File stackFolder : stacks) {
if (stackFolder.isFile())
continue;
File[] concretStacks = stackFolder.listFiles(FILENAME_FILTER);
for (File stack : concretStacks) {
if (stack.isFile())
continue;
StackInfo stackInfo = new StackInfo();
stackInfo.setName(stackFolder.getName());
stackInfo.setVersion(stack.getName());
if (LOG.isDebugEnabled()) {
LOG.debug("Adding new stack to known stacks"
+ ", stackName=" + stackFolder.getName()
+ ", stackVersion=" + stack.getName());
}
stacksResult.add(stackInfo);
// get repository data for current stack of techs
File repositoryFolder = new File(stack.getAbsolutePath()
+ File.separator + REPOSITORY_FOLDER_NAME + File.separator
+ REPOSITORY_FILE_NAME);
if (repositoryFolder.exists()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Adding repositories to stack"
+ ", stackName=" + stackFolder.getName()
+ ", stackVersion=" + stack.getName()
+ ", repoFolder=" + repositoryFolder.getPath());
}
List<RepositoryInfo> repositoryInfoList = getRepository(repositoryFolder);
stackInfo.getRepositories().addAll(repositoryInfoList);
}
// Get services for this stack
File servicesRootFolder = new File(stack.getAbsolutePath()
+ File.separator + SERVICES_FOLDER_NAME);
File[] servicesFolders = servicesRootFolder.listFiles(FILENAME_FILTER);
if (servicesFolders != null) {
for (File serviceFolder : servicesFolders) {
// Get information about service
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setName(serviceFolder.getName());
stackInfo.getServices().add(serviceInfo);
if (LOG.isDebugEnabled()) {
LOG.debug("Adding new service to stack"
+ ", stackName=" + stackFolder.getName()
+ ", stackVersion=" + stack.getName()
+ ", serviceName=" + serviceInfo.getName());
}
// Get metainfo data from metainfo.xml
File metainfoFile = new File(serviceFolder.getAbsolutePath()
+ File.separator + SERVICE_METAINFO_FILE_NAME);
if (metainfoFile.exists()) {
setMetaInfo(metainfoFile, serviceInfo);
}
// Get all properties from all "configs/*-site.xml" files
File serviceConfigFolder = new File(serviceFolder.getAbsolutePath()
+ File.separator + SERVICE_CONFIG_FOLDER_NAME);
File[] configFiles = serviceConfigFolder.listFiles(FILENAME_FILTER);
if (configFiles != null) {
for (File config : configFiles) {
if (config.getName().endsWith(SERVICE_CONFIG_FILE_NAME_POSTFIX)) {
serviceInfo.getProperties().addAll(getProperties(config));
}
}
}
}
}
}
}
}
private List<RepositoryInfo> getRepository(File repositoryFile) throws ParserConfigurationException, IOException, SAXException {
List<RepositoryInfo> repositorysInfo = new ArrayList<RepositoryInfo>();
// try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(repositoryFile);
NodeList osNodes = doc
.getElementsByTagName(REPOSITORY_XML_MAIN_BLOCK_NAME);
for (int index = 0; index < osNodes.getLength(); index++) {
Node osNode = osNodes.item(index);
if (osNode.getNodeType() == Node.ELEMENT_NODE) {
if (!osNode.getNodeName().equals(REPOSITORY_XML_MAIN_BLOCK_NAME)) {
continue;
}
NamedNodeMap attrs = osNode.getAttributes();
Node osAttr = attrs.getNamedItem(REPOSITORY_XML_ATTRIBUTE_OS_TYPE);
if (osAttr == null) {
continue;
}
String osType = osAttr.getNodeValue();
NodeList repoNodes = osNode.getChildNodes();
for (int j = 0; j < repoNodes.getLength(); j++) {
Node repoNode = repoNodes.item(j);
if (repoNode.getNodeType() != Node.ELEMENT_NODE
|| !repoNode.getNodeName().equals(
REPOSITORY_XML_REPO_BLOCK_NAME)) {
continue;
}
Element property = (Element) repoNode;
String repoId = getTagValue(REPOSITORY_XML_PROPERTY_REPOID,
property);
String repoName = getTagValue(REPOSITORY_XML_PROPERTY_REPONAME,
property);
String baseUrl = getTagValue(
REPOSITORY_XML_PROPERTY_BASEURL, property);
String mirrorsList = getTagValue(
REPOSITORY_XML_PROPERTY_MIRRORSLIST, property);
String[] osTypes = osType.split(",");
for (String os : osTypes) {
RepositoryInfo repositoryInfo = new RepositoryInfo();
repositoryInfo.setOsType(os.trim());
repositoryInfo.setRepoId(repoId);
repositoryInfo.setRepoName(repoName);
repositoryInfo.setBaseUrl(baseUrl);
repositoryInfo.setMirrorsList(mirrorsList);
if (LOG.isDebugEnabled()) {
LOG.debug("Adding repo to stack"
+ ", repoInfo=" + repositoryInfo.toString());
}
repositorysInfo.add(repositoryInfo);
}
}
}
}
// } catch (Exception e) {
// e.printStackTrace();
// }
return repositorysInfo;
}
private void setMetaInfo(File metainfoFile, ServiceInfo serviceInfo) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
Document doc = null;
DocumentBuilder dBuilder = null;
try {
dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(metainfoFile);
} catch (SAXException e) {
LOG.error("Error while parsing metainf.xml", e);
} catch (IOException e) {
LOG.error("Error while open metainf.xml", e);
} catch (ParserConfigurationException e) {
LOG.error("Error while parsing metainf.xml", e);
}
if(doc==null) return;
doc.getDocumentElement().normalize();
NodeList metaInfoNodes = doc
.getElementsByTagName(METAINFO_XML_MAIN_BLOCK_NAME);
if (metaInfoNodes.getLength() > 0) {
Node metaInfoNode = metaInfoNodes.item(0);
if (metaInfoNode.getNodeType() == Node.ELEMENT_NODE) {
Element metaInfoElem = (Element) metaInfoNode;
serviceInfo.setVersion(getTagValue(METAINFO_XML_PROPERTY_VERSION,
metaInfoElem));
serviceInfo.setUser(getTagValue(METAINFO_XML_PROPERTY_USER,
metaInfoElem));
serviceInfo.setComment(getTagValue(METAINFO_XML_PROPERTY_COMMENT,
metaInfoElem));
}
}
NodeList componentInfoNodes = doc
.getElementsByTagName(METAINFO_XML_PROPERTY_COMPONENT_MAIN);
if (componentInfoNodes.getLength() > 0) {
for (int index = 0; index < componentInfoNodes.getLength(); index++) {
Node componentInfoNode = componentInfoNodes.item(index);
if (componentInfoNode.getNodeType() == Node.ELEMENT_NODE) {
Element componentInfoElem = (Element) componentInfoNode;
ComponentInfo componentInfo = new ComponentInfo();
componentInfo.setName(getTagValue(
METAINFO_XML_PROPERTY_COMPONENT_NAME, componentInfoElem));
componentInfo.setCategory(getTagValue(
METAINFO_XML_PROPERTY_COMPONENT_CATEGORY, componentInfoElem));
serviceInfo.getComponents().add(componentInfo);
}
}
}
}
private List<PropertyInfo> getProperties(File propertyFile) {
List<PropertyInfo> resultPropertyList = new ArrayList<PropertyInfo>();
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(propertyFile);
doc.getDocumentElement().normalize();
NodeList propertyNodes = doc
.getElementsByTagName(PROPERTY_XML_MAIN_BLOCK_NAME);
for (int index = 0; index < propertyNodes.getLength(); index++) {
Node node = propertyNodes.item(index);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element property = (Element) node;
PropertyInfo propertyInfo = new PropertyInfo();
propertyInfo
.setName(getTagValue(PROPERTY_XML_PROPERTY_NAME, property));
propertyInfo.setValue(getTagValue(PROPERTY_XML_PROPERTY_VALUE,
property));
propertyInfo.setDescription(getTagValue(
PROPERTY_XML_PROPERTY_DESCRIPTION, property));
propertyInfo.setFilename(propertyFile.getName());
if (propertyInfo.getName() == null || propertyInfo.getValue() == null)
continue;
resultPropertyList.add(propertyInfo);
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return resultPropertyList;
}
private String getTagValue(String sTag, Element rawElement) {
String result = null;
if (rawElement.getElementsByTagName(sTag) != null && rawElement.getElementsByTagName(sTag).getLength() > 0) {
if (rawElement.getElementsByTagName(sTag).item(0) != null) {
NodeList element = rawElement.getElementsByTagName(sTag).item(0).getChildNodes();
if (element != null && element.item(0)!=null) {
Node value = (Node) element.item(0);
result = value.getNodeValue();
}
}
}
return result;
}
public boolean areOsTypesCompatible(String type1, String type2) {
if (type1 == null || type2 == null) {
return false;
}
if (type1.equals(type2)) {
return true;
}
if (type1.equals("redhat5") || type1.equals("centos5")) {
if (type2.equals("centos5")
|| type2.equals("redhat5")) {
return true;
}
} else if (type1.equals("redhat6") || type1.equals("centos6")) {
if (type2.equals("centos6")
|| type2.equals("redhat6")) {
return true;
}
}
return false;
}
}