/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.coordinator.client.model;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.jsoup.helper.StringUtil;
import com.emc.storageos.coordinator.common.Configuration;
import com.emc.storageos.coordinator.common.impl.ConfigurationImpl;
import com.emc.storageos.model.property.PropertyConstants;
/**
* Representation for a ViPR site, both primary and standby
*/
public class Site {
private static final String NO_ACTIVE_SITE_MESSAGE = "<no active site>";
private static final String KEY_NAME = "name";
private static final String KEY_DESCRIPTION = "description";
private static final String KEY_VIP = "vip";
private static final String KEY_VIP6 = "vip6";
private static final String KEY_SITE_SHORTID = "siteShortId";
private static final String KEY_CREATIONTIME = "creationTime";
private static final String KEY_LASTSTATEUPDATETIME = "lastStateUpdateTime";
private static final String KEY_LAST_LOST_QUORUM_TIME = "lastLostQuorumTime";
private static final String KEY_LASTSTATE = "lastState";
private static final String KEY_SITE_STATE = "state";
private static final String KEY_NODESADDR = "nodesAddr";
private static final String KEY_NODESADDR6 = "nodesAddr6";
private static final String KEY_NODECOUNT = "nodeCount";
private static TreeMap<String, String> treeMapSorter = new TreeMap<String, String>();
public static final String CONFIG_KIND = "disasterRecoverySites";
public static final Site DUMMY_ACTIVE_SITE;
private String uuid;
private String vdcShortId;
private String name;
private String vip;
private String vip6;
private String description;
private Map<String, String> hostIPv4AddressMap = new HashMap<>();
private Map<String, String> hostIPv6AddressMap = new HashMap<>();
private String siteShortId;
private long creationTime;
private long lastStateUpdateTime;
private long lastLostQuorumTime;
private SiteState state = SiteState.ACTIVE;
private SiteState lastState;
private int nodeCount;
static {
DUMMY_ACTIVE_SITE = new Site();
DUMMY_ACTIVE_SITE.setUuid("");
DUMMY_ACTIVE_SITE.setVip(NO_ACTIVE_SITE_MESSAGE);
DUMMY_ACTIVE_SITE.setName(NO_ACTIVE_SITE_MESSAGE);
DUMMY_ACTIVE_SITE.setState(SiteState.NONE);
}
public Site() {
}
public Site(Configuration config) {
if (config != null) {
fromConfiguration(config);
}
}
public SiteState getLastState() {
return lastState;
}
public void setLastState(SiteState lastState) {
this.lastState = lastState;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getVdcShortId() {
return vdcShortId;
}
public void setVdcShortId(String vdcShortId) {
this.vdcShortId = vdcShortId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVip() {
return vip;
}
public void setVip(String vip) {
this.vip = vip;
}
public Map<String, String> getHostIPv4AddressMap() {
return hostIPv4AddressMap;
}
public void setHostIPv4AddressMap(Map<String, String> hostIPv4AddressMap) {
this.hostIPv4AddressMap = hostIPv4AddressMap;
}
public Map<String, String> getHostIPv6AddressMap() {
return hostIPv6AddressMap;
}
public void setHostIPv6AddressMap(Map<String, String> hostIPv6AddressMap) {
this.hostIPv6AddressMap = hostIPv6AddressMap;
}
public int getNodeCount() {
return nodeCount;
}
public void setNodeCount(int nodeCount) {
this.nodeCount = nodeCount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSiteShortId() {
return siteShortId;
}
public void setSiteShortId(String shortId) {
this.siteShortId = shortId;
}
public long getCreationTime() {
return creationTime;
}
public void setCreationTime(long creationTime) {
this.creationTime = creationTime;
}
public long getLastLostQuorumTime() {
return lastLostQuorumTime;
}
public void setLastLostQuorumTime(long lastLostQuorumTime) {
this.lastLostQuorumTime = lastLostQuorumTime;
}
public long getLastStateUpdateTime() {
return lastStateUpdateTime;
}
public void setLastStateUpdateTime(long lastStateUpdateTime) {
this.lastStateUpdateTime = lastStateUpdateTime;
}
public SiteState getState() {
return state;
}
public void setState(SiteState state) {
this.state = state;
setLastStateUpdateTime(System.currentTimeMillis());
}
public String getVip6() {
return vip6;
}
public void setVip6(String vip6) {
this.vip6 = vip6;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Site))
return false;
Site other = (Site) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
public Configuration toConfiguration() {
ConfigurationImpl config = new ConfigurationImpl();
config.setKind(String.format("%s/%s", CONFIG_KIND, vdcShortId));
config.setId(uuid);
if (name != null) {
config.setConfig(KEY_NAME, name);
}
if (description != null) {
config.setConfig(KEY_DESCRIPTION, description);
}
if (vip != null) {
config.setConfig(KEY_VIP, vip);
}
if (vip6 != null) {
config.setConfig(KEY_VIP6, vip6);
}
if (siteShortId != null) {
config.setConfig(KEY_SITE_SHORTID, this.siteShortId);
}
config.setConfig(KEY_CREATIONTIME, String.valueOf(creationTime));
if (lastStateUpdateTime != 0L) {
config.setConfig(KEY_LASTSTATEUPDATETIME, String.valueOf(lastStateUpdateTime));
}
if (lastLostQuorumTime != 0L) {
config.setConfig(KEY_LAST_LOST_QUORUM_TIME, String.valueOf(lastLostQuorumTime));
}
if (lastState != null) {
config.setConfig(KEY_LASTSTATE, String.valueOf(lastState));
}
if (state != null) {
config.setConfig(KEY_SITE_STATE, String.valueOf(state));
}
config.setConfig(KEY_NODECOUNT, String.valueOf(nodeCount));
treeMapSorter.clear();
treeMapSorter.putAll(this.hostIPv4AddressMap);
config.setConfig(KEY_NODESADDR, StringUtil.join(treeMapSorter.values(), ","));
treeMapSorter.clear();
treeMapSorter.putAll(this.hostIPv6AddressMap);
config.setConfig(KEY_NODESADDR6, StringUtil.join(treeMapSorter.values(), ","));
return config;
}
private void fromConfiguration(Configuration config) {
String kindStr = config.getKind();
if (!kindStr.split("/")[0].equals(CONFIG_KIND)) {
throw new IllegalArgumentException("Unexpected configuration kind for Site");
}
try {
this.vdcShortId = kindStr.split("/")[1];
this.uuid = config.getId();
this.name = config.getConfig(KEY_NAME);
this.description = config.getConfig(KEY_DESCRIPTION);
this.vip = config.getConfig(KEY_VIP);
this.vip6 = config.getConfig(KEY_VIP6);
this.siteShortId = config.getConfig(KEY_SITE_SHORTID);
String s = config.getConfig(KEY_CREATIONTIME);
if (s != null) {
this.creationTime = Long.valueOf(s);
}
s = config.getConfig(KEY_LASTSTATEUPDATETIME);
if (s != null) {
this.lastStateUpdateTime = Long.valueOf(s);
}
s = config.getConfig(KEY_LAST_LOST_QUORUM_TIME);
if (s != null) {
lastLostQuorumTime = Long.valueOf(s);
}
s = config.getConfig(KEY_LASTSTATE);
if (s != null) {
lastState = SiteState.valueOf(config.getConfig(KEY_LASTSTATE));
}
s = config.getConfig(KEY_SITE_STATE);
if (s != null) {
state = SiteState.valueOf(config.getConfig(KEY_SITE_STATE));
}
s = config.getConfig(KEY_NODECOUNT);
if (s != null) {
nodeCount = Integer.valueOf(s);
}
String addrs = config.getConfig(KEY_NODESADDR);
if (!StringUtil.isBlank(addrs)) {
int i = 1;
for (String addr : addrs.split(",")) {
hostIPv4AddressMap.put(String.format("node%d", i++), addr);
}
}
String addr6s = config.getConfig(KEY_NODESADDR6);
if (!StringUtil.isBlank(addr6s)) {
int i = 1;
for (String addr : addr6s.split(",")) {
hostIPv6AddressMap.put(String.format("node%d", i++), addr);
}
}
} catch (Exception ex) {
throw new IllegalArgumentException("Unrecognized configuration data for Site", ex);
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Site [uuid=");
builder.append(uuid);
builder.append(", vdc=");
builder.append(vdcShortId);
builder.append(", name=");
builder.append(name);
builder.append(", vip=");
builder.append(vip);
builder.append(", state=");
builder.append(state);
builder.append(", description=");
builder.append(description);
builder.append(", hostIPv4AddressMap=");
builder.append(hostIPv4AddressMap);
builder.append(", hostIPv6AddressMap=");
builder.append(hostIPv6AddressMap);
builder.append(", standbyShortId=");
builder.append(siteShortId);
builder.append(", creationTime=");
builder.append(creationTime);
builder.append("]");
return builder.toString();
}
/**
* @return human-readable abstract of this site, only contains site name/vip/uuid
* The String returned by this method should only be used in display situation (e.g. log or audit log)
*/
public String toBriefString() {
StringBuilder builder = new StringBuilder();
builder.append("[name=").append(name);
builder.append(", vip=").append(vip);
builder.append(", uuid=").append(uuid).append("]");
return builder.toString();
}
public boolean isUsingIpv4() {
if (StringUtil.isBlank(vip) || PropertyConstants.IPV4_ADDR_DEFAULT.equals(vip)) {
return false;
}
return true;
}
public String getVipEndPoint() {
if (isUsingIpv4()) {
return vip;
} else {
return "[" + vip6 + "]";
}
}
}