/*************************************************************************** * Copyright (c) 2012-2014 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.placement.entity; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import com.vmware.bdd.apitypes.ClusterCreate; import com.vmware.bdd.apitypes.NodeGroupCreate; import com.vmware.bdd.apitypes.PlacementPolicy.GroupRacks; import com.vmware.bdd.placement.entity.AbstractDatacenter.AbstractCluster; import com.vmware.bdd.spectypes.VcCluster; import com.vmware.bdd.utils.AuAssert; /** * a virtual group combines node groups that both have the instance_per_host * constraint and are strictly associated (should stay on the same set of hosts) * * @author tli * */ public class VirtualGroup implements Comparable<VirtualGroup> { private ClusterCreate cluster; private List<NodeGroupCreate> nodeGroups; private List<VirtualNode> vNodes; // at least one node group in this virtual group is referenced by others // which means it should be placed first private boolean referred; private String referToGroup; // strict associated to another group? private Boolean strictAssociated; public VirtualGroup(ClusterCreate cluster) { super(); this.cluster = cluster; this.nodeGroups = new ArrayList<NodeGroupCreate>(); this.vNodes = new ArrayList<VirtualNode>(); this.referred = false; } public ClusterCreate getCluster() { return cluster; } public void setCluster(ClusterCreate cluster) { this.cluster = cluster; } public void addNodeGroup(NodeGroupCreate nodeGroup) { nodeGroups.add(nodeGroup); } public List<NodeGroupCreate> getNodeGroups() { return nodeGroups; } public void setNodeGroups(List<NodeGroupCreate> nodeGroups) { this.nodeGroups = nodeGroups; } public void addVNode(VirtualNode vNode) { vNodes.add(vNode); } public void addVNodes(List<VirtualNode> vNodes) { vNodes.addAll(vNodes); } public List<VirtualNode> getvNodes() { return vNodes; } public void setvNodes(List<VirtualNode> vNodes) { this.vNodes = vNodes; } public boolean isReferred() { return referred; } public void setReferred(boolean referred) { this.referred = referred; } public String getReferToGroup() { return referToGroup; } public void setReferToGroup(String referToGroup) { this.referToGroup = referToGroup; } public boolean isStrictAssociated() { return strictAssociated == null ? false : strictAssociated; } public void setStrictAssociated(boolean strictAssociated) { this.strictAssociated = strictAssociated; } /** * get joint abstract cluster all node groups inside this virtual group * * @return */ public List<AbstractCluster> getJointAbstractClusters() { Set<String> sharedVcClusterNames = null; // get shared vc cluster name between all node groups for (NodeGroupCreate nodeGroup : nodeGroups) { Set<String> vcClusterNameSet = new HashSet<String>(); for (VcCluster vcCluster : nodeGroup.getVcClusters(cluster)) { vcClusterNameSet.add(vcCluster.getName()); } if (sharedVcClusterNames == null) { sharedVcClusterNames = vcClusterNameSet; } else { sharedVcClusterNames.retainAll(vcClusterNameSet); } } if (sharedVcClusterNames == null || sharedVcClusterNames.size() == 0) { return null; } List<AbstractCluster> clusters = new ArrayList<AbstractCluster>(); // transform (cluster name <-> rp name list) map to AbsractCluster object list for (String name : sharedVcClusterNames) { clusters.add(new AbstractCluster(name)); } return clusters; } public int getTotalStorage() { int total = 0; for (VirtualNode node : this.vNodes) { total += node.getStorage(); } return total; } public GroupRacks getGroupRacks() { /* * basic rule: if group A is strictly associated with group B, then A should follow * B's rack policy */ NodeGroupCreate primary = getPrimaryGroup(); if (primary.getPlacementPolicies() != null) { return primary.getPlacementPolicies().getGroupRacks(); } else { return null; } } /** * if any node group inside this vGroup is strictly associated with another * node group, return that group. Otherwise, return itself. * * This method is used in Rack policy process * * @return */ public NodeGroupCreate getPrimaryGroup() { /* * mixed with multiple node groups, there must be a group that is strictly * associated by others. */ if (this.nodeGroups.size() > 1) { for (NodeGroupCreate nodeGroup : this.nodeGroups) { if (nodeGroup.getReferredGroup() == null) { // return the strictly associated group AuAssert.check(nodeGroup.getPlacementPolicies() != null); return nodeGroup; } } } /* * the rack policy in the slave node groups will be override by the primary group, * i.e., the group they strictly associated with. */ if (this.referToGroup != null && Boolean.TRUE.equals(this.strictAssociated)) { return cluster.getNodeGroup(referToGroup); } return this.nodeGroups.get(0); } public boolean hasInstancePerHostPolicy() { if (nodeGroups.get(0).getPlacementPolicies() != null && nodeGroups.get(0).getPlacementPolicies().getInstancePerHost() != null) return true; return false; } @Override public int compareTo(VirtualGroup o) { if (this.getTotalStorage() > o.getTotalStorage()) return 1; else if (this.getTotalStorage() == o.getTotalStorage()) return -1; else return 0; } public List<String> getNodeGroupNames() { List<String> nodeGroupNames = new ArrayList<String>(nodeGroups.size()); for (NodeGroupCreate nodeGroup : nodeGroups) { nodeGroupNames.add(nodeGroup.getName()); } return nodeGroupNames; } }