/**
* Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
*/
package net.juniper.contrail.vcenter;
import java.io.*;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.URL;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Hashtable;
import java.util.Map;
import java.util.SortedMap;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.io.FileNotFoundException;
import com.vmware.vim25.VirtualMachineToolsRunningStatus;
import org.apache.log4j.Logger;
import com.google.common.base.Throwables;
import com.vmware.vim25.DVPortSetting;
import com.vmware.vim25.DVPortgroupConfigInfo;
import com.vmware.vim25.GuestInfo;
import com.vmware.vim25.GuestNicInfo;
import com.vmware.vim25.IpPool;
import com.vmware.vim25.NetIpConfigInfo;
import com.vmware.vim25.NetIpConfigInfoIpAddress;
import com.vmware.vim25.VMwareDVSPortSetting;
import com.vmware.vim25.VirtualDevice;
import com.vmware.vim25.VirtualDeviceBackingInfo;
import com.vmware.vim25.VirtualEthernetCard;
import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
import com.vmware.vim25.VirtualMachineConfigInfo;
import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec;
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanSpec;
import com.vmware.vim25.DistributedVirtualSwitchKeyedOpaqueBlob;
import com.vmware.vim25.VMwareDVSConfigInfo;
import com.vmware.vim25.VMwareDVSPvlanMapEntry;
import com.vmware.vim25.mo.Datacenter;
import com.vmware.vim25.mo.DistributedVirtualPortgroup;
import com.vmware.vim25.mo.Folder;
import com.vmware.vim25.mo.HostSystem;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.IpPoolManager;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.Network;
import com.vmware.vim25.mo.util.PropertyCollectorUtil;
import com.vmware.vim25.mo.ServiceInstance;
import com.vmware.vim25.mo.VirtualMachine;
import com.vmware.vim25.mo.VmwareDistributedVirtualSwitch;
import com.vmware.vim25.mo.ComputeResource;
public class VCenterDB {
private static final Logger s_logger =
Logger.getLogger(VCenterDB.class);
private static final String esxiToVRouterIpMapFile = "/etc/contrail/ESXiToVRouterIp.map";
protected final String contrailDvSwitchName;
public final String contrailDataCenterName;
private final String vcenterUrl;
private final String vcenterUsername;
private final String vcenterPassword;
private final String contrailIpFabricPgName;
final Mode mode;
private volatile ServiceInstance serviceInstance;
private volatile Folder rootFolder;
private volatile InventoryNavigator inventoryNavigator;
private volatile IpPoolManager ipPoolManager;
private volatile IpPool[] ipPools;
protected volatile Datacenter contrailDC;
protected volatile VmwareDistributedVirtualSwitch contrailDVS;
private volatile ConcurrentMap<String, Datacenter> datacenters;
private volatile ConcurrentMap<String, VmwareDistributedVirtualSwitch> dvswitches; // key is dvsName
private volatile ConcurrentMap<String, VMwareDVSPvlanMapEntry[]> dvsPvlanMap; // key is dvsName
public volatile Map<String, String> esxiToVRouterIpMap;
public static final String OK = "Ok";
private String operationalStatus = OK;
private Calendar lastTimeSeenAlive;
public String getOperationalStatus() {
return operationalStatus;
}
public VCenterDB(String vcenterUrl, String vcenterUsername,
String vcenterPassword, String contrailDcName,
String contrailDvsName, String ipFabricPgName, Mode mode) {
this.vcenterUrl = vcenterUrl;
this.vcenterUsername = vcenterUsername;
this.vcenterPassword = vcenterPassword;
this.contrailDataCenterName = contrailDcName;
this.contrailDvSwitchName = contrailDvsName;
this.contrailIpFabricPgName = ipFabricPgName;
this.mode = mode;
s_logger.info("VCenterDB(" + contrailDvsName + ", " + ipFabricPgName + ")");
datacenters = new ConcurrentHashMap<String, Datacenter>();
dvswitches = new ConcurrentHashMap<String, VmwareDistributedVirtualSwitch>();
dvsPvlanMap = new ConcurrentHashMap<String, VMwareDVSPvlanMapEntry[]>();
// Create ESXi host to vRouterVM Ip address map
buildEsxiToVRouterIpMap();
}
private boolean initData() {
if (!isAlive()) {
return false;
}
datacenters.clear();
dvswitches.clear();
dvsPvlanMap.clear();
rootFolder = null;
rootFolder = serviceInstance.getRootFolder();
if (rootFolder == null) {
operationalStatus = "Failed to get rootfolder for vCenter ";
s_logger.error(operationalStatus);
return false;
}
s_logger.info("Got rootfolder for vCenter ");
inventoryNavigator = null;
inventoryNavigator = new InventoryNavigator(rootFolder);
if (inventoryNavigator == null) {
operationalStatus = "Failed to get InventoryNavigator for vCenter ";
s_logger.error(operationalStatus);
return false;
}
s_logger.info("Got InventoryNavigator for vCenter ");
ipPoolManager = null;
ipPoolManager = serviceInstance.getIpPoolManager();
if (ipPoolManager == null) {
operationalStatus = "Failed to get ipPoolManager for vCenter ";
s_logger.error(operationalStatus);
return false;
}
s_logger.info("Got ipPoolManager for datacenter " + contrailDataCenterName);
contrailDC = null;
try {
contrailDC = getVmwareDatacenter(contrailDataCenterName);
} catch (RemoteException e) {
}
if (contrailDC == null) {
operationalStatus = "Failed to find " + contrailDataCenterName
+ " DC on vCenter ";
s_logger.error(operationalStatus);
return false;
}
s_logger.info("Found " + contrailDataCenterName + " DC on vCenter ");
Folder hostsFolder = null;
try {
hostsFolder = contrailDC.getHostFolder();
} catch (RemoteException e) {
}
if (hostsFolder == null) {
operationalStatus = "Failed to find hostFolder on datacenter " + contrailDataCenterName;
s_logger.error(operationalStatus);
return false;
}
contrailDVS = null;
try {
contrailDVS = getVmwareDvs(contrailDvSwitchName, contrailDC, contrailDataCenterName);
} catch (RemoteException e) {
}
if (contrailDVS == null) {
operationalStatus = "Failed to find " + contrailDvSwitchName +
" DVSwitch on vCenter";
s_logger.error(operationalStatus);
return false;
}
s_logger.info("Found " + contrailDvSwitchName + " DVSwitch on vCenter ");
try {
getDvsPvlanMap(contrailDvSwitchName, contrailDC, contrailDataCenterName);
} catch (RemoteException e) {
s_logger.error(this + "Private vlan not configured on dvSwitch: " + contrailDvSwitchName +
" Datacenter: " + contrailDataCenterName);
}
// All well on vCenter front.
operationalStatus = OK;
return true;
}
public boolean connect(int timeout) {
datacenters.clear();
dvswitches.clear();
dvsPvlanMap.clear();
while(!createServiceInstance(timeout)) {
try{
Thread.sleep(5000);
} catch (InterruptedException e) {
s_logger.error(Throwables.getStackTraceAsString(e));
return false;
}
}
while(!initData() ) {
try{
Thread.sleep(5000);
} catch (InterruptedException e) {
s_logger.error(Throwables.getStackTraceAsString(e));
return false;
}
}
return true;
}
private boolean createServiceInstance(int timeout) {
try {
serviceInstance = null;
s_logger.info("Trying to Connect to vCenter Server : " + "("
+ vcenterUrl + "," + vcenterUsername + ")");
serviceInstance = new ServiceInstance(new URL(vcenterUrl),
vcenterUsername, vcenterPassword, true);
if (serviceInstance == null) {
operationalStatus = "Failed to connect to vCenter Server : " + "("
+ vcenterUrl + "," + vcenterUsername + ","
+ vcenterPassword + ")" + "Retrying after 5 secs";
s_logger.error(operationalStatus);
return false;
}
setConnectTimeout(timeout);
s_logger.info("Connected to vCenter Server : " + "("
+ vcenterUrl + "," + vcenterUsername + ","
+ vcenterPassword + ")");
operationalStatus = OK;
return true;
} catch (MalformedURLException e) {
operationalStatus = "Re-Connect unsuccessful: " + e.getMessage();
s_logger.error(operationalStatus);
return false;
} catch (RemoteException e) {
operationalStatus = "Re-Connect unsuccessful: " + e.getMessage();
s_logger.error(operationalStatus);
return false;
} catch (Exception e) {
operationalStatus = "Error while connecting to vcenter: " + e.getMessage();
s_logger.error(operationalStatus);
s_logger.error(Throwables.getStackTraceAsString(e));
return false;
}
}
public ServiceInstance getServiceInstance() {
return serviceInstance;
}
private boolean buildEsxiToVRouterIpMap() {
esxiToVRouterIpMap = new HashMap<String, String>();
try {
File file = new File("/etc/contrail/ESXiToVRouterIp.map");
Scanner input = new Scanner(file);
while(input.hasNext()) {
String nextLine = input.nextLine();
String[] part = nextLine.split(":");
s_logger.info(" ESXi IP Address:" + part[0] + " vRouter-IP-Address: " + part[1]);
esxiToVRouterIpMap.put(part[0], part[1]);
VRouterNotifier.setVrouterActive(part[1], true);
}
input.close();
} catch (FileNotFoundException e) {
s_logger.error("file not found :" + esxiToVRouterIpMapFile);
return false;
}
return true;
}
public Map<String, String> getEsxiToVRouterIpMap() {
return esxiToVRouterIpMap;
}
public void setReadTimeout(int milliSecs) {
//Set read timeout on connection to vcenter server
serviceInstance.getServerConnection()
.getVimService()
.getWsc().setReadTimeout(milliSecs);
}
public void setConnectTimeout(int milliSecs) {
//Set connect timeout on connection to vcenter server
serviceInstance.getServerConnection()
.getVimService()
.getWsc().setConnectTimeout(milliSecs);
}
public boolean isConnected() {
return (serviceInstance != null);
}
public IpPoolManager getIpPoolManager() {
return ipPoolManager;
}
public void setIpPoolManager(IpPoolManager _ipPoolManager) {
ipPoolManager = _ipPoolManager;
}
public InventoryNavigator getInventoryNavigator() {
return inventoryNavigator;
}
public void setInventoryNavigator(InventoryNavigator _inventoryNavigator) {
inventoryNavigator = _inventoryNavigator;
}
public Datacenter getDatacenter() {
return contrailDC;
}
public void setDatacenter(Datacenter _dc) {
contrailDC = _dc;
}
public VmwareDistributedVirtualSwitch getDvs() {
return contrailDVS;
}
protected static String getVirtualMachineMacAddress(
VirtualMachineConfigInfo vmConfigInfo,
DistributedVirtualPortgroup portGroup) {
VirtualDevice devices[] = vmConfigInfo.getHardware().getDevice();
for (VirtualDevice device : devices) {
// Assuming only one interface
if (device instanceof VirtualEthernetCard) {
VirtualDeviceBackingInfo backingInfo =
device.getBacking();
if (backingInfo == null)
continue;
// Is it backed by the distributed virtual port group?
if (backingInfo instanceof
VirtualEthernetCardDistributedVirtualPortBackingInfo) {
VirtualEthernetCardDistributedVirtualPortBackingInfo
dvpBackingInfo =
(VirtualEthernetCardDistributedVirtualPortBackingInfo)
backingInfo;
if ((dvpBackingInfo.getPort() == null) ||
(dvpBackingInfo.getPort().getPortgroupKey() == null))
continue;
if (dvpBackingInfo.getPort().getPortgroupKey().
equals(portGroup.getKey())) {
String vmMac = ((VirtualEthernetCard) device).
getMacAddress();
return vmMac;
}
}
}
}
s_logger.error("dvPg: " + portGroup.getName() + " vmConfig: " +
vmConfigInfo + " MAC Address NOT found");
return null;
}
protected String getVRouterVMIpFabricAddress(String hostName,
HostSystem host, String vmNamePrefix)
throws Exception {
// Find if vRouter Ip Fabric mapping exists..
String vRouterIpAddress = esxiToVRouterIpMap.get(hostName);
if (host.getRuntime().isInMaintenanceMode()) {
VRouterNotifier.setVrouterActive(vRouterIpAddress, false);
}
if (vRouterIpAddress != null) {
return vRouterIpAddress;
}
VirtualMachine[] vms = host.getVms();
for (VirtualMachine vm : vms) {
String vmName = vm.getName();
if (!vmName.toLowerCase().contains(vmNamePrefix.toLowerCase())) {
continue;
}
// Assumption here is that VMware Tools are installed
// and IP address is available
GuestInfo guestInfo = vm.getGuest();
if (guestInfo == null) {
s_logger.debug(" Host: " + hostName +
" vm:" + vmName + " GuestInfo - VMware Tools " +
" NOT installed");
continue;
}
GuestNicInfo[] nicInfos = guestInfo.getNet();
if (nicInfos == null) {
s_logger.debug(" Host: " + hostName +
" vm:" + vmName + " GuestNicInfo - VMware Tools " +
" NOT installed");
continue;
}
for (GuestNicInfo nicInfo : nicInfos) {
// Extract the IP address associated with simple port
// group. Assumption here is that Contrail VRouter VM will
// have only one standard port group
String networkName = nicInfo.getNetwork();
if (networkName == null || !networkName.equals(contrailIpFabricPgName)) {
continue;
}
Network network = (Network)
inventoryNavigator.searchManagedEntity("Network",
networkName);
if (network == null) {
s_logger.debug("Host: " +
hostName + " vm: " + vmName + " network: " +
networkName + " NOT found");
continue;
}
NetIpConfigInfo ipConfigInfo = nicInfo.getIpConfig();
if (ipConfigInfo == null) {
continue;
}
NetIpConfigInfoIpAddress[] ipAddrConfigInfos =
ipConfigInfo.getIpAddress();
if (ipAddrConfigInfos == null ||
ipAddrConfigInfos.length == 0) {
continue;
}
for (NetIpConfigInfoIpAddress ipAddrConfigInfo :
ipAddrConfigInfos) {
String ipAddress = ipAddrConfigInfo.getIpAddress();
// Choose IPv4 only
InetAddress ipAddr = InetAddress.getByName(ipAddress);
if (ipAddr instanceof Inet4Address) {
// found vRouter VM ip-fabric address. Store it.
esxiToVRouterIpMap.put(hostName, ipAddress);
return ipAddress;
}
}
}
}
return null;
}
public static String getVirtualMachineIpAddress(VirtualMachine vm,
String dvPgName) throws Exception {
// Assumption here is that VMware Tools are installed
// and IP address is available
GuestInfo guestInfo = vm.getGuest();
String vmName = vm.getName();
if (guestInfo == null) {
s_logger.debug("dvPg: " + dvPgName + " vm:" + vmName
+ " GuestInfo - VMware Tools " + " NOT installed");
return null;
}
GuestNicInfo[] nicInfos = guestInfo.getNet();
if (nicInfos == null) {
s_logger.debug("dvPg: " + dvPgName + " vm:" + vmName
+ " GuestNicInfo - VMware Tools " + " NOT installed");
return null;
}
for (GuestNicInfo nicInfo : nicInfos) {
// Extract the IP address associated with simple port
// group. Assumption here is that Contrail VRouter VM will
// have only one standard port group
String networkName = nicInfo.getNetwork();
if (networkName == null || !networkName.equals(dvPgName)) {
continue;
}
NetIpConfigInfo ipConfigInfo = nicInfo.getIpConfig();
if (ipConfigInfo == null) {
continue;
}
NetIpConfigInfoIpAddress[] ipAddrConfigInfos =
ipConfigInfo.getIpAddress();
if (ipAddrConfigInfos == null ||
ipAddrConfigInfos.length == 0) {
continue;
}
for (NetIpConfigInfoIpAddress ipAddrConfigInfo :
ipAddrConfigInfos) {
String ipAddress = ipAddrConfigInfo.getIpAddress();
InetAddress ipAddr = InetAddress.getByName(ipAddress);
if (ipAddr instanceof Inet4Address) {
// the VMI can have multiple IPv4 and IPv6 addresses,
// but we pick only the first IPv4 address
return ipAddress;
}
}
}
return null;
}
private static boolean doIgnoreVirtualNetwork(DVPortSetting portSetting) {
// Ignore dvPgs that do not have PVLAN/VLAN configured
if (portSetting instanceof VMwareDVSPortSetting) {
VMwareDVSPortSetting vPortSetting =
(VMwareDVSPortSetting) portSetting;
VmwareDistributedVirtualSwitchVlanSpec vlanSpec =
vPortSetting.getVlan();
if (vlanSpec instanceof VmwareDistributedVirtualSwitchPvlanSpec) {
return false;
}
if (vlanSpec instanceof VmwareDistributedVirtualSwitchVlanIdSpec) {
return false;
}
}
return true;
}
public boolean getExternalIpamInfo(DVPortgroupConfigInfo configInfo, String vnName) throws Exception {
DistributedVirtualSwitchKeyedOpaqueBlob[] opaqueBlobs
= configInfo.getVendorSpecificConfig();
if ((opaqueBlobs == null) || (opaqueBlobs.length == 0)) {
return false;
}
for (DistributedVirtualSwitchKeyedOpaqueBlob opaqueBlob : opaqueBlobs) {
s_logger.debug("pg (" + vnName + ") " + "opaqueBlob: key ("
+ opaqueBlob.getKey() + " ) opaqueData ("
+ opaqueBlob.getOpaqueData() + ")");
if (opaqueBlob.getKey().equals("external_ipam")) {
if (opaqueBlob.getOpaqueData().equals("true")) {
return true;
} else {
return false;
}
}
}
return false;
}
public boolean getExternalIpamInfo(DistributedVirtualSwitchKeyedOpaqueBlob[] opaqueBlobs, String vnName) {
if ((opaqueBlobs == null) || (opaqueBlobs.length == 0)) {
return false;
}
for (DistributedVirtualSwitchKeyedOpaqueBlob opaqueBlob : opaqueBlobs) {
s_logger.debug("pg (" + vnName + ") " + "opaqueBlob: key ("
+ opaqueBlob.getKey() + " ) opaqueData ("
+ opaqueBlob.getOpaqueData() + ")");
if (opaqueBlob.getKey().equals("external_ipam")) {
if (opaqueBlob.getOpaqueData().equals("true")) {
return true;
} else {
return false;
}
}
}
return false;
}
public String getVcenterUrl() {
return vcenterUrl;
}
public Datacenter getVmwareDatacenter(String name)
throws RemoteException {
if (datacenters.containsKey(name)) {
return datacenters.get(name);
}
String description = "<datacenter " + name + ", vCenter " + vcenterUrl + ">.";
Folder rootFolder = serviceInstance.getRootFolder();
if (rootFolder == null) {
operationalStatus = "Failed to get rootfolder for vCenter " + vcenterUrl;
s_logger.error(operationalStatus);
throw new RemoteException(operationalStatus);
}
InventoryNavigator inventoryNavigator = new InventoryNavigator(rootFolder);
Datacenter dc = null;
try {
dc = (Datacenter) inventoryNavigator.searchManagedEntity(
"Datacenter", name);
} catch (RemoteException e ) {
operationalStatus = "Failed to retrieve " + description;
s_logger.error(operationalStatus);
throw new RemoteException(operationalStatus, e);
}
if (dc == null) {
operationalStatus = "Failed to retrieve " + description;
s_logger.error(operationalStatus);
throw new RemoteException(operationalStatus);
}
datacenters.put(name, dc);
s_logger.info("Found " + description);
return dc;
}
public VmwareDistributedVirtualSwitch getVmwareDvs(String name,
Datacenter dc, String dcName)
throws RemoteException {
if (dvswitches.containsKey(name)) {
return dvswitches.get(name);
}
String description = "<dvs " + name + ", datacenter " + dcName
+ ", vCenter " + vcenterUrl + ">.";
InventoryNavigator inventoryNavigator = new InventoryNavigator(dc);
VmwareDistributedVirtualSwitch dvs = null;
try {
dvs = (VmwareDistributedVirtualSwitch)inventoryNavigator.searchManagedEntity(
"VmwareDistributedVirtualSwitch", name);
} catch (RemoteException e ) {
operationalStatus = "Failed to retrieve " + description;
s_logger.error(operationalStatus);
throw new RemoteException(operationalStatus, e);
}
if (dvs == null) {
operationalStatus = "Failed to retrieve " + description;
s_logger.error(operationalStatus);
throw new RemoteException(operationalStatus);
}
s_logger.info("Found " + description);
dvswitches.put(name, dvs);
return dvs;
}
public VMwareDVSPvlanMapEntry[] getDvsPvlanMap(String dvsName, Datacenter dc, String dcName)
throws RemoteException {
if (dvsPvlanMap.containsKey(dvsName)) {
return dvsPvlanMap.get(dvsName);
}
VmwareDistributedVirtualSwitch dvs = getVmwareDvs(dvsName, dc, dcName);
// Extract private vlan entries for the virtual switch
VMwareDVSConfigInfo dvsConfigInfo = (VMwareDVSConfigInfo) dvs.getConfig();
if (dvsConfigInfo == null) {
s_logger.error("dvSwitch: " + dvsName
+ " Datacenter: " + dcName + " ConfigInfo is empty");
}
if (!(dvsConfigInfo instanceof VMwareDVSConfigInfo)) {
s_logger.error("dvSwitch: " + dvsName +
" Datacenter: " + dcName + " ConfigInfo " +
"isn't instanceof VMwareDVSConfigInfo");
}
VMwareDVSPvlanMapEntry[] pvlanMapArray = dvsConfigInfo.getPvlanConfig();
if (pvlanMapArray != null) {
dvsPvlanMap.put(dvsName, pvlanMapArray);
s_logger.info("Found private vlan map array on dvSwitch: " + dvsName +
" Datacenter: " + dcName);
return pvlanMapArray;
}
s_logger.error("dvSwitch: " + dvsName +
" Datacenter: " + dcName + " Private VLAN NOT" +
"configured");
return null;
}
public IpPool getIpPoolById(Integer poolid, String nwName, Datacenter dc, String dcName)
throws RemoteException {
if (ipPools == null) {
ipPools = ipPoolManager.queryIpPools(dc);
if (ipPools == null || ipPools.length == 0) {
s_logger.debug(" Datacenter: " + dcName + " IP Pools NOT configured");
return null;
}
}
// refresh cached pools and try again
ipPools = ipPoolManager.queryIpPools(dc);
if (ipPools == null || ipPools.length == 0) {
s_logger.debug(" Datacenter: " + dcName + " IP Pools NOT configured");
return null;
}
return getIpPool(poolid, nwName);
}
private IpPool getIpPool(Integer poolid, String nwName) {
if (poolid == null) {
// there is a vmware bug in which the ip pool association
// is lost upon vcenter restart.
// Retrieve the pool based on name
// Remove this code if vmware bug is fixed
String IpPoolForPG = "ip-pool-for-" + nwName;
for (IpPool pool : ipPools) {
if (IpPoolForPG.equals(pool.getName())) {
return pool;
}
}
return null;
}
for (IpPool pool : ipPools) {
if (pool.id.equals(poolid)) {
return pool;
}
}
return null;
}
public Network getVmwareNetwork(String name,
VmwareDistributedVirtualSwitch dvs, String dvsName, String dcName)
throws RemoteException {
String description = "<network " + name
+ ", dvs " + dvsName + ", datacenter " + dcName
+ ", vCenter " + vcenterUrl + ">.";
// funny but search on the dvs does not work, we need to use rootFolder
InventoryNavigator inventoryNavigator = new InventoryNavigator(rootFolder);
Network nw = null;
try {
nw = (Network)inventoryNavigator.searchManagedEntity(
"Network", name);
} catch (RemoteException e ) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg, e);
}
if (nw == null) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg);
}
s_logger.info("Found " + description);
return nw;
}
public DistributedVirtualPortgroup getVmwareDpg(String name,
VmwareDistributedVirtualSwitch dvs, String dvsName, String dcName)
throws RemoteException {
String description = "<dpg " + name + ", dvs " + dvsName
+ ", datacenter " + dcName + ", vCenter " + vcenterUrl + ">.";
// funny but search on the dvs does not work, we need to use rootFolder
InventoryNavigator inventoryNavigator = new InventoryNavigator(rootFolder);
DistributedVirtualPortgroup dpg = null;
try {
dpg = (DistributedVirtualPortgroup)inventoryNavigator.searchManagedEntity(
"DistributedVirtualPortgroup", name);
} catch (RemoteException e ) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg, e);
}
if (dpg == null) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg);
}
s_logger.info("Found " + description);
return dpg;
}
public HostSystem getVmwareHost(String name,
Datacenter dc, String dcName)
throws RemoteException {
String description = "<host " + name
+ ", datacenter " + dcName + ", vCenter " + vcenterUrl +">.";
// narrow the search to the dc level
InventoryNavigator inventoryNavigator = new InventoryNavigator(dc);
HostSystem host = null;
try {
host = (HostSystem)inventoryNavigator.searchManagedEntity(
"HostSystem", name);
} catch (RemoteException e ) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg, e);
}
if (host == null) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg);
}
s_logger.info("Found " + description);
return host;
}
public VirtualMachine getVmwareVirtualMachine(String name,
HostSystem host, String hostName, String dcName)
throws RemoteException {
String description = "<virtual machine " + name + ", host " + hostName
+ ", datacenter " + dcName + ", vCenter " + vcenterUrl +">.";
// narrow the search to the host level
InventoryNavigator inventoryNavigator = new InventoryNavigator(host);
VirtualMachine vm = null;
try {
vm = (VirtualMachine)inventoryNavigator.searchManagedEntity(
"VirtualMachine", name);
} catch (RemoteException e ) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg, e);
}
if (vm == null) {
String msg = "Failed to retrieve " + description;
s_logger.error(msg);
throw new RemoteException(msg);
}
s_logger.info("Found " + description);
return vm;
}
public SortedMap<String, VirtualNetworkInfo> readVirtualNetworks()
throws Exception {
s_logger.info("Start reading virtual networks from vcenter ...");
SortedMap<String, VirtualNetworkInfo> map =
new ConcurrentSkipListMap<String, VirtualNetworkInfo>();
if (contrailDVS == null) {
s_logger.error("dvSwitch: " + contrailDvSwitchName +
" NOT configured");
return map;
}
// Extract distributed virtual port groups
DistributedVirtualPortgroup[] dvPgs = contrailDVS.getPortgroup();
if (dvPgs == null || dvPgs.length == 0) {
s_logger.error("dvSwitch: " + contrailDvSwitchName +
" Distributed portgroups NOT configured");
return map;
}
@SuppressWarnings("rawtypes")
Hashtable[] pTables = PropertyCollectorUtil.retrieveProperties(dvPgs,
"DistributedVirtualPortgroup",
new String[] {"name",
"config.key",
"config.defaultPortConfig",
"config.vendorSpecificConfig",
"summary.ipPoolId",
"summary.ipPoolName",
});
for (int i=0; i < dvPgs.length; i++) {
// Extract dvPg configuration info and port setting
DVPortSetting portSetting = (DVPortSetting) pTables[i].get("config.defaultPortConfig");
if (doIgnoreVirtualNetwork(portSetting)) {
continue;
}
VirtualNetworkInfo vnInfo =
new VirtualNetworkInfo(
this, dvPgs[i], pTables[i], contrailDC, contrailDataCenterName,
contrailDVS, contrailDvSwitchName);
s_logger.info("Read from vcenter " + vnInfo + ", ipPoolId " + vnInfo.getIpPoolId());
VCenterNotify.watchVn(vnInfo);
map.put(vnInfo.getUuid(), vnInfo);
}
s_logger.info("Done reading from vcenter, found " + map.size() + " Virtual Networks");
return map;
}
private void readVirtualMachines(SortedMap<String, VirtualMachineInfo> map,
ManagedEntity me,
Datacenter dc, String dcName)
throws Exception {
ManagedEntity[] vms = new InventoryNavigator(me).searchManagedEntities("VirtualMachine");
if (vms == null || vms.length == 0) {
s_logger.debug("Datacenter: " + dcName +
" NO virtual machines connected");
return;
}
String vrouterIpAddress = null;
HostSystem host = null;
// If the passed Managed Entity is at the host-level, then pass
// the hostName and Contrail VM IP Address instead of finding
// it every time for every VM which is costly.
if (me instanceof HostSystem) {
host = (HostSystem) me;
String hostName = host.getName();
vrouterIpAddress = getVRouterVMIpFabricAddress(hostName, host, dcName);
}
@SuppressWarnings("rawtypes")
Hashtable[] pTables = PropertyCollectorUtil.retrieveProperties(vms, "VirtualMachine",
new String[] {"name",
"config.instanceUuid",
"config.annotation",
"runtime.powerState",
"runtime.host",
"guest.toolsRunningStatus",
"guest.net"
});
for (int i=0; i < vms.length; i++) {
VirtualMachineInfo vmInfo = new VirtualMachineInfo(this,
dc, dcName,
(VirtualMachine)vms[i], pTables[i],
host, vrouterIpAddress);
readVirtualMachineInterfaces(vmInfo);
// Ignore virtual machine?
if (vmInfo.ignore()) {
s_logger.debug(" Ignoring vm: " + vmInfo.getName());
continue;
}
s_logger.info("Read from vcenter " + vmInfo);
map.put(vmInfo.getUuid(), vmInfo);
}
}
private void findHostsInFolder(Folder hostsFolder, List<HostSystem> hostsList)
throws IOException, Exception {
for (ManagedEntity e : hostsFolder.getChildEntity()) {
if (e instanceof HostSystem) {
hostsList.add((HostSystem)e);
}
// This is a cluster resource. Delve deeper to
// find more hosts.
if (e instanceof ComputeResource) {
ComputeResource cluster = (ComputeResource) e;
for(HostSystem host : cluster.getHosts()) {
hostsList.add((HostSystem)host);
}
}
if (e instanceof Folder) {
findHostsInFolder((Folder)e, hostsList);
}
}
}
SortedMap<String, VirtualMachineInfo> readVirtualMachines()
throws IOException, Exception {
s_logger.info("Start reading virtual machines from vcenter ...");
SortedMap<String, VirtualMachineInfo> map =
new ConcurrentSkipListMap<String, VirtualMachineInfo>();
/* the method below can be called in a loop to read multiple
* datacenters and read VMs per hosts
* for (dc: datacenters)
* for (host: dc)
readVirtualMachines(map, host, dc, dcName);
*/
Folder hostsFolder = contrailDC.getHostFolder();
if (hostsFolder == null) {
s_logger.error("Unable to read VMs, hostFolder is null");
return map;
}
List<HostSystem> hostsList = new ArrayList<HostSystem>();
findHostsInFolder(hostsFolder, hostsList);
for (HostSystem host : hostsList) {
readVirtualMachines(map, host, contrailDC, contrailDataCenterName);
}
s_logger.info("Done reading from vcenter, found " + map.size() + " Virtual Machines");
return map;
}
public void readVirtualMachineInterfaces(VirtualMachineInfo vmInfo)
throws IOException, Exception {
VirtualMachine vm = vmInfo.vm;
Network[] nets = vm.getNetworks();
for (Network net: nets) {
VirtualNetworkInfo vnInfo = null;
switch (mode) {
case VCENTER_ONLY:
String netName = net.getName();
vnInfo = MainDB.getVnByName(netName);
if (vnInfo == null) {
if (mode == Mode.VCENTER_ONLY) {
s_logger.info("Skipping VMI in unmanaged network " + netName);
continue;
}
}
break;
case VCENTER_AS_COMPUTE:
// network is managed by Openstack or other entity
// UUID is used in the name because name is not unique
String uuid = net.getName();
/*
From Mitaka nova driver will append cluster_id to port group
therefore need to extract the appended cluster id
*/
uuid = uuid.substring(Math.max(0, uuid.length() - 36));
vnInfo = MainDB.getVnById(uuid);
if (vnInfo == null) {
s_logger.info("Skipping VMI in unmanaged network " + uuid);
continue;
}
break;
default:
throw new Exception("Unhandled mode " + mode.name());
}
VirtualMachineInterfaceInfo vmiInfo =
new VirtualMachineInterfaceInfo(vmInfo, vnInfo);
vmiInfo.setMacAddress(getVirtualMachineMacAddress(vm.getConfig(), vnInfo.getDpg()));
if (mode != Mode.VCENTER_AS_COMPUTE && vnInfo.getExternalIpam() ){
if (vmInfo.getToolsRunningStatus().equals(
VirtualMachineToolsRunningStatus.guestToolsRunning.toString())) {
// static IP Address & vmWare tools installed
// see if we can read it from Guest Nic Info
vmiInfo.setIpAddress(getVirtualMachineIpAddress(vm, vnInfo.getName()));
}
VCenterNotify.watchVm(vmiInfo.vmInfo);
}
vmInfo.created(vmiInfo);
}
}
public boolean isAlive() {
try {
lastTimeSeenAlive = null;
lastTimeSeenAlive = serviceInstance.currentTime();
if (lastTimeSeenAlive == null) {
operationalStatus = "Failed aliveness check for vCenter " + vcenterUrl;
s_logger.error(operationalStatus);
return false;
}
} catch (Exception e) {
operationalStatus = "Failed aliveness check for vCenter " + vcenterUrl;
s_logger.error(operationalStatus);
return false;
}
return true;
}
public Calendar getLastTimeSeenAlive() {
return lastTimeSeenAlive;
}
public VmwareDistributedVirtualSwitch getContrailDvs() {
return contrailDVS;
}
}