/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package controllers;
import static controllers.Common.angularRenderArgs;
import static render.RenderProxy.renderViprProxy;
import static render.RenderSupportPackage.renderSupportPackage;
import static util.BourneUtil.getSysClient;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.emc.storageos.model.tenant.TenantOrgRestRep;
import com.emc.storageos.services.ServicesMetadata;
import com.emc.vipr.model.sys.recovery.RecoveryPrecheckStatus;
import jobs.MinorityNodeRecoveryJob;
import jobs.RebootNodeJob;
import jobs.RestartServiceJob;
import models.datatable.NodeServicesDataTable;
import models.datatable.NodesDataTable;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import play.Logger;
import play.data.validation.Required;
import play.i18n.Messages;
import play.libs.F.Promise;
import play.mvc.Controller;
import play.mvc.With;
import util.AdminDashboardUtils;
import util.BourneUtil;
import util.DisasterRecoveryUtils;
import util.MonitorUtils;
import util.SystemLogUtils;
import util.TenantUtils;
import util.datatable.DataTablesSupport;
import util.support.SupportPackageCreator;
import util.support.SupportPackageCreator.OrderTypes;
import com.emc.storageos.model.property.PropertyInfoRestRep;
import com.emc.storageos.services.util.PlatformUtils;
import com.emc.storageos.systemservices.impl.healthmonitor.models.Status;
import com.emc.vipr.client.ViPRSystemClient;
import com.emc.vipr.model.sys.ClusterInfo;
import com.emc.vipr.model.sys.healthmonitor.DataDiskStats;
import com.emc.vipr.model.sys.healthmonitor.NodeHealth;
import com.emc.vipr.model.sys.healthmonitor.NodeStats;
import com.emc.vipr.model.sys.healthmonitor.ProcModels.MemoryStats;
import com.emc.vipr.model.sys.healthmonitor.ServiceHealth;
import com.emc.vipr.model.sys.healthmonitor.ServiceStats;
import com.emc.vipr.model.sys.recovery.DbRepairStatus;
import com.emc.vipr.model.sys.recovery.RecoveryStatus;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import controllers.deadbolt.Restrict;
import controllers.deadbolt.Restrictions;
import controllers.security.Security;
import controllers.util.Models;
@With(Common.class)
@Restrictions({ @Restrict("SYSTEM_MONITOR"), @Restrict("SYSTEM_ADMIN"), @Restrict("RESTRICTED_SYSTEM_ADMIN"), @Restrict("SECURITY_ADMIN") })
public class SystemHealth extends Controller {
public static final String PARAM_NODE_ID = "nodeId";
public static final String PARAM_SERVICE = "service";
public static final String PARAM_SEVERITY = "severity";
public static final String PARAM_SEARCH_MESSAGE = "searchMessage";
public static final String PARAM_START_TIME = "startTime";
public static final String PARAM_END_TIME = "endTime";
public static final String PARAM_CONFIG_PROP = "redeploy";
public static final String DBHEALTH_STATUS_SUCCESS = "SUCCESS";
public static final String DBHEALTH_STATUS_FAIL = "FAILED";
public static final String DBHEALTH_STATUS_FINISH = "FINISHED";
public static final String DEFAULT_SEVERITY = "7";
public static final String[] SEVERITIES = { "4", "5", "7", "8" };
public static final String[] ORDER_TYPES = { OrderTypes.ERROR.name(), OrderTypes.ALL.name() };
public static void systemHealth() {
final ViPRSystemClient client = BourneUtil.getSysClient();
List<NodeHealth> nodeHealthList = MonitorUtils.getNodeHealth(client);
Map<String, Integer> statusCount = Maps.newHashMap();
// Initialize Map so with a "Good" status to have 0 services so when we display, if no other service is "Good" it will still display
// that in UI.
statusCount.put(Status.GOOD.toString(), 0);
for (NodeHealth nodeHealth : nodeHealthList) {
Integer count = statusCount.get(nodeHealth.getStatus());
statusCount.put(nodeHealth.getStatus(), (count == null) ? 1 : ++count);
}
renderArgs.put("allServices", getAllServiceNames(nodeHealthList));
angularRenderArgs().put("clusterInfo", AdminDashboardUtils.getClusterInfo());
renderArgs.put("dataTable", new NodesDataTable());
angularRenderArgs().put("nodeCount", nodeHealthList.size());
angularRenderArgs().put("statusCount", statusCount);
render();
}
public static void clusterHealth() {
Map<String, Promise<?>> promises = Maps.newHashMap();
promises.put("nodeHealthList", AdminDashboardUtils.nodeHealthList());
promises.put("clusterInfo", AdminDashboardUtils.clusterInfo());
trySetRenderArgs(promises);
render();
}
public static void dbHealth() {
DbRepairStatus dbstatus = AdminDashboardUtils.gethealthdb();
int progress = dbstatus.getProgress();
String health = dbstatus.getStatus().toString();
angularRenderArgs().put("progress", progress + "%");
if (health == DBHEALTH_STATUS_SUCCESS || health == DBHEALTH_STATUS_FAIL) {
health = DBHEALTH_STATUS_FINISH;
}
renderArgs.put("health", health);
if (dbstatus.getStartTime() != null) {
DateTime startTime = new DateTime(dbstatus.getStartTime().getTime());
renderArgs.put("startTime", startTime);
}
if (dbstatus.getLastCompletionTime() != null) {
DateTime endTime = new DateTime(dbstatus.getLastCompletionTime().getTime());
renderArgs.put("endTime", endTime);
}
render(dbstatus);
}
public static void nodeRecoveryVapp() {
ViPRSystemClient client = BourneUtil.getSysClient();
RecoveryStatus recoveryStatus = client.control().getRecoveryStatus();
if (recoveryStatus.getStartTime()!= null ) {
DateTime startTime = new DateTime(recoveryStatus.getStartTime().getTime());
renderArgs.put("startTime", startTime);
}
if (recoveryStatus.getEndTime() != null) {
DateTime endTime = new DateTime(recoveryStatus.getEndTime().getTime());
renderArgs.put("endTime", endTime);
}
RecoveryPrecheckStatus recoveryPrecheckStatus = client.control().getRecoveryPrecheckStatus();
String precheckMsg = "";
switch (recoveryPrecheckStatus.getStatus()) {
case RECOVERY_NEEDED:
precheckMsg = Messages.get("nodeRecovery.precheck.success", recoveryPrecheckStatus.getRecoverables().toString());
break;
case ALL_GOOD:
precheckMsg = Messages.get("nodeRecovery.precheck.fail.allgood");
break;
case VAPP_IN_DR_OR_GEO:
precheckMsg = Messages.get("nodeRecovery.precheck.fail.drorgeo");
break;
case NODE_UNREACHABLE:
precheckMsg = Messages.get("nodeRecovery.precheck.fail.unreachable");
break;
case CORRUPTED_NODE_COUNT_MORE_THAN_QUORUM:
precheckMsg = Messages.get("nodeRecovery.precheck.fail.quorum");
break;
case CORRUPTED_NODE_FOR_OTHER_REASON:
precheckMsg = Messages.get("nodeRecovery.precheck.fail.other");
break;
}
renderArgs.put("precheckMsg", precheckMsg);
renderArgs.put("precheckStatus", recoveryPrecheckStatus.getStatus().name());
String recoveringMsg = Messages.get("nodeRecovery.recovering.status", recoveryPrecheckStatus.getRecoverables().toString());
renderArgs.put("recoveringMsg", recoveringMsg);
ClusterInfo clusterInfo = AdminDashboardUtils.getClusterInfo();
render(recoveryStatus, clusterInfo);
}
public static void nodeRecovery() {
ViPRSystemClient client = BourneUtil.getSysClient();
RecoveryStatus recoveryStatus = client.control().getRecoveryStatus();
if (recoveryStatus.getStartTime()!= null ) {
DateTime startTime = new DateTime(recoveryStatus.getStartTime().getTime());
renderArgs.put("startTime", startTime);
}
if (recoveryStatus.getEndTime() != null) {
DateTime endTime = new DateTime(recoveryStatus.getEndTime().getTime());
renderArgs.put("endTime", endTime);
}
ClusterInfo clusterInfo = AdminDashboardUtils.getClusterInfo();
render(recoveryStatus, clusterInfo);
}
public static void nodeRecoveryReady() {
render();
}
public static void startNodeRecovery() {
minorityNodeRecovery();
}
/**
* Tries to set a number of render arguments.
*
* @param promises
* the map or key to promise.
*/
private static void trySetRenderArgs(Map<String, Promise<?>> promises) {
for (Map.Entry<String, Promise<?>> entry : promises.entrySet()) {
trySetRenderArg(entry.getKey(), entry.getValue());
}
}
/**
* Tries to set a render argument, ignoring any errors that may occur.
*
* @param name
* the name of the render argument.
* @param promise
* the promise to retrieve the value of the promise.
*/
private static void trySetRenderArg(String name, Promise<?> promise) {
try {
Object value = await(promise);
renderArgs.put(name, value);
} catch (Exception e) {
Throwable cause = Common.unwrap(e);
String message = Common.getUserMessage(cause);
renderArgs.put(name + "_error", message);
Logger.warn(cause, "Could not set renderArg '%s'", name);
}
}
public static void logs() {
List<NodeHealth> nodeHealthList = MonitorUtils.getNodeHealth();
ClusterInfo clusterInfo = AdminDashboardUtils.getClusterInfo();
renderArgs.put("severities", SEVERITIES);
if(DisasterRecoveryUtils.isActiveSite()) {
renderArgs.put("orderTypes", ORDER_TYPES);
}
Set<String> controlServiceNames = getControlServiceNames(nodeHealthList, clusterInfo);
renderArgs.put("controlServices", controlServiceNames);
Set<String> allServiceNames = getAllServiceNames(nodeHealthList);
renderArgs.put("allServices", allServiceNames);
List<NodeHealth> controlNodes = getControlNodes(nodeHealthList, clusterInfo);
renderArgs.put("controlNodes", controlNodes);
DateTime defaultStartTime = new DateTime().minusMinutes(15);
// Remove some logs from the default list
Set<String> defaultServiceNames = Sets.newHashSet(allServiceNames);
defaultServiceNames.remove(SystemLogUtils.MESSAGES_LOG);
defaultServiceNames.remove(SystemLogUtils.NGINX_ACCESS_LOG);
defaultServiceNames.remove(SystemLogUtils.NGINX_ERROR_LOG);
loadSystemLogArgument(PARAM_NODE_ID, null);
loadSystemLogArgument(PARAM_SERVICE, defaultServiceNames, String[].class);
loadSystemLogArgument(PARAM_SEVERITY, DEFAULT_SEVERITY);
loadSystemLogArgument(PARAM_SEARCH_MESSAGE, null);
loadSystemLogArgument(PARAM_START_TIME, defaultStartTime.getMillis(), Long.class);
Common.copyRenderArgsToAngular();
render();
}
public static void services(String nodeId) {
NodeHealth nodeHealth = MonitorUtils.getNodeHealth(nodeId);
if (nodeHealth != null) {
List<ServiceHealth> serviceHealthList = nodeHealth.getServiceHealthList();
if (!serviceHealthList.isEmpty()) {
renderArgs.put("dataTable", new NodeServicesDataTable());
angularRenderArgs().put("nodeStatus", nodeHealth.getStatus());
angularRenderArgs().put("serviceCount", serviceHealthList.size());
angularRenderArgs().put("statusCount", getStatusCount(serviceHealthList));
angularRenderArgs().put("nodeId", nodeId);
angularRenderArgs().put("nodeName", nodeHealth.getNodeName());
render(nodeId);
}
else {
flash.error(Messages.get("system.node.services.error", nodeHealth.getNodeName()));
}
} else {
Logger.warn("Could not determine node name.");
flash.error(Messages.get("system.node.error", nodeId));
}
systemHealth();
}
public static void details(String nodeId) {
NodeStats nodeStats = MonitorUtils.getNodeStats(nodeId);
NodeHealth nodeHealth = MonitorUtils.getNodeHealth(nodeId);
if (nodeStats != null && nodeHealth != null) {
angularRenderArgs().put("nodeType", getNodeType(nodeId));
angularRenderArgs().put("diskStats", nodeStats.getDiskStatsList());
angularRenderArgs().put("nodeStatus", nodeHealth.getStatus());
angularRenderArgs().put("nodeIp", nodeStats.getIp());
renderArgs.put("healthDetails", healthDetails(nodeStats, nodeHealth));
angularRenderArgs().put("nodeId", nodeId);
angularRenderArgs().put("nodeName", nodeHealth.getNodeName());
render(nodeId);
}
else {
flash.error(Messages.get("system.node.error", nodeId));
String nodeError= nodeId;
try {
nodeError = nodeHealth.getNodeName();
}catch (NullPointerException e){
Logger.warn("Could not determine node name.");
}
flash.error(Messages.get("system.node.error", nodeError));
systemHealth();
}
}
public static void renderNodeDetailsJson(String nodeId) {
NodeStats nodeStats = MonitorUtils.getNodeStats(nodeId);
NodeHealth nodeHealth = MonitorUtils.getNodeHealth(nodeId);
Map<String, Object> healthDetails = Maps.newHashMap();
if (nodeStats != null && nodeHealth != null) {
healthDetails = healthDetails(nodeStats, nodeHealth);
}
renderJSON(healthDetails);
}
private static Map<String, Object> healthDetails(NodeStats nodeStats, NodeHealth nodeHealth) {
MemoryStats memoryStats = nodeStats.getMemoryStats();
DataDiskStats dataDiskStats = nodeStats.getDataDiskStats();
Capacity rootCapacity = new Capacity();
Capacity dataCapacity = new Capacity();
Capacity memoryCapacity = new Capacity();
if (memoryStats != null) {
memoryCapacity = new Capacity((memoryStats.getMemTotal() - memoryStats.getMemFree()), memoryStats.getMemTotal());
}
if (dataDiskStats != null) {
rootCapacity = new Capacity(dataDiskStats.getRootUsedKB(), dataDiskStats.getRootUsedKB() + dataDiskStats.getRootAvailKB());
dataCapacity = new Capacity(dataDiskStats.getDataUsedKB(), dataDiskStats.getDataUsedKB() + dataDiskStats.getDataAvailKB());
}
List<ServiceHealth> serviceHealthList = nodeHealth.getServiceHealthList();
Map<String, Integer> statusCount = getStatusCount(serviceHealthList);
Map<String, Object> nodeDetails = Maps.newHashMap();
nodeDetails.put("serviceCount", serviceHealthList.size());
nodeDetails.put("cpuLoad", nodeStats.getLoadAvgStats());
nodeDetails.put("memoryCapacity", memoryCapacity);
nodeDetails.put("rootCapacity", rootCapacity);
nodeDetails.put("dataCapacity", dataCapacity);
nodeDetails.put("statusCount", statusCount);
return nodeDetails;
}
public static void nodeDetails(String nodeId) {
NodeStats nodeStats = MonitorUtils.getNodeStats(nodeId);
NodeHealth nodeHealth = MonitorUtils.getNodeHealth(nodeId);
if (nodeStats != null && nodeHealth != null) {
renderArgs.put("healthDetails", healthDetails(nodeStats, nodeHealth));
}
render(nodeId);
}
public static void listDiagnosticsJson(String nodeId) {
renderJSON(MonitorUtils.getNodeDiagnostics(nodeId));
}
public static void logsJson(String uri) {
String url = BourneUtil.getSysApiUrl() + StringEscapeUtils.unescapeHtml(uri);
renderViprProxy(url, Security.getAuthToken(), null);
}
public static void listNodesJson() {
List<NodesDataTable.Nodes> dataTableNodes = Lists.newArrayList();
for (NodeHealth node : MonitorUtils.getNodeHealth()) {
String type = getNodeType(node.getNodeId());
dataTableNodes.add(new NodesDataTable.Nodes(node, type));
}
renderJSON(DataTablesSupport.createSource(dataTableNodes, params));
}
private static String getNodeType(String nodeId) {
ClusterInfo cluster = AdminDashboardUtils.getClusterInfo();
if (isControlNode(nodeId, cluster)) {
return Messages.get("system.node.controller");
}
else if (isExtraNode(nodeId, cluster)) {
return Messages.get("system.node.dataservice");
}
else {
return null;
}
}
public static void listServicesJson(String nodeId) {
List<ServiceStats> serviceStatsList = MonitorUtils.getNodeStats(nodeId).getServiceStatsList();
List<ServiceHealth> serviceHealthList = MonitorUtils.getNodeHealth(nodeId).getServiceHealthList();
List<NodeServicesDataTable.Services> servicesList = Lists.newArrayList();
for (ServiceStats service : serviceStatsList) {
for (ServiceHealth health : serviceHealthList) {
if (service.getServiceName().equals(health.getServiceName())) {
servicesList.add(new NodeServicesDataTable.Services(nodeId, health, service));
}
}
}
renderJSON(DataTablesSupport.createSource(servicesList, params));
}
public static void diskStatsJson(String nodeId) {
renderJSON(MonitorUtils.getNodeStats(nodeId).getDiskStatsList());
}
public static void proxyJson(String uri) {
String url = BourneUtil.getSysApiUrl() + uri;
renderViprProxy(url, Security.getAuthToken(), null);
}
private static Map<String, Integer> getStatusCount(List<ServiceHealth> serviceList) {
Map<String, Integer> statusCount = Maps.newHashMap();
// Initialize Map so with a "Good" status to have 0 services so when we display, if no other service is "Good" it will still display
// that in UI.
statusCount.put(Status.GOOD.toString(), 0);
for (ServiceHealth service : serviceList) {
Integer count = statusCount.get(service.getStatus());
statusCount.put(service.getStatus(), (count == null) ? 1 : ++count);
}
return statusCount;
}
private static Set<String> getControlServiceNames(List<NodeHealth> nodeHealthList, ClusterInfo clusterInfo) {
List<NodeHealth> controlNodeHealthList = extractControlNodeHealth(nodeHealthList, clusterInfo);
Set<String> names = extractServiceNames(controlNodeHealthList);
names.addAll(Arrays.asList(SystemLogUtils.NON_SERVICE_LOGS));
return names;
}
private static Set<String> getAllServiceNames(List<NodeHealth> nodeHealthList) {
Set<String> names = extractServiceNames(nodeHealthList);
names.addAll(Arrays.asList(SystemLogUtils.NON_SERVICE_LOGS));
return names;
}
private static Set<String> extractServiceNames(NodeHealth nodeHealth) {
Set<String> services = Sets.newHashSet();
if (nodeHealth != null) {
for (ServiceHealth serviceHealth : nodeHealth.getServiceHealthList()) {
services.add(serviceHealth.getServiceName());
}
}
return services;
}
private static Set<String> extractServiceNames(List<NodeHealth> nodeHealthList) {
Set<String> services = Sets.newTreeSet();
if (nodeHealthList != null) {
for (NodeHealth nodeHealth : nodeHealthList) {
services.addAll(extractServiceNames(nodeHealth));
}
}
return services;
}
private static List<NodeHealth> extractControlNodeHealth(List<NodeHealth> nodeHealthList, ClusterInfo clusterInfo) {
List<NodeHealth> controlNodeHealths = Lists.newArrayList();
for (NodeHealth nodeHealth : nodeHealthList) {
if (isControlNode(nodeHealth.getNodeId(), clusterInfo)) {
controlNodeHealths.add(nodeHealth);
}
}
return controlNodeHealths;
}
private static List<NodeHealth> getControlNodes(List<NodeHealth> nodeHealthList, ClusterInfo clusterInfo) {
List<NodeHealth> controlNodes = Lists.newArrayList();
for (NodeHealth node : nodeHealthList) {
if (isControlNode(node.getNodeId(), clusterInfo)) {
controlNodes.add(node);
}
}
return controlNodes;
}
private static boolean isControlNode(String nodeId, ClusterInfo clusterInfo) {
if (clusterInfo != null && clusterInfo.getControlNodes() != null) {
return clusterInfo.getControlNodes().keySet().contains(nodeId);
}
return false;
}
private static boolean isExtraNode(String nodeId, ClusterInfo clusterInfo) {
if (clusterInfo != null && clusterInfo.getExtraNodes() != null) {
return clusterInfo.getExtraNodes().keySet().contains(nodeId);
}
return false;
}
private static void loadSystemLogArgument(String name, Object defaultValue) {
loadSystemLogArgument(name, defaultValue, String.class);
}
private static Object loadSystemLogArgument(String name, Object defaultValue, Class type) {
Object returnValue = null;
String[] values = params.getAll(name);
if (values != null && values.length > 0) {
if (values.length == 1) {
String value = values[0];
returnValue = convert(value, type);
} else {
returnValue = convert(values, type);
}
} else {
returnValue = defaultValue;
}
renderArgs.put(name, returnValue);
return returnValue;
}
private static <T> T convert(String value, Class<T> targetType) {
if (targetType.equals(String[].class)) {
return (T) new String[] { value };
}
else {
return (T) ConvertUtils.convert(value, targetType);
}
}
private static <T> T[] convert(String[] values, Class<T> targetType) {
if (targetType.equals(String[].class)) {
return (T[]) values;
}
else {
return (T[]) ConvertUtils.convert(values, targetType);
}
}
/**
* Download logs capability really creates the old support package.
*/
public static void download(String nodeId, String[] service, Integer severity, String searchMessage,
String startTime, String endTime, String orderTypes) {
SupportPackageCreator creator = new SupportPackageCreator(request, BourneUtil.getSysClient(),
Models.currentTenant(), BourneUtil.getCatalogClient());
if (StringUtils.isNotEmpty(nodeId)) {
creator.setNodeIds(Lists.newArrayList(nodeId));
}
if (service != null && service.length > 0) {
List<String> logNames = getLogNames(service);
creator.setLogNames(logNames);
}
if (StringUtils.isNotEmpty(searchMessage)) {
creator.setMsgRegex("(?i).*" + searchMessage + ".*");
}
if (StringUtils.isNotEmpty(startTime)) {
creator.setStartTimeWithRestriction(startTime);
}
if (StringUtils.isNotEmpty(endTime)) {
creator.setEndTime(endTime);
}
if (severity != null && severity > 0) {
creator.setLogSeverity(severity);
}
if(DisasterRecoveryUtils.isActiveSite()) {
if (StringUtils.equalsIgnoreCase(orderTypes, OrderTypes.ALL.name())) {
creator.setOrderTypes(OrderTypes.ALL);
} else if (StringUtils.equals(orderTypes, OrderTypes.ERROR.name())) {
creator.setOrderTypes(OrderTypes.ERROR);
}
}
if (Security.isSystemAdmin()) {
List<URI> tenantIds = Lists.newArrayList();
for (TenantOrgRestRep tenant : TenantUtils.getAllTenants()) {
tenantIds.add(tenant.getId());
}
creator.setTenantIds(tenantIds);
}
renderSupportPackage(creator);
}
private static List<String> getLogNames(String[] services) {
List<String> logNames = new ArrayList();
for (String service : services) {
if (service.equals("controllersvc")) {
logNames.addAll(ServicesMetadata.CONTROLLSVC_LOG_NAMES);
}
logNames.add(service);
}
return logNames;
}
@Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SECURITY_ADMIN"), @Restrict("RESTRICTED_SECURITY_ADMIN") })
public static void getRecoveryStatus() {
ViPRSystemClient client = BourneUtil.getSysClient();
RecoveryStatus recoveryStatus = client.control().getRecoveryStatus();
JsonElement jsonElement = new Gson().toJsonTree(recoveryStatus);
JsonObject jsonObj = jsonElement.getAsJsonObject();
if (recoveryStatus.getStartTime() != null) {
DateTime startTime = new DateTime(recoveryStatus.getStartTime().getTime());
jsonObj.addProperty("startTime", startTime.toString());
}
if (recoveryStatus.getEndTime() != null) {
DateTime endTime = new DateTime(recoveryStatus.getEndTime().getTime());
jsonObj.addProperty("endTime", endTime.toString());
}
renderJSON(jsonObj.toString());
}
@Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SECURITY_ADMIN"), @Restrict("RESTRICTED_SECURITY_ADMIN") })
public static void nodeReboot(@Required String nodeId) {
NodeHealth nodeHealth = MonitorUtils.getNodeHealth(nodeId);
String node= nodeId;
try {
node = MonitorUtils.getNodeHealth(nodeId).getNodeName();
}catch (NullPointerException e){
Logger.warn("Could not determine node name.");
}
if(nodeHealth!=null && nodeHealth.getStatus().equals("Good")){
new RebootNodeJob(getSysClient(), nodeId).in(3);
flash.success(Messages.get("adminDashboard.nodeRebooting", node));
Maintenance.maintenance(Common.reverseRoute(SystemHealth.class, "systemHealth"));
}else{
flash.error(Messages.get("systemHealth.message.reboot.unavailable", node));
systemHealth();
}
}
@Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SECURITY_ADMIN"), @Restrict("RESTRICTED_SECURITY_ADMIN") })
public static void minorityNodeRecovery() {
new MinorityNodeRecoveryJob(getSysClient()).in(3);
ViPRSystemClient client = BourneUtil.getSysClient();
List<NodeHealth> nodeHealthList = MonitorUtils.getNodeHealth();
ClusterInfo clusterInfo = AdminDashboardUtils.getClusterInfo();
if (PlatformUtils.isVMwareVapp()) {
RecoveryPrecheckStatus recoveryPrecheckStatus = client.control().getRecoveryPrecheckStatus();
String recoveringMsg = Messages.get("nodeRecovery.recovering.status", recoveryPrecheckStatus.getRecoverables().toString());
renderArgs.put("recoveringMsg", recoveringMsg);
}
RecoveryStatus recoveryStatus = client.control().getRecoveryStatus();
renderArgs.put("nodeHealthList", nodeHealthList);
renderArgs.put("clusterInfo", clusterInfo);
renderArgs.put("recoveryStatus", recoveryStatus);
if (PlatformUtils.isVMwareVapp()) {
render("@nodeRecoveryVapp");
} else {
render("@nodeRecovery");
}
}
@Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("SECURITY_ADMIN"), @Restrict("RESTRICTED_SECURITY_ADMIN") })
public static void serviceRestart(@Required String nodeId, @Required String serviceName) {
new RestartServiceJob(getSysClient(), serviceName, nodeId).in(3);
String node= nodeId;
try {
node = MonitorUtils.getNodeHealth(nodeId).getNodeName();
}catch (NullPointerException e){
Logger.warn("Could not determine node name.");
}
flash.success(Messages.get("adminDashboard.serviceRestarting", serviceName, node));
Maintenance.maintenance(Common.reverseRoute(SystemHealth.class, "services","nodeId", nodeId));
}
public static void downloadConfigParameters() throws UnsupportedEncodingException {
ViPRSystemClient client = BourneUtil.getSysClient();
PropertyInfoRestRep propertyInfo = client.config().getProperties(PARAM_CONFIG_PROP);
Map<String, String> props = propertyInfo.getAllProperties();
StringBuffer output = new StringBuffer();
for (Map.Entry<String, String> entry : props.entrySet()) {
output.append(entry.getKey());
output.append("=");
output.append(entry.getValue());
output.append("\n");
}
ByteArrayInputStream is = new ByteArrayInputStream(output.toString().getBytes("UTF-8"));
renderBinary(is, "configProperties", "text/plain", false);
}
/**
* If this is not an appliance, then node recovery should be available (may be a dev kit).
* If it is an appliance and it is not a VMware app, then node recovery should be available.
*
* @return Returns true if node recovery should be available.
*/
public static boolean isNodeRecoveryEnabled() {
boolean isEnabled = false;
try {
if (!PlatformUtils.isAppliance()) {
isEnabled = true;
} else if (!PlatformUtils.isVMwareVapp()) {
isEnabled = true;
}
} catch (IllegalStateException ise) {
// Thrown if method could not determine platform.
Logger.warn("Could not determine platform.");
}
return isEnabled;
}
public static class Capacity {
private long used;
private long total;
public Capacity(long usedInKB, long totalInKB) {
this.used = usedInKB * 1024;
this.total = totalInKB * 1024;
}
public Capacity() {
}
public long getUsed() {
return used;
}
public void setUsed(long used) {
this.used = used;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
}
}