/*************************************************************************** * Copyright (c) 2012-2015 VMware, Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ***************************************************************************/ package com.vmware.bdd.entity; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; 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.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OrderBy; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import com.vmware.bdd.apitypes.*; import org.hibernate.annotations.Type; import com.google.gson.Gson; import com.vmware.bdd.apitypes.Datastore.DatastoreType; import com.vmware.bdd.apitypes.PlacementPolicy.GroupAssociation; import com.vmware.bdd.apitypes.PlacementPolicy.GroupRacks; import com.vmware.bdd.utils.AuAssert; /** * Node Group Entity: node group info * */ @Entity @SequenceGenerator(name = "IdSequence", sequenceName = "node_group_seq", allocationSize = 1) @Table(name = "node_group") public class NodeGroupEntity extends EntityBase { @Column(name = "name", nullable = false) private String name; @Column(name = "defined_instance_num", nullable = false) private int defineInstanceNum; @Column(name = "cpu") private int cpuNum; // MB @Column(name = "memory") private int memorySize; @Column(name = "reservedcpu_ratio") private Float reservedCpu_ratio; @Column(name = "reservedmem_ratio") private Float reservedMem_ratio; @Enumerated(EnumType.STRING) @Column(name = "latencysensitivity") private LatencyPriority latencySensitivity; @Column(name = "swap_ratio") private Float swapRatio = 1F; @Enumerated(EnumType.STRING) @Column(name = "storage_type") private DatastoreType storageType; // GB @Column(name = "storage_size") private int storageSize; @Column(name = "disk_number") private Integer diskNum = 0; @Column(name = "is_share_datastore") private Boolean shareDatastore = true; /* * check whether the node group is under provisioning, if the value is false or null, * node group can't do any operation about expand */ @Column(name = "is_provisioning") private Boolean isProvisioning; @ManyToOne @JoinColumn(name = "cluster_id") private ClusterEntity cluster; @OneToMany(mappedBy = "nodeGroup", cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OrderBy("id") private Set<NodeEntity> nodes; /* * cluster definition field. VCResourcePool inside this array may not be used * by this node group, so we should avoid setting up the ManyToMany mapping. * JSON encoded VCResourcePoolEntity name array */ @Column(name = "vc_rp_names") @Type(type = "text") private String vcRpNames; /* * cluster definition field. VCDataStores inside this array may not be used * by this node group, so we should avoid setting up the ManyToMany mapping. * JSON encoded VCDataStoreEntity name array */ // datastore for data disks @Column(name = "vc_datastore_names") @Type(type = "text") private String vcDatastoreNames; @Column(name = "dd_datastore_names") @Type(type = "text") private String ddDatastoreNames; // datastores for system|image disk @Column(name = "sd_datastore_names") @Type(type = "text") private String sdDatastoreNames; @Column(name = "roles") private String roles; // JSON string @Column(name = "node_type") private InstanceType nodeType; @Column(name = "ha_flag") private String haFlag; @Column(name = "configuration") @Type(type = "text") private String hadoopConfig; @Column(name = "instance_per_host") private Integer instancePerHost; @OneToMany(mappedBy = "nodeGroup", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private Set<NodeGroupAssociation> groupAssociations; @Column(name = "group_racks") @Type(type = "text") private String groupRacks; @Column(name = "vm_folder_path") private String vmFolderPath; public NodeGroupEntity() { } public NodeGroupEntity(String name, int defineInstanceNum, int cpuNum, int memorySize, Float swapRatio, DatastoreType storageType, int storageSize) { super(); this.name = name; this.defineInstanceNum = defineInstanceNum; this.cpuNum = cpuNum; this.memorySize = memorySize; this.swapRatio = swapRatio; this.storageType = storageType; this.storageSize = storageSize; } public String getHadoopConfig() { return hadoopConfig; } public void setHadoopConfig(String hadoopConfig) { this.hadoopConfig = hadoopConfig; } public String getHaFlag() { return haFlag; } public void setHaFlag(String haFlag) { this.haFlag = haFlag; } public InstanceType getNodeType() { return nodeType; } public void setNodeType(InstanceType nodeType) { this.nodeType = nodeType; } public NodeGroupEntity(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getDefineInstanceNum() { return defineInstanceNum; } public void setDefineInstanceNum(int defineInstanceNum) { this.defineInstanceNum = defineInstanceNum; } public int getCpuNum() { return cpuNum; } public void setCpuNum(int cpuNum) { this.cpuNum = cpuNum; } public int getMemorySize() { return memorySize; } public void setMemorySize(int memorySize) { this.memorySize = memorySize; } public Float getSwapRatio() { return swapRatio; } public void setSwapRatio(Float swapRatio) { this.swapRatio = swapRatio; } public DatastoreType getStorageType() { return storageType; } public void setStorageType(DatastoreType storageType) { this.storageType = storageType; } public int getStorageSize() { return storageSize; } public void setStorageSize(int storageSize) { this.storageSize = storageSize; } public Set<NodeEntity> getNodes() { return nodes; } public void setNodes(Set<NodeEntity> nodes) { this.nodes = nodes; } public ClusterEntity getCluster() { return cluster; } public void setCluster(ClusterEntity cluster) { this.cluster = cluster; } public String getVcRpNames() { return this.vcRpNames; } @SuppressWarnings("unchecked") public List<String> getVcRpNameList() { return (new Gson()).fromJson(vcRpNames, (new ArrayList<String>()).getClass()); } public void setVcRpNameList(List<String> vcRpNameList) { this.vcRpNames = (new Gson()).toJson(vcRpNameList); } public String getVcDatastoreNames() { return vcDatastoreNames; } @SuppressWarnings("unchecked") public List<String> getVcDatastoreNameList() { return (new Gson()).fromJson(vcDatastoreNames, (new ArrayList<String>()).getClass()); } public void setVcDatastoreNameList(List<String> vcDatastoreNameList) { this.vcDatastoreNames = (new Gson()).toJson(vcDatastoreNameList); } public String getDdDatastoreNames() { return this.ddDatastoreNames; } @SuppressWarnings("unchecked") public List<String> getDdDatastoreNameList() { return (new Gson()).fromJson(ddDatastoreNames, (new ArrayList<String>()).getClass()); } public void setDdDatastoreNameList(List<String> ddDatastoreNameList) { this.ddDatastoreNames = (new Gson()).toJson(ddDatastoreNameList); } public String getSdDatastoreNames() { return sdDatastoreNames; } @SuppressWarnings("unchecked") public List<String> getSdDatastoreNameList() { return (new Gson()).fromJson(sdDatastoreNames, (new ArrayList<String>()).getClass()); } public void setSdDatastoreNameList(List<String> sdDatastoreNameList) { this.sdDatastoreNames = (new Gson()).toJson(sdDatastoreNameList); } public String getRoles() { return roles; } public void setRoles(String roles) { this.roles = roles; } public Integer getInstancePerHost() { return instancePerHost; } public void setInstancePerHost(Integer instancePerHost) { this.instancePerHost = instancePerHost; } public Set<NodeGroupAssociation> getGroupAssociations() { return groupAssociations; } public void setGroupAssociations(Set<NodeGroupAssociation> groupAssociations) { this.groupAssociations = groupAssociations; } public String getGroupRacks() { return groupRacks; } public void setGroupRacks(String groupRacks) { this.groupRacks = groupRacks; } public String getVmFolderPath() { return vmFolderPath; } public void setVmFolderPath(String vmFolderPath) { this.vmFolderPath = vmFolderPath; } public void setVmFolderPath(ClusterEntity cluster) { this.vmFolderPath = cluster.getRootFolder() + "/" + this.name; } @SuppressWarnings("unchecked") public List<String> getRoleNameList() { return (new Gson()).fromJson(this.roles, (new ArrayList<String>()).getClass()); } public int getRealInstanceNum() { return nodes.size(); } public int getRealInstanceNum(boolean ignoreObsolete) { if (!ignoreObsolete) { return nodes.size(); } else { int num = 0; for (NodeEntity node : nodes) { if (node.isObsoleteNode()) { continue; } num ++; } return num; } } public Set<VcResourcePoolEntity> getUsedVcResourcePools() { HashSet<VcResourcePoolEntity> rps = new HashSet<VcResourcePoolEntity>(); for (NodeEntity node : nodes) { if (node.getVcRp() != null) { rps.add(node.getVcRp()); } } return rps; } public Set<String> getUsedVcDatastores() { Set<String> datastores = new HashSet<String>(); for (NodeEntity node : nodes) { List<String> vcDss = node.getDatastoreNameList(); if (vcDss != null) { datastores.addAll(vcDss); } } return datastores; } public LatencyPriority getLatencySensitivity() { return latencySensitivity; } public void setLatencySensitivity(LatencyPriority latencySensitivity) { this.latencySensitivity = latencySensitivity; } public Float getReservedCpu_ratio() { return reservedCpu_ratio; } public void setReservedCpu_ratio(Float reservedCpu_ratio) { this.reservedCpu_ratio = reservedCpu_ratio; } public Float getReservedMem_ratio() { return reservedMem_ratio; } public void setReservedMem_ratio(Float reservedMem_ratio) { this.reservedMem_ratio = reservedMem_ratio; } // this method should be called inside a transaction public NodeGroupRead toNodeGroupRead(boolean withNodesList, boolean ignoreObsoleteNode) { NodeGroupRead nodeGroupRead = new NodeGroupRead(); nodeGroupRead.setName(this.name); nodeGroupRead.setCpuNum(this.cpuNum); nodeGroupRead.setMemCapacityMB(this.memorySize); nodeGroupRead.setSwapRatio(this.swapRatio); nodeGroupRead.setInstanceNum(this.getRealInstanceNum(ignoreObsoleteNode)); Gson gson = new Gson(); @SuppressWarnings("unchecked") List<String> groupRoles = gson.fromJson(roles, List.class); nodeGroupRead.setRoles(groupRoles); StorageRead storage = new StorageRead(); storage.setType(this.storageType.toString()); storage.setSizeGB(this.storageSize); storage.setDiskNum(this.diskNum); storage.setShareDatastore(this.shareDatastore); // set dsNames/dsNames4Data/dsNames4System List<String> datastoreNameList = getVcDatastoreNameList(); if (datastoreNameList != null && !datastoreNameList.isEmpty()) storage.setDsNames(datastoreNameList); if (getSdDatastoreNameList() != null && !getSdDatastoreNameList().isEmpty()) storage.setDsNames4System(getSdDatastoreNameList()); if (getDdDatastoreNameList() != null && !getDdDatastoreNameList().isEmpty()) storage.setDsNames4Data(getDdDatastoreNameList()); nodeGroupRead.setStorage(storage); if(withNodesList) { List<NodeRead> nodeList = new ArrayList<NodeRead>(); for (NodeEntity node : this.nodes) { if (ignoreObsoleteNode && (node.isObsoleteNode() || node.isDisconnected())) { continue; } nodeList.add(node.toNodeRead(true)); } nodeGroupRead.setInstances(nodeList); } List<GroupAssociation> associations = new ArrayList<GroupAssociation>(); for (NodeGroupAssociation relation : groupAssociations) { GroupAssociation association = new GroupAssociation(); association.setReference(relation.getReferencedGroup()); association.setType(relation.getAssociationType()); associations.add(association); } PlacementPolicy policy = new PlacementPolicy(); policy.setInstancePerHost(instancePerHost); policy.setGroupAssociations(associations); policy.setGroupRacks(new Gson().fromJson(groupRacks, GroupRacks.class)); nodeGroupRead.setPlacementPolicies(policy); return nodeGroupRead; } @Override public int hashCode() { AuAssert.check(this.name != null, "id = " + this.id + " memory = " + this.getMemorySize()); return this.name.hashCode(); } @Override public boolean equals(Object nodeGroup) { AuAssert.check(this.name != null, "id = " + this.id + " memory = " + this.getMemorySize()); if (!(nodeGroup instanceof NodeGroupEntity)) return false; NodeGroupEntity group = (NodeGroupEntity) nodeGroup; if (this.cluster != null && group.getCluster() != null) { return this.cluster.getName().equals(group.getCluster().getName()) && this.name.equals(group.getName()); } return this.name.equals(group.getName()); } public Integer getDiskNum() { return diskNum; } public void setDiskNum(Integer diskNum) { this.diskNum = diskNum; } public Boolean isShareDatastore() { return shareDatastore; } public void setShareDatastore(Boolean shareDatastore) { this.shareDatastore = shareDatastore; } public Boolean getIsProvisioning() { return isProvisioning; } public void setIsProvisioning(Boolean isProvisioning) { this.isProvisioning = isProvisioning; } }