Package com.vmware.bdd.placement

Source Code of com.vmware.bdd.placement.PlacementService

/***************************************************************************
* 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;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.Pair;
import com.vmware.bdd.apitypes.ClusterCreate;
import com.vmware.bdd.apitypes.PlacementPolicy.GroupRacks.GroupRacksType;
import com.vmware.bdd.placement.entity.AbstractDatacenter.AbstractHost;
import com.vmware.bdd.placement.entity.BaseNode;
import com.vmware.bdd.placement.entity.VirtualGroup;
import com.vmware.bdd.placement.entity.VirtualNode;
import com.vmware.bdd.placement.exception.PlacementException;
import com.vmware.bdd.placement.interfaces.IContainer;
import com.vmware.bdd.placement.interfaces.IPlacementPlanner;
import com.vmware.bdd.placement.interfaces.IPlacementService;
import com.vmware.bdd.placement.util.PlacementUtil;
import com.vmware.bdd.spectypes.DiskSpec;
import com.vmware.bdd.utils.AuAssert;

/**
* supported placement policies are: instance_per_host, group association, rack
* association
*
* @author tli
*
*/
@Service
public class PlacementService implements IPlacementService {
   static final Logger logger = Logger.getLogger(PlacementService.class);

   private void placeVirtualGroup(IContainer container, ClusterCreate cluster,
         IPlacementPlanner planner, VirtualGroup vGroup,
         List<BaseNode> placedNodes, Map<String, List<String>> filteredHosts) {
      String targetRack = null;
      if (vGroup.getGroupRacks() != null
            && GroupRacksType.SAMERACK.equals(vGroup.getGroupRacks().getType())) {
         AuAssert.check(vGroup.getGroupRacks().getRacks() != null
               && vGroup.getGroupRacks().getRacks().length == 1);
         targetRack = vGroup.getGroupRacks().getRacks()[0];
      }

      // find out hosts filtered out by datastores
      if (filteredHosts.containsKey(PlacementUtil.NO_DATASTORE_HOSTS)) {
         filteredHosts.remove(PlacementUtil.NO_DATASTORE_HOSTS);
         filteredHosts.remove(PlacementUtil.NO_DATASTORE_HOSTS_NODE_GROUP);
      }
      List<String> dsFilteredOutHosts = new ArrayList<String>();
      if (vGroup.getvNodes().size() != 0) {
         List<String> noDatastoreHosts = container.getDsFilteredOutHosts(vGroup);
         if (null != noDatastoreHosts && !noDatastoreHosts.isEmpty()) {
            filteredHosts.put(PlacementUtil.NO_DATASTORE_HOSTS,
                  noDatastoreHosts);
            filteredHosts.put(PlacementUtil.NO_DATASTORE_HOSTS_NODE_GROUP,
                  vGroup.getNodeGroupNames());
         }
      }

      // place virtual node one by one
      for (VirtualNode vNode : vGroup.getvNodes()) {
         logger.info("placing the virtual node " + vNode.getBaseNodeNames());
         List<AbstractHost> candidates =
               container.getValidHosts(vNode, targetRack);

         if (candidates == null || candidates.size() == 0) {
            logger.error("cannot find candidate hosts from the container "
                  + "to place the virtual node " + vNode.getBaseNodeNames());
            throw PlacementException.OUT_OF_VC_HOST(PlacementUtil.getBaseNodeNames(vNode));
         }

         // select host
         AbstractHost host = planner.selectHost(vNode, candidates);

         if (host == null) {
            logger.error("cannot find a candidate from host lists "
                  + candidates + " for the virtual node "
                  + vNode.getBaseNodeNames());
            // TODO different exception for policy violation
            throw PlacementException.OUT_OF_VC_HOST(PlacementUtil.getBaseNodeNames(vNode));
         }

         // generate placement topology
         for (BaseNode baseNode : vNode.getBaseNodes()) {
            Pair<String, String> rpClusterPair =
                  planner.selectVcRp(baseNode, host);
            String rack = container.getRack(host);
            baseNode.place(rack, rpClusterPair.first, rpClusterPair.second,
                  host);
         }

         // allocate resource from container
         container.allocate(vNode, host);

         logger.info("placed the virtual node on host " + host);
         logger.info("detailed virtual node info is as below " + vNode);

         // done, add to the complete list
         placedNodes.addAll(vNode.getBaseNodes());
      }
   }

   private void placeVirtualGroupWithSnapshot(IContainer container,
         ClusterCreate cluster, IPlacementPlanner planner, VirtualGroup vGroup,
         List<BaseNode> placedNodes, Map<String, List<String>> filteredHosts) {
      // snap shot environment on placement exceptions
      try {
         placeVirtualGroup(container, cluster, planner, vGroup, placedNodes, filteredHosts);
      } catch (PlacementException e) {
         logger.error("Place cluster " + cluster.getName()
               + " failed. PlacementException: " + e.getMessage());
         snapShotPlacementEnv(container, cluster, placedNodes);
         throw PlacementException.PLACEMENT_ERROR(e, placedNodes, filteredHosts);
      }
   }

   private void snapShotPlacementEnv(IContainer container,
         ClusterCreate cluster, List<BaseNode> placedNodes) {
      Gson gson = new GsonBuilder().setPrettyPrinting().create();

      logger.info("the cluster spec is shown as follows");
      logger.info(gson.toJson(cluster));

      logger.info("The following nodes have been successfully placed");
      for (BaseNode node : placedNodes) {
         logger.info(node.getDetailDesc());
      }

      logger.info("The status of vc hosts after placement are shown as follows");
      for (AbstractHost host : container.getAllHosts()) {
         logger.info(gson.toJson(host));
      }
   }

   @Override
   public List<BaseNode> getPlacementPlan(IContainer container,
         ClusterCreate cluster, List<BaseNode> existedNodes, Map<String, List<String>> filteredHosts) {
      IPlacementPlanner planner = new PlacementPlanner();

      /*
       *  assert the getBadNodes method is called before this method and bad nodes
       *  have been removed
       *
       *  TODO: handle the case when nodes are vMotioned between host before a resize operation
       */
      List<BaseNode> badNodes = planner.getBadNodes(cluster, existedNodes);
      AuAssert.check(badNodes == null || badNodes.size() == 0);

      AuAssert.check(((Container) container).getTemplateNode() != null);

      planner.init(cluster, ((Container) container).getTemplateNode(),
            existedNodes, ((Container) container).getRackMap());

      /*
       * pre-process the cluster and split them into virtual groups, by
       * analyzing the instance_per_host and group association policy
       */
      List<VirtualGroup> vGroups = planner.getVirtualGroups(existedNodes);

      // place virtual groups that are referred by others at first
      List<VirtualGroup> referredGroups = new ArrayList<VirtualGroup>();
      List<VirtualGroup> normalGroups = new ArrayList<VirtualGroup>();
      for (VirtualGroup vGroup : vGroups) {
         if (vGroup.isReferred())
            referredGroups.add(vGroup);
         else
            normalGroups.add(vGroup);
      }

      // bin pack: place vGroups that have larger storage requirement first
      List<BaseNode> placedNodes = new ArrayList<BaseNode>();
      Collections.sort(referredGroups, Collections.reverseOrder());
      for (VirtualGroup vGroup : referredGroups) {
         placeVirtualGroupWithSnapshot(container, cluster, planner, vGroup,
               placedNodes, filteredHosts);
      }

      // bin pack: place vGroups that have larger storage requirement first
      Collections.sort(normalGroups, Collections.reverseOrder());
      for (VirtualGroup vGroup : normalGroups) {
         placeVirtualGroupWithSnapshot(container, cluster, planner, vGroup,
               placedNodes, filteredHosts);
      }

      // ensure the number of nodes is correct
      if (existedNodes != null && existedNodes.size() != 0)
         AuAssert.check(placedNodes.size() == cluster.totalInstances()
               - existedNodes.size());
      else
         AuAssert.check(placedNodes.size() == cluster.totalInstances());
      return placedNodes;
   }

   @Override
   public List<BaseNode> getBadNodes(ClusterCreate cluster,
         List<BaseNode> existedNodes) {
      // remove policy violated VMs
      IPlacementPlanner planner = new PlacementPlanner();
      return planner.getBadNodes(cluster, existedNodes);
   }

   @Override
   public List<DiskSpec> getReplacementDisks(IContainer container,
         ClusterCreate spec, String groupName, String nodeName,
         String targetHost, List<DiskSpec> badDisks,
         Map<String, Integer> dsUsage) {
      // TODO Auto-generated method stub
      return null;
   }
}
TOP

Related Classes of com.vmware.bdd.placement.PlacementService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.