/* * Copyright (C) 2015 Red Hat, inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ package org.jboss.as.server.operations; import static java.security.AccessController.doPrivileged; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DOMAIN_ORGANIZATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.JVM; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ORGANIZATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PRODUCT_NAME; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.PRODUCT_VERSION; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.ARCH; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.AVAILABLE_PROCESSORS; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.CPU; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.HOSTNAME; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.INSTANCE_ID; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.JAVA_VERSION; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.JVM_HOME; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.JVM_VENDOR; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.JVM_VERSION; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.OS; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.PRODUCT_TYPE; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.PRODUCT_COMMUNITY_IDENTIFIER; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.PRODUCT_HOME; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.PRODUCT_INSTALLATION_DATE; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.PRODUCT_LAST_UPDATE; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.PROJECT_TYPE; import static org.jboss.as.controller.operations.global.GlobalInstallationReportHandler.STANDALONE_DOMAIN_IDENTIFIER; import java.io.File; import java.io.IOException; import java.io.Reader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Properties; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.OperationStepHandler; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.ProcessType; import org.jboss.as.controller.client.helpers.Operations; import org.jboss.as.controller.interfaces.InetAddressUtil; import org.jboss.as.controller.operations.common.ProcessEnvironment; import org.jboss.as.controller.operations.global.GlobalInstallationReportHandler; import org.jboss.as.version.ProductConfig; import org.jboss.dmr.ModelNode; import org.wildfly.common.cpu.ProcessorInfo; import org.wildfly.security.manager.action.ReadEnvironmentPropertyAction; import org.wildfly.security.manager.action.ReadPropertyAction; /** * Base class to build a report of the current instance installation. * * @author <a href="mailto:ehugonne@redhat.com">Emmanuel Hugonnet</a> (c) 2015 Red Hat, inc. */ public abstract class AbstractInstallationReporter implements OperationStepHandler { protected static final String OPERATION_NAME = GlobalInstallationReportHandler.SUB_OPERATION_NAME; /** * Create a ModelNode representing the operating system the instance is running on. * * @return a ModelNode representing the operating system the instance is running on. * @throws OperationFailedException */ private ModelNode createOSNode() throws OperationFailedException { String osName = getProperty("os.name"); final ModelNode os = new ModelNode(); if (osName != null && osName.toLowerCase().contains("linux")) { try { os.set(GnuLinuxDistribution.discover()); } catch (IOException ex) { throw new OperationFailedException(ex); } } else { os.set(osName); } return os; } /** * Create a ModelNode representing the JVM the instance is running on. * * @return a ModelNode representing the JVM the instance is running on. * @throws OperationFailedException */ private ModelNode createJVMNode() throws OperationFailedException { ModelNode jvm = new ModelNode().setEmptyObject(); jvm.get(NAME).set(getProperty("java.vm.name")); jvm.get(JAVA_VERSION).set(getProperty("java.vm.specification.version")); jvm.get(JVM_VERSION).set(getProperty("java.version")); jvm.get(JVM_VENDOR).set(getProperty("java.vm.vendor")); jvm.get(JVM_HOME).set(getProperty("java.home")); return jvm; } /** * Create a ModelNode representing the CPU the instance is running on. * * @return a ModelNode representing the CPU the instance is running on. * @throws OperationFailedException */ private ModelNode createCPUNode() throws OperationFailedException { ModelNode cpu = new ModelNode().setEmptyObject(); cpu.get(ARCH).set(getProperty("os.arch")); cpu.get(AVAILABLE_PROCESSORS).set(ProcessorInfo.availableProcessors()); return cpu; } /** * Create a ModelNode representing the instance product and the plateform it is running on. * * @param context the operation context. * @param installation the instance installation configuration. * @return a ModelNode representing the instance product and the plateform it is running on. * @throws OperationFailedException */ protected ModelNode createProductNode(OperationContext context, InstallationConfiguration installation) throws OperationFailedException { assert installation != null; assert installation.getEnvironment() != null; ProcessEnvironment environment = installation.getEnvironment(); ModelNode product = new ModelNode().setEmptyObject(); product.get(HOSTNAME).set(installation.getHostName()); product.get(INSTANCE_ID).set(environment.getInstanceUuid().toString()); PathAddress organizationAddress = PathAddress.EMPTY_ADDRESS; if (context.getProcessType() == ProcessType.HOST_CONTROLLER) { organizationAddress = PathAddress.pathAddress(HOST, environment.getHostControllerName()); } ModelNode root = context.readResourceFromRoot(organizationAddress, false).getModel(); if (!root.hasDefined(ORGANIZATION) && context.getProcessType() == ProcessType.HOST_CONTROLLER) { root = context.readResourceFromRoot(PathAddress.EMPTY_ADDRESS, false).getModel(); } if (root.hasDefined(ORGANIZATION)) { product.get(ORGANIZATION).set(root.get(ORGANIZATION).asString()); } else if (root.hasDefined(DOMAIN_ORGANIZATION)) { product.get(ORGANIZATION).set(root.get(DOMAIN_ORGANIZATION).asString()); } if (installation.getConfig() != null) { if (installation.getConfig().getProductName() != null) { product.get(PRODUCT_NAME).set(installation.getConfig().getProductName()); } if (installation.getConfig().getProductVersion() != null) { product.get(PRODUCT_VERSION).set(installation.getConfig().getProductVersion()); } if (installation.getConfig().isProduct()) { product.get(PRODUCT_COMMUNITY_IDENTIFIER).set(PRODUCT_TYPE); } else { product.get(PRODUCT_COMMUNITY_IDENTIFIER).set(PROJECT_TYPE); } } if (context.getProcessType() != ProcessType.SELF_CONTAINED) { String home = installation.getInstallationDir(); if (home != null && !home.isEmpty()) { product.get(PRODUCT_HOME).set(home); String installationDate = installation.getInstallationDate(); if (installationDate != null && !installationDate.isEmpty()) { product.get(PRODUCT_INSTALLATION_DATE).set(installationDate); } } } String updateDate = installation.getLastUpdateDate(); if (updateDate != null && !updateDate.isEmpty()) { product.get(PRODUCT_LAST_UPDATE).set(updateDate); } product.get(STANDALONE_DOMAIN_IDENTIFIER).set(context.getProcessType().name()); product.get(OS).set(createOSNode()); product.get(CPU).set(createCPUNode()); product.get(JVM).set(createJVMNode()); return product; } /** * Get a System property by its name. * * @param name the name of the wanted System property. * @return the System property value - null if it is not defined. */ private String getProperty(String name) { return System.getSecurityManager() == null ? System.getProperty(name) : doPrivileged(new ReadPropertyAction(name)); } /** * Enum to detect what is the current GnuLinux Distribution used. */ private static enum GnuLinuxDistribution { ARCH("Arch", "/etc/arch-release"), CENTOS("CentOS", "/etc/redhat-release"), CENTOS_ALTERNATIVE("CentOS", "/etc/centos-release"), DEBIAN("Debian", "/etc/debian_version"), DEBIAN_ALTERNATIVE("Debian", "/etc/debian_release"), FEDORA("Fedora", "/etc/fedora-release"), GENTOO("Gentoo", "/etc/gentoo-release"), YELLOWDOG("YellowDog", "/etc/yellowdog-release"), KNOPPIX("Knoppix", "knoppix_version"), MAGEIA("Mageia", "/etc/mageia-release"), MANDRAKE("Mandrake", "/etc/mandrake-release"), MANDRIVA("Mandriva", "/etc/mandriva-release"), MANDRIVA_ALTERNATIVE("Mandriva", "/etc/version"), MINT("LinuxMint", "/etc/lsb-release"), PLD("PLD", "/etc/pld-release"), REDHAT("Red Hat", "/etc/redhat-release"), SLACKWARE("Slackware", "/etc/slackware-version"), SLACKWARE_ALTERNATIVE("Slackware", "/etc/slackware-release"), SUSE("SUSE", "/etc/SuSE-release"), OPEN_SUSE("openSUSE", "/etc/os-release"), SUSE_ALTERNATIVE("SUSE", "/etc/os-release"), UBUNTU("Ubuntu", "/etc/lsb-release"), PUPPY("Puppy", "/etc/puppyversion"), DEFAULT("Linux", "/etc/os-release"); private static final GnuLinuxDistribution[] ALL = new GnuLinuxDistribution[]{ CENTOS, CENTOS_ALTERNATIVE, MINT, UBUNTU, DEBIAN, FEDORA, GENTOO, KNOPPIX, MANDRAKE, MANDRIVA, PLD, REDHAT, SLACKWARE, SLACKWARE_ALTERNATIVE, SUSE, OPEN_SUSE, SUSE_ALTERNATIVE, YELLOWDOG, ARCH, DEBIAN_ALTERNATIVE, DEFAULT }; private final String distributionName; private final Path releasePath; private GnuLinuxDistribution(String distributionName, String releasePath) { this.releasePath = new File(releasePath).toPath(); this.distributionName = distributionName; } /** * Discover what is the underlying Gnu/Linux distribution. * * @return the distribution description (name and version) of the the underlying Gnu/Linux distribution. * @throws IOException */ public static final String discover() throws IOException { for (GnuLinuxDistribution distribution : ALL) { if (Files.exists(distribution.releasePath)) { Properties lines = new Properties(); try (final Reader reader = Files.newBufferedReader(distribution.releasePath, StandardCharsets.UTF_8)) { lines.load(reader); String name = lines.getProperty("DISTRIB_DESCRIPTION", lines.getProperty("PRETTY_NAME")); if (name != null && !name.isEmpty()) { return name.replace('\"', ' ').trim(); } } } } return DEFAULT.distributionName; } } protected static final class InstallationConfiguration { private final ProcessEnvironment environment; private final ProductConfig config; private final ModelNode patchingInfo; private final Path installationDir; public InstallationConfiguration(ProcessEnvironment environment, ProductConfig config, ModelNode patchingInfo, Path installationDir) { assert environment != null; assert config != null; assert patchingInfo != null; assert installationDir != null; this.environment = environment; this.config = config; this.patchingInfo = patchingInfo; this.installationDir = installationDir; } public String getInstallationDate() { return ""; } ProcessEnvironment getEnvironment() { return environment; } ProductConfig getConfig() { return config; } String getInstallationDir() { if (Files.exists(installationDir)) { return installationDir.toAbsolutePath().toString(); } return ""; } String getLastUpdateDate() { List<ModelNode> result = Operations.readResult(patchingInfo).asList(); for (ModelNode patchAtt : result) { if (patchAtt.has("applied-at")) { return patchAtt.get("applied-at").asString(); } } return null; } String getHostName() { String hostName = getEnv("HOSTNAME"); if (hostName == null || hostName.isEmpty()) { hostName = getEnv("COMPUTERNAME"); if (hostName == null || hostName.isEmpty()) { hostName = InetAddressUtil.getLocalHostName(); if (hostName == null || hostName.isEmpty()) { hostName = environment.getHostName(); } } } return hostName; } /** * Get a System property by its name. * * @param name the name of the wanted System property. * @return the System property value - null if it is not defined. */ private String getEnv(String name) { return System.getSecurityManager() == null ? System.getenv(name) : doPrivileged(new ReadEnvironmentPropertyAction(name)); } } }