/*
* This file is part of DRBD Management Console by LINBIT HA-Solutions GmbH
* written by Rasto Levrinc.
*
* Copyright (C) 2009-2010, LINBIT HA-Solutions GmbH.
* Copyright (C) 2009-2010, Rasto Levrinc
*
* DRBD Management Console is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* DRBD Management Console 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with drbd; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package lcmc.crm.ui.resource;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import lcmc.common.domain.AccessMode;
import lcmc.common.domain.Application;
import lcmc.crm.domain.CrmXml;
import lcmc.crm.domain.ClusterStatus;
import lcmc.host.domain.Host;
import lcmc.common.domain.StringValue;
import lcmc.common.domain.Value;
import lcmc.crm.domain.Service;
import lcmc.common.ui.Browser;
import lcmc.cluster.ui.ClusterBrowser;
import lcmc.common.ui.EditableInfo;
import lcmc.cluster.ui.widget.Check;
import lcmc.cluster.ui.widget.Widget;
import lcmc.crm.service.CRM;
import lcmc.common.domain.util.Tools;
import javax.inject.Named;
/**
* Object that holds a colocation constraint information.
*/
@Named
final class HbColocationInfo extends EditableInfo implements HbConstraintInterface {
private ServiceInfo serviceInfoRsc;
private ServiceInfo serviceInfoWithRsc;
private HbConnectionInfo connectionInfo;
void init(final HbConnectionInfo connectionInfo,
final ServiceInfo serviceInfoRsc,
final ServiceInfo serviceInfoWithRsc,
final Browser browser) {
super.init("Colocation", browser);
setResource(new Service("Colocation"));
this.connectionInfo = connectionInfo;
this.serviceInfoRsc = serviceInfoRsc;
this.serviceInfoWithRsc = serviceInfoWithRsc;
}
void setServiceInfoRsc(final ServiceInfo serviceInfoRsc) {
this.serviceInfoRsc = serviceInfoRsc;
}
void setServiceInfoWithRsc(final ServiceInfo serviceInfoWithRsc) {
this.serviceInfoWithRsc = serviceInfoWithRsc;
}
@Override
public ClusterBrowser getBrowser() {
return (ClusterBrowser) super.getBrowser();
}
void setParameters() {
final ClusterStatus clStatus = getBrowser().getClusterStatus();
final String colId = getService().getCrmId();
final Map<String, Value> resourceNode = new HashMap<String, Value>();
if (serviceInfoRsc == null || serviceInfoWithRsc == null) {
/* rsc set placeholder */
final CrmXml.ColocationData colocationData = clStatus.getColocationData(colId);
final String score = colocationData.getScore();
resourceNode.put(CrmXml.SCORE_CONSTRAINT_PARAM, new StringValue(score));
} else if (serviceInfoRsc.isConstraintPlaceholder()
|| serviceInfoWithRsc.isConstraintPlaceholder()) {
/* rsc set edge */
final ConstraintPHInfo cphi;
final CrmXml.RscSet rscSet;
if (serviceInfoRsc.isConstraintPlaceholder()) {
cphi = (ConstraintPHInfo) serviceInfoRsc;
rscSet = cphi.getRscSetConnectionDataColocation().getRscSet1();
} else {
cphi = (ConstraintPHInfo) serviceInfoWithRsc;
rscSet = cphi.getRscSetConnectionDataColocation().getRscSet2();
}
resourceNode.put("sequential", new StringValue(rscSet.getSequential()));
resourceNode.put("role", new StringValue(rscSet.getColocationRole()));
} else {
final CrmXml.ColocationData colocationData = clStatus.getColocationData(colId);
if (colocationData != null) {
final String score = colocationData.getScore();
final String rscRole = colocationData.getRscRole();
final String withRscRole = colocationData.getWithRscRole();
resourceNode.put(CrmXml.SCORE_CONSTRAINT_PARAM, new StringValue(score));
resourceNode.put("rsc-role", new StringValue(rscRole));
resourceNode.put("with-rsc-role", new StringValue(withRscRole));
}
}
final String[] params = getParametersFromXML();
if (params != null) {
for (final String param : params) {
Value value = resourceNode.get(param);
if (value == null || value.isNothingSelected()) {
value = getParamDefault(param);
}
final Value oldValue = getParamSaved(param);
if (!Tools.areEqual(value, oldValue)) {
getResource().setValue(param, value);
final Widget wi = getWidget(param, null);
if (wi != null) {
wi.setValue(value);
}
}
}
}
}
@Override
public boolean isOrder() {
return false;
}
/**
* Returns long description of the parameter, that is used for
* tool tips.
*/
@Override
protected String getParamLongDesc(final String param) {
final String text = getBrowser().getCrmXml().getColocationParamLongDesc(param);
if (serviceInfoRsc != null && serviceInfoWithRsc != null) {
return text.replaceAll("@RSC@", Matcher.quoteReplacement(serviceInfoRsc.toString()))
.replaceAll("@WITH-RSC@", Matcher.quoteReplacement(serviceInfoWithRsc.toString()));
}
return text;
}
/** Returns short description of the parameter, that is used as * label. */
@Override
protected String getParamShortDesc(final String param) {
return getBrowser().getCrmXml().getColocationParamShortDesc(param);
}
/**
* Checks if the new value is correct for the parameter type and
* constraints.
*/
@Override
protected boolean checkParam(final String param, final Value newValue) {
return getBrowser().getCrmXml().checkColocationParam(param, newValue);
}
@Override
protected Value getParamDefault(final String param) {
return getBrowser().getCrmXml().getColocationParamDefault(param);
}
@Override
protected Value getParamPreferred(final String param) {
return getBrowser().getCrmXml().getColocationParamPreferred(param);
}
@Override
public String[] getParametersFromXML() {
if (serviceInfoRsc == null || serviceInfoWithRsc == null) {
/* rsc set colocation */
return getBrowser().getCrmXml().getResourceSetColocationParameters();
} else if (serviceInfoRsc.isConstraintPlaceholder() || serviceInfoWithRsc.isConstraintPlaceholder()) {
/* when rsc set edges are clicked */
return getBrowser().getCrmXml().getResourceSetColConnectionParameters();
} else {
return getBrowser().getCrmXml().getColocationParameters();
}
}
/** Returns when at least one resource in rsc set can be promoted. */
private boolean isRscSetMaster() {
final ConstraintPHInfo cphi;
final CrmXml.RscSet rscSet;
if (serviceInfoRsc.isConstraintPlaceholder()) {
cphi = (ConstraintPHInfo) serviceInfoRsc;
rscSet = cphi.getRscSetConnectionDataColocation().getRscSet1();
} else {
cphi = (ConstraintPHInfo) serviceInfoWithRsc;
rscSet = cphi.getRscSetConnectionDataColocation().getRscSet2();
}
return rscSet != null && getBrowser().isOneMaster(rscSet.getRscIds());
}
/**
* Possible choices for pulldown menus, or null if it is not a pull
* down menu.
*/
@Override
protected Value[] getParamPossibleChoices(final String param) {
if ("role".equals(param)) {
return getBrowser().getCrmXml().getColocationParamComboBoxChoices(param, isRscSetMaster());
} else if ("with-rsc-role".equals(param)) {
return getBrowser().getCrmXml().getColocationParamComboBoxChoices(param,
serviceInfoWithRsc.getService().isMaster());
} else if ("rsc-role".equals(param)) {
return getBrowser().getCrmXml().getColocationParamComboBoxChoices(param,
serviceInfoRsc.getService().isMaster());
} else {
return getBrowser().getCrmXml().getColocationParamComboBoxChoices(param, false);
}
}
/** Returns parameter type, boolean etc. */
@Override
protected String getParamType(final String param) {
return getBrowser().getCrmXml().getColocationParamType(param);
}
/** Returns section to which the global belongs. */
@Override
protected String getSection(final String param) {
return getBrowser().getCrmXml().getColocationSectionForDisplay(param);
}
/**
* Returns whether the parameter is of the boolean type and needs the
* checkbox.
*/
@Override
protected boolean isCheckBox(final String param) {
return getBrowser().getCrmXml().isColocationBoolean(param);
}
/** Returns true if the specified parameter is of time type. */
@Override
protected boolean isTimeType(final String param) {
return getBrowser().getCrmXml().isColocationTimeType(param);
}
/** Returns true if the specified parameter is integer. */
@Override
protected boolean isInteger(final String param) {
return getBrowser().getCrmXml().isColocationInteger(param);
}
/** Returns true if the specified parameter is label. */
@Override
protected boolean isLabel(final String param) {
return getBrowser().getCrmXml().isColocationLabel(param);
}
/** Returns true if the specified parameter is required. */
@Override
protected boolean isRequired(final String param) {
return getBrowser().getCrmXml().isColocationRequired(param);
}
/** Returns attributes of this colocation. */
protected Map<String, String> getAttributes() {
final String[] params = getParametersFromXML();
final Map<String, String> attrs = new LinkedHashMap<String, String>();
for (final String param : params) {
final Value value = getComboBoxValue(param);
if (value != null) {
attrs.put(param, value.getValueForConfig());
}
}
return attrs;
}
/** Applies changes to the colocation parameters. */
@Override
public void apply(final Host dcHost, final Application.RunMode runMode) {
final String[] params = getParametersFromXML();
final Map<String, String> attrs = new LinkedHashMap<String, String>();
boolean changed = true;
for (final String param : params) {
final Value value = getComboBoxValue(param);
if (!Tools.areEqual(value, getParamSaved(param))) {
changed = true;
}
if (value != null) {
attrs.put(param, value.getValueForConfig());
}
}
if (changed) {
final String colId = getService().getCrmId();
if (serviceInfoRsc == null || serviceInfoWithRsc == null) {
/* placeholder */
final PcmkRscSetsInfo prsi = (PcmkRscSetsInfo) connectionInfo;
CRM.setRscSet(dcHost,
colId,
false,
null,
false,
prsi.getAllAttributes(dcHost, null, null, true, runMode),
null,
attrs,
runMode);
} else if (serviceInfoRsc.isConstraintPlaceholder() || serviceInfoWithRsc.isConstraintPlaceholder()) {
/* edge */
final ConstraintPHInfo cphi;
final CrmXml.RscSet rscSet;
if (serviceInfoRsc.isConstraintPlaceholder()) {
cphi = (ConstraintPHInfo) serviceInfoRsc;
rscSet = cphi.getRscSetConnectionDataColocation().getRscSet1();
} else {
cphi = (ConstraintPHInfo) serviceInfoWithRsc;
rscSet = cphi.getRscSetConnectionDataColocation().getRscSet2();
}
final PcmkRscSetsInfo prsi = cphi.getPcmkRscSetsInfo();
CRM.setRscSet(dcHost,
colId,
false,
null,
false,
prsi.getAllAttributes(dcHost, rscSet, attrs, true, runMode),
null,
prsi.getColocationAttributes(colId),
runMode);
} else {
CRM.addColocation(dcHost,
colId,
serviceInfoRsc.getHeartbeatId(runMode),
serviceInfoWithRsc.getHeartbeatId(runMode),
attrs,
runMode);
}
}
if (Application.isLive(runMode)) {
storeComboBoxValues(params);
}
}
/** Returns service that belongs to this info object. */
@Override
public Service getService() {
return (Service) getResource();
}
/** Returns name of the rsc1 attribute. */
@Override
public String getRsc1Name() {
return "rsc";
}
/** Returns name of the rsc2 attribute. */
@Override
public String getRsc2Name() {
return "with-rsc";
}
/** Resource 1 in colocation constraint. */
@Override
public String getRsc1() {
return serviceInfoRsc.toString();
}
/** Resource 2 in colocation constraint. */
@Override
public String getRsc2() {
return serviceInfoWithRsc.toString();
}
/** Resource 1 object in colocation constraint. */
@Override
public ServiceInfo getRscInfo1() {
return serviceInfoRsc;
}
/** Resource 2 object in colocation constraint. */
@Override
public ServiceInfo getRscInfo2() {
return serviceInfoWithRsc;
}
/** Returns the score of this colocation. */
int getScore() {
//final String rsc = serviceInfoRsc.getService().getHeartbeatId();
//final String withRsc =
// serviceInfoWithRsc.getService().getHeartbeatId();
final ClusterStatus clStatus = getBrowser().getClusterStatus();
final String colId = getService().getCrmId();
final CrmXml.ColocationData data = clStatus.getColocationData(colId);
if (data == null) {
return 0;
}
final String score = data.getScore();
if (score == null) {
return 0;
} else if (CrmXml.INFINITY_VALUE.getValueForConfig().equals(score)
|| CrmXml.PLUS_INFINITY_VALUE.getValueForConfig().equals(score)) {
return 1000000;
} else if (CrmXml.MINUS_INFINITY_VALUE.getValueForConfig().equals(score)) {
return -1000000;
}
return Integer.parseInt(score);
}
@Override
protected boolean isAdvanced(final String param) {
return true;
}
@Override
protected String isEnabled(final String param) {
return null;
}
@Override
protected AccessMode.Type getAccessType(final String param) {
return AccessMode.ADMIN;
}
@Override
protected AccessMode.Mode isEnabledOnlyInAdvancedMode(final String param) {
return AccessMode.NORMAL;
}
@Override
public Check checkResourceFields(final String param, final String[] params) {
return checkResourceFields(param, params, false);
}
@Override
public Check checkResourceFields(final String param, final String[] params, final boolean fromUp) {
if (fromUp) {
return super.checkResourceFields(param, params);
} else {
return connectionInfo.checkResourceFields(param, null);
}
}
}