/******************************************************************************* * Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com> * This file is part of Gluster Management Console. * * Gluster 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 3 of the License, or (at your option) any later version. * * Gluster 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 this program. If not, see * <http://www.gnu.org/licenses/>. *******************************************************************************/ package org.gluster.storage.management.core.model; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import org.gluster.storage.management.core.constants.GlusterConstants; import org.gluster.storage.management.core.utils.GlusterCoreUtil; import org.gluster.storage.management.core.utils.StringUtil; @XmlRootElement public class Volume extends Entity { public enum VOLUME_STATUS { ONLINE, OFFLINE }; public enum VOLUME_TYPE { DISTRIBUTE, REPLICATE, DISTRIBUTED_REPLICATE, STRIPE, DISTRIBUTED_STRIPE }; public enum TRANSPORT_TYPE { ETHERNET, INFINIBAND }; public enum NAS_PROTOCOL { GLUSTERFS, NFS, CIFS }; public static final int DEFAULT_REPLICA_COUNT = 2; public static final int DEFAULT_STRIPE_COUNT = 4; public static final String OPTION_AUTH_ALLOW = "auth.allow"; public static final String OPTION_NFS_DISABLE = "nfs.disable"; private static final String[] VOLUME_TYPE_STR = new String[] { "Distribute", "Replicate", "Distributed Replicate", "Stripe", "Distributed Stripe" }; private static final String[] TRANSPORT_TYPE_STR = new String[] { "Ethernet", "Infiniband" }; private static final String[] STATUS_STR = new String[] { "Online", "Offline" }; private static final String[] NAS_PROTOCOL_STR = new String[] { "Gluster", "NFS", "CIFS" }; private VOLUME_TYPE volumeType; private TRANSPORT_TYPE transportType; private VOLUME_STATUS status; private int replicaCount; private int stripeCount; private VolumeOptions options = new VolumeOptions(); private List<Brick> bricks = new ArrayList<Brick>(); private List<String> cifsUsers; public Volume() { } // Only GlusterFS is enabled private Set<NAS_PROTOCOL> nasProtocols = new LinkedHashSet<NAS_PROTOCOL>(Arrays.asList(new NAS_PROTOCOL[] { NAS_PROTOCOL.GLUSTERFS })); public String getVolumeTypeStr() { return getVolumeTypeStr(getVolumeType()); } public static String getVolumeTypeStr(VOLUME_TYPE volumeType) { return VOLUME_TYPE_STR[volumeType.ordinal()]; } public static VOLUME_TYPE getVolumeTypeByStr(String volumeTypeStr) { return VOLUME_TYPE.valueOf(volumeTypeStr); } public static TRANSPORT_TYPE getTransportTypeByStr(String transportTypeStr) { return TRANSPORT_TYPE.valueOf(transportTypeStr); } public String getTransportTypeStr() { return TRANSPORT_TYPE_STR[getTransportType().ordinal()]; } public String getStatusStr() { return STATUS_STR[getStatus().ordinal()]; } public int getNumOfBricks() { return bricks.size(); } public VOLUME_TYPE getVolumeType() { return volumeType; } public void setVolumeType(VOLUME_TYPE volumeType) { this.volumeType = volumeType; // TODO find a way to get the replica / strip count if (volumeType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { setReplicaCount(0); setStripeCount(DEFAULT_STRIPE_COUNT); } else if (volumeType == VOLUME_TYPE.DISTRIBUTED_REPLICATE) { setReplicaCount(DEFAULT_REPLICA_COUNT); setStripeCount(0); } else { setReplicaCount(0); setStripeCount(0); } } public TRANSPORT_TYPE getTransportType() { return transportType; } public void setTransportType(TRANSPORT_TYPE transportType) { this.transportType = transportType; } public VOLUME_STATUS getStatus() { return status; } public int getReplicaCount() { return replicaCount; } public void setReplicaCount(int replicaCount) { this.replicaCount = replicaCount; } public int getStripeCount() { return stripeCount; } public void setStripeCount(int stripeCount) { this.stripeCount = stripeCount; } public void setStatus(VOLUME_STATUS status) { this.status = status; } @XmlElementWrapper(name = "nasProtocols") @XmlElement(name = "nasProtocol", type=NAS_PROTOCOL.class) public Set<NAS_PROTOCOL> getNASProtocols() { return nasProtocols; } public void setNASProtocols(Set<NAS_PROTOCOL> nasProtocols) { this.nasProtocols = nasProtocols; } public String getNASProtocolsStr() { String protocolsStr = ""; for (NAS_PROTOCOL protocol : nasProtocols) { String protocolStr = NAS_PROTOCOL_STR[protocol.ordinal()]; protocolsStr += (protocolsStr.isEmpty() ? protocolStr : ", " + protocolStr); } return protocolsStr; } @XmlTransient public String getAccessControlList() { return options.get(OPTION_AUTH_ALLOW); } public void setAccessControlList(String accessControlList) { setOption(OPTION_AUTH_ALLOW, accessControlList); } @XmlTransient public boolean isNfsEnabled() { String nfsDisabled = options.get(OPTION_NFS_DISABLE); if(nfsDisabled == null || nfsDisabled.equalsIgnoreCase(GlusterConstants.OFF)) { return true; } else { return false; } } @XmlElement(name="options") public VolumeOptions getOptions() { return options; } public void setOption(String key, String value) { options.put(key, value); } public void setOptions(VolumeOptions options) { this.options = options; } public void setOptions(LinkedHashMap<String, String> options) { List<VolumeOption> volumeOptions = new ArrayList<VolumeOption>(); for(Entry<String, String> entry : options.entrySet()) { volumeOptions.add(new VolumeOption(entry.getKey(), entry.getValue())); } this.options.setOptions(volumeOptions); } public void addBrick(Brick brick) { bricks.add(brick); } public void addBricks(Collection<Brick> bricks) { this.bricks.addAll(bricks); } public void setBricks(List<Brick> bricks) { this.bricks = bricks; } public void removeBrick(Brick brick) { bricks.remove(brick); } @XmlElementWrapper(name = "bricks") @XmlElement(name = "brick", type=Brick.class) public List<Brick> getBricks() { return bricks; } public void enableNFS() { nasProtocols.add(NAS_PROTOCOL.NFS); setOption(OPTION_NFS_DISABLE, GlusterConstants.OFF); } public void disableNFS() { nasProtocols.remove(NAS_PROTOCOL.NFS); setOption(OPTION_NFS_DISABLE, GlusterConstants.ON); } public void enableCifs() { if (!nasProtocols.contains(NAS_PROTOCOL.CIFS)) { nasProtocols.add(NAS_PROTOCOL.CIFS); } } public void disableCifs() { nasProtocols.remove(NAS_PROTOCOL.CIFS); } public boolean isCifsEnable() { return nasProtocols.contains(NAS_PROTOCOL.CIFS); } public void setCifsUsers(List<String> cifsUsers) { this.cifsUsers = cifsUsers; } public List<String> getCifsUsers() { return cifsUsers; } public Volume(String name, Entity parent, VOLUME_TYPE volumeType, TRANSPORT_TYPE transportType, VOLUME_STATUS status) { super(name, parent); setVolumeType(volumeType); setTransportType(transportType); setStatus(status); } /** * Filter matches if any of the properties name, volume type, transport type, status and number of disks contains * the filter string */ @Override public boolean filter(String filterString, boolean caseSensitive) { return StringUtil.filterString(getName() + getVolumeTypeStr() + getTransportTypeStr() + getStatusStr() + getNumOfBricks(), filterString, caseSensitive); } public List<String> getBrickDirectories() { List<String> brickDirectories = new ArrayList<String>(); for(Brick brick : getBricks()) { brickDirectories.add(brick.getQualifiedName()); } return brickDirectories; } @Override public boolean equals(Object obj) { if(!(obj instanceof Volume)) { return false; } Volume volume = (Volume)obj; if (!(getName().equals(volume.getName()) && getVolumeType() == volume.getVolumeType() && getTransportType() == volume.getTransportType() && getStatus() == volume.getStatus() && getReplicaCount() == volume.getReplicaCount() && getStripeCount() == volume.getStripeCount() && getOptions().equals(volume.getOptions()))) { return false; } for(NAS_PROTOCOL nasProtocol : getNASProtocols()) { if(!(volume.getNASProtocols().contains(nasProtocol))) { return false; } } List<Brick> oldBricks = getBricks(); List<Brick> newBricks = volume.getBricks(); if(oldBricks.size() != newBricks.size()) { return false; } if(!GlusterCoreUtil.getAddedEntities(oldBricks, newBricks, false).isEmpty()) { return false; } if(!GlusterCoreUtil.getAddedEntities(newBricks, oldBricks, false).isEmpty()) { return false; } Map<Brick, Brick> modifiedBricks = GlusterCoreUtil.getModifiedEntities(oldBricks, newBricks); if(modifiedBricks.size() > 0) { return false; } return true; } /** * Note: this method doesn't copy the bricks. Clients should write separate code to identify added/removed/modified * bricks and update the volume bricks appropriately. * * @param newVolume */ public void copyFrom(Volume newVolume) { setName(newVolume.getName()); setVolumeType(newVolume.getVolumeType()); setTransportType(newVolume.getTransportType()); setStatus(newVolume.getStatus()); setReplicaCount(newVolume.getReplicaCount()); setStripeCount(newVolume.getStripeCount()); setNASProtocols(newVolume.getNASProtocols()); setCifsUsers(newVolume.getCifsUsers()); getOptions().copyFrom(newVolume.getOptions()); } }