/***************************************************************************
* Copyright (c) 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.aurora.vc;
import com.vmware.aurora.exception.VcException;
import com.vmware.aurora.util.AuAssert;
import com.vmware.aurora.vc.vcservice.VcContext;
import com.vmware.vim.binding.vim.ClusterComputeResource;
import com.vmware.vim.binding.vim.ComputeResource;
import com.vmware.vim.binding.vim.Datacenter;
import com.vmware.vim.binding.vim.HostSystem;
import com.vmware.vim.binding.vim.cluster.ConfigInfoEx;
import com.vmware.vim.binding.vim.cluster.ConfigSpecEx;
import com.vmware.vim.binding.vim.cluster.DasVmConfigInfo;
import com.vmware.vim.binding.vim.host.ConnectInfo;
import com.vmware.vim.binding.vmodl.ManagedObject;
import com.vmware.vim.binding.vmodl.ManagedObjectReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/**
* Refactored by xiaoliangl on 7/16/15.
*/
@SuppressWarnings("serial")
class VcClusterImpl extends VcObjectImpl implements VcCluster {
private ComputeResource.Summary summary;
private String name;
// either a folder or datacenter
private ManagedObjectReference parent;
private ManagedObjectReference[] host;
private ManagedObjectReference[] network;
private ManagedObjectReference[] datastore;
private ManagedObjectReference resourcePool;
private List<ManagedObjectReference> sharedNetwork;
private List<ManagedObjectReference> sharedDatastore;
private VcClusterConfig config;
private List<String> haDrsIncompatReasonsForRBQual;
private List<String> haDrsIncompatReasonsForAlert;
// XXX : TODO - move this field to VcClusterConfig
private transient DasVmConfigInfo[] vmConfigInfo = null;
public ManagedObjectReference[] getHostMoRefs() {
return host;
}
@Override
public ManagedObjectReference[] getNetworkMoRefs() {
return network;
}
@Override
public ManagedObjectReference[] getDataStoreMoRefs() {
return datastore;
}
/**
* Sync request to update networks, datastores and/or RPs.
*/
protected static class SyncRequest extends VcInventory.SyncRequest {
SyncRequest(ManagedObjectReference moRef,
VcDatacenterImpl.SyncRequest parent) {
super(moRef, parent);
}
@Override
protected void syncChildObjects(VcObject obj) {
if (obj instanceof VcClusterImpl) {
VcClusterImpl cluster = (VcClusterImpl) obj;
if (syncSet.contains(VcObjectType.VC_NETWORK)) {
for (ManagedObjectReference net : cluster.network) {
VcCache.loadAsync(net);
}
}
if (syncSet.contains(VcObjectType.VC_DATASTORE)) {
for (ManagedObjectReference ds : cluster.datastore) {
VcCache.loadAsync(ds);
}
}
if (syncSet.contains(VcObjectType.VC_RP)) {
add(new VcResourcePoolImpl.SyncRequest(cluster.resourcePool,
this));
}
if (syncSet.contains(VcObjectType.VC_HOST)) {
for (ManagedObjectReference h : cluster.host) {
VcCache.loadAsync(h);
}
}
}
}
}
protected VcClusterImpl(ClusterComputeResource cluster) throws Exception {
super(cluster);
update(cluster);
}
private void updateRP(ManagedObjectReference rp) {
if (!rp.equals(resourcePool)) {
if (resourcePool != null) {
VcCache.loadAsync(resourcePool);
}
resourcePool = rp;
VcCache.loadAsync(rp);
}
}
@Override
protected void update(ManagedObject mo) throws Exception {
AuAssert.check(this.moRef.equals(mo._getRef()));
ClusterComputeResource cluster = (ClusterComputeResource) mo;
name = cluster.getName();
summary = checkReady(cluster.getSummary());
parent = checkReady(cluster.getParent());
host = checkReady(cluster.getHost());
network = checkReady(cluster.getNetwork());
datastore = checkReady(cluster.getDatastore());
sharedNetwork = getSharedNetworkInt();
sharedDatastore = getSharedDatastoreInt();
ConfigInfoEx configEx =
(ConfigInfoEx) checkReady(cluster.getConfigurationEx());
config = VcClusterConfig.create(configEx);
// Update the transient dasVmConfigInfo
vmConfigInfo = configEx.getDasVmConfig();
haDrsIncompatReasonsForRBQual =
VcClusterConfig.skipHADRSCheck() ? new ArrayList<String>() : config
.getHADRSIncompatReasons(false); // Lenient check for a minimal set of config
haDrsIncompatReasonsForAlert =
VcClusterConfig.skipHADRSCheck() ? new ArrayList<String>() : config
.getHADRSIncompatReasons(true); // Strict check, alert on each config problem
updateRP(checkReady(cluster.getResourcePool()));
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getName()
*/
@Override
public String getName() {
return MoUtil.fromURLString(name);
}
@Override
public String toString() {
return String.format("CLUSTER[%s](cpu=%d,mem=%d,#host=%d)", name,
summary.getTotalCpu(), summary.getTotalMemory(), host.length);
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getDatacenter()
*/
@Override
public VcDatacenter getDatacenter() {
return VcCache.get(MoUtil.getAncestorMoRef(parent, Datacenter.class));
}
/*
* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getHosts()
*/
@Override
public List<VcHost> getHosts() throws Exception {
List<VcHost> results = new ArrayList<VcHost>();
for (ManagedObjectReference ref : host) {
VcHost h = VcCache.get(ref);
results.add(h);
}
return results;
}
private List<ManagedObjectReference> getSharedNetworkInt() throws Exception {
List<HostSystem> hostList = MoUtil.getManagedObjects(host);
List<ManagedObjectReference> results =
new ArrayList<ManagedObjectReference>();
ManagedObjectReference[] candidateList = null;
HashMap<ManagedObjectReference, Integer> map =
new HashMap<ManagedObjectReference, Integer>();
if (hostList.size() == 0) {
return results;
}
for (HostSystem h : hostList) {
ManagedObjectReference[] netMorefs = h.getNetwork();
if (candidateList == null) {
candidateList = netMorefs;
}
for (ManagedObjectReference mo : netMorefs) {
Integer count = map.get(mo);
if (count != null) {
map.put(mo, count + 1);
} else {
map.put(mo, Integer.valueOf(1));
}
}
}
// collect those in the map with as many counts as the number of hosts
if (candidateList != null) {
for (ManagedObjectReference mo : candidateList) {
if (map.get(mo).equals(hostList.size())) {
results.add(mo);
}
}
}
return results;
}
@Override
public List<VcNetwork> getSharedNetworks() {
List<VcNetwork> results = new ArrayList<VcNetwork>();
for (ManagedObjectReference ref : sharedNetwork) {
VcNetwork net = VcCache.get(ref);
if (!net.isUplink()) {
results.add(net);
}
}
return results;
}
@Override
public List<VcNetwork> getAllNetworks() {
List<VcNetwork> results = new ArrayList<VcNetwork>();
for (ManagedObjectReference ref : network) {
VcNetwork net = VcCache.get(ref);
if (!net.isUplink()) {
results.add(net);
}
}
return results;
}
@Override
public VcNetwork getNetwork(String name) {
String urlName = MoUtil.toURLString(name);
for (ManagedObjectReference ref : network) {
VcNetwork net = VcCache.get(ref);
if (urlName.equalsIgnoreCase(net.getName())) {
if (net.isUplink()) {
return null;
}
return net;
}
}
return null;
}
@Override
public VcNetwork getSharedNetwork(String name) {
String urlName = MoUtil.toURLString(name);
for (ManagedObjectReference ref : sharedNetwork) {
VcNetwork net = VcCache.get(ref);
if (urlName.equalsIgnoreCase(net.getName())) {
if (net.isUplink()) {
return null;
}
return net;
}
}
return null;
}
private List<ManagedObjectReference> getSharedDatastoreInt()
throws Exception {
AuAssert.check(VcContext.isInSession());
List<HostSystem> hostList = MoUtil.getManagedObjects(host);
List<ManagedObjectReference> results =
new ArrayList<ManagedObjectReference>();
ConnectInfo.DatastoreInfo[] candidateList = null;
HashMap<String, Integer> map = new HashMap<String, Integer>();
if (hostList.size() == 0) {
return results;
}
for (HostSystem h : hostList) {
ConnectInfo.DatastoreInfo[] info = h.queryConnectionInfo().getDatastore();
if (info == null)
continue;
if (candidateList == null) {
candidateList = info;
}
for (ConnectInfo.DatastoreInfo n : info) {
String name = n.getSummary().getName();
Integer count = map.get(name);
if (count != null) {
map.put(name, count + 1);
} else {
map.put(name, Integer.valueOf(1));
}
}
}
// collect those in the map with as many counts as the number of hosts
if (candidateList != null) {
for (ConnectInfo.DatastoreInfo n : candidateList) {
if (map.get(n.getSummary().getName()).equals(hostList.size())) {
results.add(n.getSummary().getDatastore());
}
}
}
return results;
}
@Override
public List<VcDatastore> getSharedDatastores() {
return VcCache.<VcDatastore> getPartialList(sharedDatastore, getMoRef());
}
@Override
public List<VcDatastore> getAllDatastores() {
return VcCache.<VcDatastore> getPartialList(Arrays.asList(datastore),
getMoRef());
}
@Override
public VcDatastore getDatastore(String name) {
String urlName = MoUtil.toURLString(name);
for (ManagedObjectReference ref : datastore) {
VcDatastore ds = VcCache.get(ref);
if (urlName.equalsIgnoreCase(ds.getName())) {
if (!ds.isAccessible()) {
return null;
}
return ds;
}
}
return null;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getRootRP()
*/
@Override
public VcResourcePool getRootRP() {
return VcCache.get(resourcePool);
}
private VcResourcePoolImpl getRootRPImpl() {
return VcCache.get(resourcePool);
}
@Override
public VcResourcePool searchRP(final String path) throws Exception {
try {
return getRootRPImpl().searchRP(path);
} catch (VcException e) {
if (!e.isINVALID_MOREF() && !e.isMOREF_NOTREADY()) {
throw e;
} else {
return null;
}
}
}
@Override
public List<VcResourcePool> getQualifiedRPs() throws Exception {
try {
return getRootRPImpl().getQualifiedRPs();
} catch (VcException e) {
if (!e.isINVALID_MOREF() && !e.isMOREF_NOTREADY()) {
throw e;
} else {
return new ArrayList<VcResourcePool>();
}
}
}
@Override
public List<VcResourcePool> getAllRPs() throws Exception {
try {
return getRootRPImpl().getAllRPs();
} catch (VcException e) {
if (!e.isINVALID_MOREF() && !e.isMOREF_NOTREADY()) {
throw e;
} else {
return new ArrayList<VcResourcePool>();
}
}
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getConfig()
*/
@Override
public VcClusterConfig getConfig() {
return config;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getHADRSIncompatReasonsForAlert()
*/
@Override
public List<String> getHADRSIncompatReasonsForAlert() {
return haDrsIncompatReasonsForAlert;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getHADRSIncompatReasonsForRBQual()
*/
@Override
public List<String> getHADRSIncompatReasonsForRBQual() {
return haDrsIncompatReasonsForRBQual;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#getVmConfigInfo()
*/
@Override
public DasVmConfigInfo[] getVmConfigInfo() {
return vmConfigInfo;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#reconfigure(com.vmware.vim.binding.vim.cluster.ConfigSpec, com.vmware.aurora.vc.IVcTaskCallback)
*/
@Override
public VcTask reconfigure(final ConfigSpecEx spec,
final IVcTaskCallback callback) throws Exception {
VcTask task = VcContext.getTaskMgr().execute(new VcTaskMgr.IVcTaskBody() {
public VcTask body() throws Exception {
final ClusterComputeResource cluster = getManagedObject();
return new VcTask(VcTask.TaskType.ReconfigCluster, cluster.reconfigureEx(
spec, true), callback);
}
});
return task;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcCluster#reconfigure(com.vmware.vim.binding.vim.cluster.ConfigSpec)
*/
@Override
public boolean reconfigure(final ConfigSpecEx spec) throws Exception {
VcTask task = reconfigure(spec, VcCache.getRefreshVcTaskCB(this));
task.waitForCompletion();
return task.taskCompleted();
}
@Override
public int getTotalCpu() {
if (summary == null) {
throw VcException.INIT_ERROR();
}
return summary.getTotalCpu();
}
@Override
public long getTotalMemory() {
if (summary == null) {
throw VcException.INIT_ERROR();
}
return summary.getTotalMemory();
}
@Override
public int getNumberOfHost() {
if (host == null) {
throw VcException.INIT_ERROR();
}
return host.length;
}
}