/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.hyperic.plugin.vrealize.automation; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.InetAddress; import java.net.URI; import java.net.URL; import java.net.URLConnection; import java.net.UnknownHostException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Properties; import java.util.Scanner; import java.util.regex.Pattern; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.map.ObjectMapper; import org.hyperic.hq.product.PluginException; import org.hyperic.hq.product.ServerResource; import org.hyperic.plugin.vrealize.automation.model.cluster.config.ClusterConfig; import org.hyperic.plugin.vrealize.automation.model.components.ComponentsRegistry; import org.hyperic.plugin.vrealize.automation.model.components.Content; import org.hyperic.sigar.win32.RegistryKey; import org.hyperic.sigar.win32.Win32Exception; import org.hyperic.util.exec.Execute; import org.hyperic.util.exec.ExecuteWatchdog; import org.hyperic.util.exec.PumpStreamHandler; import org.w3c.dom.Document; import com.vmware.hyperic.model.relations.ObjectFactory; import com.vmware.hyperic.model.relations.RelationType; import com.vmware.hyperic.model.relations.Resource; /** * @author glaullon */ public class VRAUtils { private static final Log log = LogFactory.getLog(VRAUtils.class); private static final HashMap<String, Properties> propertiesMap = new HashMap<String, Properties>(); private static final String IPv4_ADDRESS_PATTERN = "[0-9]+.[0-9]+.[0-9]+.[0-9]+"; private static final String IPv6_ADDRESS_PATTERN = "([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)"; private static final String VERSION_PATTERN = "[0-9].[0-9,.-]+"; private static final int DEFAULT_TIMEOUT = 60; private static String localFqdn; public static VraVersion getVraVersion(boolean isWindows) { VraVersion version; if (isWindows) { version = getVraVersionWindows(); } else { version = getVraVersionLinux(); } return version; } public static VraVersion getVraVersionLinux() { String versionString = "6.1"; String[] findVersionCommand = new String[] { "rpm", "-qa" }; String allRunningPrograms = new String(); try { allRunningPrograms = runCommandLine(findVersionCommand); } catch (PluginException e) { e.printStackTrace(); } String[] runningPrograms = allRunningPrograms.split("\n"); Pattern p = Pattern.compile("vcac-[0-9]+"); for (String program : runningPrograms) { if (p.matcher(program).find()) { versionString = program; break; } } return extractVersionFromString(versionString); } public static VraVersion getVraVersionWindows() { try { RegistryKey vCACProgram = RegistryKey.LocalMachine.openSubKey( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{A8DF9A88-CC1D-4FAF-B1DE-B09ABAA13540}"); log.debug("[findVraVersionInWindows] We have the registry of: " + vCACProgram.getStringValue( "DisplayName")); String programVersion = vCACProgram.getStringValue("DisplayVersion"); programVersion = programVersion.trim(); log.debug("[findVraVersionInWindows] The pogram version is: " + programVersion); return extractVersionFromString(programVersion); } catch (Win32Exception ex) { log.debug("[getServerResources] Error accessing to windows registry to get version. ", ex); } return null; } public static String getVcoConfFile(boolean isWindows) { if (isWindows) { String vcoInstallPathWindows = getVcoInstallPathWindows(); File vmoProperties = new File(vcoInstallPathWindows, "\\app-server\\conf\\vmo.properties"); try { return vmoProperties.getCanonicalPath(); } catch (IOException e) { log.debug(String.format("Failed to read: '%s',", vcoInstallPathWindows + "\\app-server\\conf\\vmo.properties"), e); return null; } } return "/etc/vco/app-server/vmo.properties"; } public static String getVcoInstallPathWindows() { try { RegistryKey vCACProgram = RegistryKey.LocalMachine.openSubKey( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\vCenter Orchestrator"); String programVersion = vCACProgram.getStringValue("InstallLocation"); log.debug(String.format("[getVcoInstallPathWindows] installPath: '%s'", programVersion)); return programVersion.trim(); } catch (Win32Exception ex) { log.debug("[getVcoInstallPathWindows] Error accessing to windows registry to get version. ", ex); return null; } } private static VraVersion extractVersionFromString(String programVersion) { // TODO: change the implementation to use REGEX for splitting version onto tokens String versionPrefix = "vcac-"; if (programVersion.startsWith(versionPrefix)) { programVersion = programVersion.substring(versionPrefix.length()); } if (Pattern.matches(VERSION_PATTERN, programVersion)) { programVersion = programVersion.substring(0, 3); } VraVersion vraVersion = new VraVersion(6, 1); if (StringUtils.isNotBlank(programVersion)) { String[] tokens = programVersion.split("\\."); if (tokens.length >= 2) { vraVersion = new VraVersion(Integer.valueOf(tokens[0]).intValue(), Integer.valueOf(tokens[1]).intValue()); } } log.debug("[extractVersionFromString] The extracted log version is: '" + programVersion + "'"); log.debug("[extractVersionFromString] The extracted log version is: '" + vraVersion + "'"); return vraVersion; } public static String executeXMLQuery( String xmlPath, String configFilePath) { File configFile = new File(configFilePath); return executeXMLQuery(xmlPath, configFile); } public static String executeXMLQuery( String xPath, File xmlFile) { InputStream inputStream; String result = null; try { inputStream = new FileInputStream(xmlFile); result = executeXMLQuery(xPath, inputStream); } catch (FileNotFoundException e) { log.error(String.format("Unable to load configuration file [%s]", xmlFile.getName()), e); } return result; } public static String executeXMLQuery( String xPath, InputStream is) { String res = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = (Document) builder.parse(is); XPathFactory xFactory = XPathFactory.newInstance(); XPath xpath = xFactory.newXPath(); res = xpath.evaluate(xPath, doc); } catch (Exception ex) { log.error("[executeXMLQuery] " + ex, ex); } return res; } protected static Properties configFile(String filePath) { if (propertiesMap.containsKey(filePath)) return propertiesMap.get(filePath); Properties properties = new Properties(); // TODO: German, to implement same for Windows OS File configFile = new File(filePath); if (configFile.exists()) { FileInputStream in = null; try { in = new FileInputStream(configFile); properties.load(in); propertiesMap.put(filePath, properties); } catch (FileNotFoundException ex) { log.debug(ex, ex); } catch (IOException ex) { log.debug(ex, ex); } finally { if (in != null) { try { in.close(); } catch (IOException ex) { log.debug(ex, ex); } } } } return properties; } protected static String marshallResource(Resource model) { ObjectFactory factory = new ObjectFactory(); ByteArrayOutputStream fos = new ByteArrayOutputStream(); factory.saveModel(model, fos); log.debug("[marshallResource] fos=" + fos.toString()); return fos.toString(); } public static void setModelProperty( ServerResource server, String model) { server.getProductConfig().setValue(VraConstants.PROP_EXTENDED_REL_MODEL, new String(Base64.encodeBase64(model.getBytes()))); server.setProductConfig(server.getProductConfig()); } public static String getFqdn( String containsAddress, AddressExtractor addressExtractor) { return getFqdn(addressExtractor.extractAddress(containsAddress)); } public static String getFqdn(String address) { String parsedAddress = parseAddress(address); if (StringUtils.isBlank(parsedAddress) || StringUtils.containsIgnoreCase(parsedAddress, "localhost")) { if (StringUtils.isNotBlank(getLocalFqdn())) { return getLocalFqdn(); } } return parsedAddress; } private static String parseAddress(String address) { if (StringUtils.isBlank(address)) { return StringUtils.EMPTY; } address = address.replace("\\:", ":"); String fqdnOrIpFromURI = getFQDNFromURI(address); if (StringUtils.isNotBlank(fqdnOrIpFromURI)) { String fqdn = getFqdnFromIp(fqdnOrIpFromURI); if (StringUtils.isNotBlank(fqdn)) { return fqdn; } return fqdnOrIpFromURI; } address = getAddressWithoutPort(address); String fqdnFromIp = getFqdnFromIp(address); if (StringUtils.isNotBlank(fqdnFromIp)) { return fqdnFromIp; } return address; } private static String getAddressWithoutPort(String address) { int index = address.split(":").length; if (index > 6) { address = address.substring(0, address.lastIndexOf(":")); } else if (index == 2) { address = address.split(":")[0]; } return address; } private static String getFqdnFromIp(String address) { InetAddress addr = null; try { if (Pattern.matches(IPv4_ADDRESS_PATTERN, address) || Pattern.matches(IPv6_ADDRESS_PATTERN, address)) { addr = InetAddress.getByName(address); return addr.getCanonicalHostName(); } } catch (Exception e) { } return null; } private static String getFQDNFromURI(String address) { try { URI uri = new URI(address); String fqdn = uri.getHost(); return fqdn; } catch (Exception e) { } return null; } public static Collection<String> getDnsNames(final String url) { Collection<String> dnsNames = null; try { DnsNameExtractor dnsExtractor = new DnsNameExtractor(); dnsNames = dnsExtractor.getDnsNames(url); } catch (Exception e) { log.error(e.getMessage(), e); dnsNames = new HashSet<String>(); } return dnsNames; } public static String getWGet(String path) { log.debug("[getWGet] Accessing the path: " + path); String retValue = null; try { TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( X509Certificate[] certs, String authType) { } public void checkServerTrusted( X509Certificate[] certs, String authType) { } } }; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); // Create all-trusting host name verifier HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify( String hostname, SSLSession session) { return true; } }; // Install the all-trusting host verifier HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); URL url = new URL(path); URLConnection con; try { con = url.openConnection(); } catch (Exception e) { log.debug("[getWGet] Couldnt connect to vRa API"); return ""; } Reader reader = new InputStreamReader(con.getInputStream()); while (true) { int ch = reader.read(); if (ch == -1) { break; } retValue += (char) ch; } } catch (Exception e) { log.error(e.getMessage(), e); } log.debug("[getWGet] The answer from the wget command is: " + retValue); return retValue; } public static void setLocalFqdn(String localFqdn) { VRAUtils.localFqdn = localFqdn; } public static String getLocalFqdn() { if (StringUtils.isBlank(localFqdn)) { try { localFqdn = InetAddress.getLocalHost().getCanonicalHostName(); } catch (Exception e) { log.warn("Failed to get local FQDN", e); } } return localFqdn; } public static String readFile(String filePath) { Scanner scanner = null; StringBuilder result = new StringBuilder(); try { result = new StringBuilder(); scanner = new Scanner(new FileInputStream(filePath)); while (scanner.hasNextLine()) { result.append(String.format("%s%n", scanner.nextLine())); } } catch (Exception e) { return null; } finally { if (scanner != null) { scanner.close(); } } return (result == null) ? null : result.toString(); } public static RelationType getDataBaseRalationType(String databaseServerFqdn) { if (StringUtils.equalsIgnoreCase(localFqdn, databaseServerFqdn)) { return RelationType.SIBLING; } return RelationType.CHILD; } public static String runCommandLine(String[] command) throws PluginException { return runCommandLine(command, DEFAULT_TIMEOUT); } public static String runCommandLine(String[] command, int timeoutSeconds) throws PluginException { ByteArrayOutputStream output = new ByteArrayOutputStream(); final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(output); ExecuteWatchdog wdog = new ExecuteWatchdog(timeoutSeconds * 1000); Execute exec = new Execute(pumpStreamHandler, wdog); exec.setCommandline(command); log.debug("[runCommand] Running the command: " + exec.getCommandLineString()); try { exec.execute(); } catch (Exception e) { throw new PluginException("Fail to run command: " + e.getMessage(), e); } String out = output.toString().trim(); log.debug("[runCommand] The output is: {starting out}" + out + "'{finishing out}"); log.debug("[runCommand] ExitValue: '" + exec.getExitValue() + "'"); if (exec.getExitValue() != 0) { throw new PluginException(out); } return out; } public static Collection<String> getFqdnFromComponentRegistryJson( String componentsRegistryJson, String serviceName) throws IOException { Collection<String> result = new ArrayList<String>(); if (StringUtils.isNotBlank(componentsRegistryJson)) { if (componentsRegistryJson.startsWith("null{")) { // remove the "null" prefix if present componentsRegistryJson = componentsRegistryJson.substring("null".length()); } log.debug("[getFqdnFromComponentRegistryJson] Content: \n\n" + componentsRegistryJson); ObjectMapper mapper = new ObjectMapper(); ComponentsRegistry compReg = mapper.readValue(componentsRegistryJson, ComponentsRegistry.class); if (compReg != null) { for (Content c : compReg.getContent()) { if (c.getServiceName().equalsIgnoreCase(serviceName)) { result.add(getFqdn(c.getStatusEndPointUrl())); } } } } else { log.warn("[getFqdnFromComponentRegistryJson] JSON is EMPTY or NULL"); } return result; } public static Collection<String> getNodeHostUrlsFromClusterConfigJson(String clusterConfigJson, String nodeType) throws IOException { ObjectMapper mapper = new ObjectMapper(); ClusterConfig[] clusterConfig = mapper.readValue(clusterConfigJson, ClusterConfig[].class); Collection<String> result = new ArrayList<String>(); for (int i = 0; i < clusterConfig.length; i++) { ClusterConfig config = clusterConfig[i]; if (config.getNodeType().equalsIgnoreCase(nodeType)) { result.add(config.getNodeHost()); } } return result; } /** * Compare two given FQDNs * * @param localFqdn * @param remoteFqdn * @return true if given FQDNs are equivalent */ public static boolean areFqdnsEquivalent(final String localFqdn, final String remoteFqdn) { boolean result = false; if (StringUtils.isNotBlank(localFqdn) && StringUtils.isNotBlank(remoteFqdn)) { if (localFqdn.equalsIgnoreCase(remoteFqdn)) { result = true; } else { try { String localHostName = InetAddress.getByName(localFqdn).getHostName(); String remoteHostName = InetAddress.getByName(remoteFqdn).getHostName(); if (localHostName.equalsIgnoreCase(remoteHostName)) { result = true; } } catch (UnknownHostException e) { log.error(String.format( "Unable to resolve host name for one of the given addresses.\nLocal: %s\nRemote: %s", localFqdn, remoteFqdn), e); } } } return result; } public static String getJsonFromVcacConfigListCommand() { String resultJson = ""; final String[] commandToGetJsonWithIaas = new String[] { "/usr/sbin/vcac-config", "-v", "cluster-config", "-list" }; String includingJsonWithIaas = new String(); try { includingJsonWithIaas = VRAUtils.runCommandLine(commandToGetJsonWithIaas); } catch (PluginException ex) { log.error("[getIaaSFqdns] " + ex, ex); } if (StringUtils.isNotBlank(includingJsonWithIaas)){ /* * The string is of the following format: * * ---BEGIN--- * [{"nodeId":"cafe.node.457745596.6313"...."}] * ---END--- * */ String [] tokens = includingJsonWithIaas.split("\n"); if (tokens.length >= 1){ resultJson = tokens[1]; } } return resultJson; } static class VraVersion { int major; int minor; int buildNumber; public VraVersion( int major, int minor, int buildNumber) { super(); this.major = major; this.minor = minor; this.buildNumber = buildNumber; } public VraVersion( int major, int minor) { this(major, minor, 0); } public int getMajor() { return major; } public void setMajor(int major) { this.major = major; } public int getMinor() { return minor; } public void setMinor(int minor) { this.minor = minor; } public int getBuildNumber() { return buildNumber; } public void setBuildNumber(int buildNumber) { this.buildNumber = buildNumber; } @Override public String toString() { return "VraVersion [major=" + major + ", minor=" + minor + ", buildNumber=" + buildNumber + "]"; } } }