/* * RHQ Management Platform * Copyright (C) 2005-2013 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 General Public License, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * 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 General Public License and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.core.domain.cloud; import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.OneToOne; import javax.persistence.PrePersist; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import org.rhq.core.domain.operation.ResourceOperationHistory; import org.rhq.core.domain.resource.Resource; /** * An RHQ Storage Node (Cassandra) * * @author Jay Shaughnessy */ @Entity(name = "StorageNode") @NamedQueries( // { @NamedQuery(name = StorageNode.QUERY_FIND_ALL, query = "SELECT s FROM StorageNode s"), @NamedQuery(name = StorageNode.QUERY_FIND_BY_ADDRESS, query = "" // + " SELECT s " // + " FROM StorageNode s " // + "LEFT JOIN FETCH s.resource r " // + " WHERE s.address = :address"), @NamedQuery(name = StorageNode.QUERY_FIND_ALL_BY_MODE, query = "SELECT s FROM StorageNode s WHERE s.operationMode = :operationMode"), @NamedQuery(name = StorageNode.QUERY_FIND_ALL_BY_MODES, query = "SELECT s FROM StorageNode s WHERE s.operationMode IN (:operationModes)"), @NamedQuery(name = StorageNode.QUERY_FIND_ALL_BY_MODE_EXCLUDING, query = "SELECT s FROM StorageNode s WHERE s.operationMode = :operationMode AND s <> :storageNode"), @NamedQuery(name = StorageNode.QUERY_FIND_ALL_NOT_INSTALLED, query = "SELECT s FROM StorageNode s WHERE NOT s.operationMode = 'INSTALLED'"), @NamedQuery(name = StorageNode.QUERY_FIND_ALL_NORMAL, query = "SELECT s FROM StorageNode s WHERE s.operationMode = 'NORMAL'"), @NamedQuery(name = StorageNode.QUERY_DELETE_BY_ID, query = "DELETE FROM StorageNode s WHERE s.id = :storageNodeId "), @NamedQuery(name = StorageNode.QUERY_FIND_SCHEDULE_IDS_BY_PARENT_RESOURCE_ID_AND_MEASUREMENT_DEFINITION_NAMES, query = "" // + " SELECT def.name, def.id, ms.id, res.id FROM MeasurementSchedule ms " // + " JOIN ms.definition def " // + " JOIN ms.resource res " // + " WHERE ms.definition = def " // + " AND res.parentResource.id = :parrentId " // + " AND ms.enabled = true" // + " AND def.name IN (:metricNames)"), @NamedQuery(name = StorageNode.QUERY_FIND_SCHEDULE_IDS_BY_GRANDPARENT_RESOURCE_ID_AND_MEASUREMENT_DEFINITION_NAMES, query = "" // + " SELECT def.name, def.id, ms.id, res.id FROM MeasurementSchedule ms " // + " JOIN ms.definition def " // + " JOIN ms.resource res " // + " WHERE ms.definition = def " // + " AND res.parentResource.parentResource.id = :grandparrentId " // + " AND ms.enabled = true" // + " AND def.name IN (:metricNames)"), // @NamedQuery(name = StorageNode.QUERY_UPDATE_REMOVE_LINKED_RESOURCES, query = "" // + " UPDATE StorageNode s " // + " SET s.resource = NULL " // + " WHERE s.resource.id in (:resourceIds)"), @NamedQuery(name = StorageNode.QUERY_UPDATE_OPERATION_MODE, query = "UPDATE StorageNode s SET s.operationMode = :newOperationMode WHERE s.operationMode = :oldOperationMode"), @NamedQuery(name = StorageNode.QUERY_FIND_UNACKED_ALERTS_COUNTS, query = "" // + " SELECT resource.id, COUNT(alert.id) " + " FROM Alert alert JOIN alert.alertDefinition alertDef JOIN alertDef.resource resource" // + " WHERE resource.inventoryStatus = 'COMMITTED' " // + " AND alert.acknowledgeTime = -1 " // + " AND resource.resourceType.plugin = 'RHQStorage' " // + " GROUP BY resource.id") }) @SequenceGenerator(allocationSize = org.rhq.core.domain.util.Constants.ALLOCATION_SIZE, name = "RHQ_STORAGE_NODE_ID_SEQ", sequenceName = "RHQ_STORAGE_NODE_ID_SEQ") @Table(name = "RHQ_STORAGE_NODE") public class StorageNode implements Serializable { public static final long serialVersionUID = 1L; public static final String QUERY_FIND_ALL = "StorageNode.findAll"; public static final String QUERY_FIND_BY_ADDRESS = "StorageNode.findByAddress"; public static final String QUERY_FIND_ALL_BY_MODE = "StorageNode.findAllByMode"; public static final String QUERY_FIND_ALL_BY_MODES = "StorageNode.findAllByModes"; public static final String QUERY_FIND_ALL_BY_MODE_EXCLUDING = "StorageNode.findAllByModeExcluding"; public static final String QUERY_FIND_ALL_NOT_INSTALLED = "StorageNode.findAllCloudMembers"; public static final String QUERY_DELETE_BY_ID = "StorageNode.deleteById"; public static final String QUERY_FIND_ALL_NORMAL = "StorageNode.findAllNormalCloudMembers"; public static final String QUERY_FIND_SCHEDULE_IDS_BY_PARENT_RESOURCE_ID_AND_MEASUREMENT_DEFINITION_NAMES = "StorageNode.findScheduleIdsByParentResourceIdAndMeasurementDefinitionNames"; public static final String QUERY_FIND_SCHEDULE_IDS_BY_GRANDPARENT_RESOURCE_ID_AND_MEASUREMENT_DEFINITION_NAMES = "StorageNode.findScheduleIdsByGrandparentResourceIdAndMeasurementDefinitionNames"; public static final String QUERY_UPDATE_REMOVE_LINKED_RESOURCES = "StorageNode.updateRemoveLinkedResources"; public static final String QUERY_UPDATE_OPERATION_MODE = "StorageNode.updateOperationMode"; public static final String QUERY_FIND_UNACKED_ALERTS_COUNTS = "StorageNode.findUnackedAlertsCounts"; private static final String JMX_CONNECTION_STRING = "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi"; @Column(name = "ID", nullable = false) @GeneratedValue(strategy = GenerationType.AUTO, generator = "RHQ_STORAGE_NODE_ID_SEQ") @Id private int id; @Column(name = "ADDRESS", nullable = false) private String address; @Column(name = "CQL_PORT", nullable = false) private int cqlPort; @Column(name = "OPERATION_MODE", nullable = false) @Enumerated(EnumType.STRING) private OperationMode operationMode; // the time this storage node was installed into the infrastructure @Column(name = "CTIME", nullable = false) private long ctime; // the time this storage node was last updated @Column(name = "MTIME", nullable = false) private long mtime; @Column(name = "MAINTENANCE_PENDING", nullable = false) private boolean maintenancePending; @Column(name = "ERROR_MSG", nullable = true) private String errorMessage; @JoinColumn(name = "RESOURCE_ID", referencedColumnName = "ID", nullable = true) @OneToOne(fetch = FetchType.EAGER, optional = true) private Resource resource; @JoinColumn(name = "RESOURCE_OP_HIST_ID", referencedColumnName = "ID", nullable = true) @OneToOne(optional = true, cascade = { CascadeType.REMOVE }) private ResourceOperationHistory failedOperation; @Column(name = "VERSION", nullable = false) private String version; // required for JPA public StorageNode() { } public StorageNode(int storageNodeId) { this.id = storageNodeId; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public int getCqlPort() { return cqlPort; } public void setCqlPort(int cqlPort) { this.cqlPort = cqlPort; } public long getCtime() { return ctime; } public long getMtime() { return mtime; } public void setMtime(long mtime) { this.mtime = mtime; } public boolean isMaintenancePending() { return maintenancePending; } public void setMaintenancePending(boolean maintenancePending) { this.maintenancePending = maintenancePending; } public Resource getResource() { return resource; } public void setResource(Resource resource) { this.resource = resource; } public String getErrorMessage() { return errorMessage; } public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } public ResourceOperationHistory getFailedOperation() { return failedOperation; } public void setFailedOperation(ResourceOperationHistory failedOperation) { this.failedOperation = failedOperation; } public OperationMode getOperationMode() { return operationMode; } public void setOperationMode(OperationMode operationMode) { this.operationMode = operationMode; } public Status getStatus() { if (operationMode == OperationMode.INSTALLED) { return Status.INSTALLED; } if (operationMode == OperationMode.ANNOUNCE || operationMode == OperationMode.BOOTSTRAP || operationMode == OperationMode.ADD_MAINTENANCE) { if (errorMessage == null && failedOperation == null) { return Status.JOINING; } else { return Status.DOWN; } } if (operationMode == OperationMode.DECOMMISSION || operationMode == OperationMode.UNANNOUNCE || operationMode == OperationMode.REMOVE_MAINTENANCE || operationMode == OperationMode.UNINSTALL) { if (errorMessage == null && failedOperation == null) { return Status.LEAVING; } else { return Status.DOWN; } } // bz 1149687 -> returning NORMAL even if the maintenance is running if (operationMode == OperationMode.NORMAL || operationMode == OperationMode.MAINTENANCE) { return Status.NORMAL; } return Status.DOWN; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public enum OperationMode { DECOMMISSION("Remove the storage node from service"), DOWN("This storage node is down"), // INSTALLED("This storage node is newly installed but not yet operational"), // MAINTENANCE("This storage node is in maintenance mode"), // NORMAL("This storage node is running normally"), ANNOUNCE( "The storage node is installed but not yet part of the cluster. It is being announced so that it " + "can join the cluster."), UNANNOUNCE( "The storage node has been decommissioned and the cluster is being notified to stop accepting " + "gossip from its IP address."), BOOTSTRAP( "The storage is installed but not yet part of the cluster. It is getting bootstrapped into the " + "cluster"), ADD_MAINTENANCE( "The storage node is running and is preparing to undergo routine maintenance that is " + "necessary when a new node joins the cluster."), REMOVE_MAINTENANCE( "The storage node is no longer part of the cluster. Remaining storage node are " + "undergoing cluster maintenance due to the topology change."), UNINSTALL( "The storage node is being removed from inventory and its bits on disk are getting purged."); public final String message; private OperationMode(String message) { this.message = message; } public String getMessage() { return message; } } public enum Status { INSTALLED, DOWN, NORMAL, JOINING, LEAVING } @Override public String toString() { return "StorageNode[id=" + id + ", address=" + address + ", cqlPort=" + cqlPort + ", operationMode=" + operationMode + ", mtime=" + mtime + "]"; } @PrePersist void onPersist() { this.ctime = System.currentTimeMillis(); this.mtime = this.ctime; // I'd like to do this bu smartgwt can't handle the getPackage() call //this.version = this.getClass().getPackage().getImplementationVersion(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((address == null) ? 0 : address.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || !(obj instanceof StorageNode)) { return false; } final StorageNode other = (StorageNode) obj; if (address == null) { if (other.getAddress() != null) { return false; } } else if (!address.equals(other.getAddress())) { return false; } return true; } }