/**
* Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
*
* @author Andra Cismaru
*/
package net.juniper.contrail.vcenter;
import java.io.IOException;
import org.apache.log4j.Logger;
import com.google.common.net.InetAddresses;
import com.vmware.vim25.GuestNicInfo;
import com.vmware.vim25.NetIpConfigInfo;
import com.vmware.vim25.NetIpConfigInfoIpAddress;
import com.vmware.vim25.VirtualMachineToolsRunningStatus;
public class VirtualMachineInterfaceInfo extends VCenterObject {
private String uuid;
VirtualMachineInfo vmInfo;
VirtualNetworkInfo vnInfo;
private String ipAddress;
private String macAddress;
private boolean portAdded;
//API server objects
net.juniper.contrail.api.types.VirtualMachineInterface apiVmi;
net.juniper.contrail.api.types.InstanceIp apiInstanceIp;
private final Logger s_logger =
Logger.getLogger(VirtualMachineInterfaceInfo.class);
VirtualMachineInterfaceInfo(VirtualMachineInfo vmInfo,
VirtualNetworkInfo vnInfo) {
if (vmInfo == null) {
throw new IllegalArgumentException("Cannot init VMI, null VM argument");
}
if (vnInfo == null) {
throw new IllegalArgumentException("Cannot init VMI, null VN argument");
}
this.vmInfo = vmInfo;
this.vnInfo = vnInfo;
}
VirtualMachineInterfaceInfo(String macAddress)
{
if (macAddress == null) {
throw new IllegalArgumentException("Cannot init VMI, null MAC address");
}
this.macAddress = macAddress;
}
VirtualMachineInterfaceInfo(VirtualMachineInterfaceInfo vmiInfo)
{
if (vmiInfo == null) {
throw new IllegalArgumentException("Cannot init VMI from null VMI");
}
this.vmInfo = vmiInfo.vmInfo;
this.vnInfo = vmiInfo.vnInfo;
this.macAddress = vmiInfo.macAddress;
this.uuid = vmiInfo.uuid;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public VirtualMachineInfo getVmInfo() {
return vmInfo;
}
public void setVmInfo(VirtualMachineInfo vmInfo) {
this.vmInfo = vmInfo;
}
public VirtualNetworkInfo getVnInfo() {
return vnInfo;
}
public void setVnInfo(VirtualNetworkInfo vnInfo) {
this.vnInfo = vnInfo;
}
public String getMacAddress() {
return macAddress;
}
public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
if (vnInfo.isIpAddressInSubnetAndRange(ipAddress)) {
this.ipAddress = ipAddress;
} else {
s_logger.error(this + " Ignoring IP Address " + ipAddress + ", out of range for VN " + vnInfo);
this.ipAddress = null;
}
}
public boolean getPortAdded() {
return portAdded;
}
public void setPortAdded(boolean portAdded) {
this.portAdded = portAdded;
}
public void updatedGuestNic(GuestNicInfo nic, VncDB vncDB)
throws Exception {
if (nic == null) {
return;
}
NetIpConfigInfo ipConfig = nic.getIpConfig();
if (ipConfig == null ) {
return;
}
NetIpConfigInfoIpAddress[] ipAddrs = nic.getIpConfig().getIpAddress();
if (ipAddrs == null || ipAddrs.length <= 0) {
return;
}
String newIpAddress = ipAddrs[0].getIpAddress();
if (newIpAddress != null && newIpAddress.equals(ipAddress)) {
// IP address has not changed
return;
}
s_logger.info("Updated guestNic Address " + " to " + newIpAddress + " for " + this);
if (ipAddress != null) {
vncDB.deleteInstanceIp(this);
}
deletePort();
setIpAddress(newIpAddress);
if (ipAddress != null || vnInfo.getExternalIpam() == false) {
vncDB.createInstanceIp(this);
}
addPort();
}
public boolean equals(VirtualMachineInterfaceInfo vmi) {
if (vmi == null) {
return false;
}
if (!vmInfo.getUuid().equals(vmi.vmInfo.getUuid())) {
return false;
}
if (!vnInfo.getUuid().equals(vmi.vnInfo.getUuid())) {
return false;
}
if ((ipAddress != null && !ipAddress.equals(vmi.ipAddress))
|| (ipAddress == null && vmi.ipAddress != null)) {
return false;
}
if ((macAddress != null && !macAddress.equals(vmi.macAddress))
|| (macAddress == null && vmi.macAddress != null)) {
return false;
}
return true;
}
public String toString() {
return "VMI <" + vmInfo.getDisplayName() + ", " + vnInfo.getName() +
", " + uuid + ", " + ipAddress + ", " + macAddress +
", primary vlan = " + vnInfo.getPrimaryVlanId() +
", isolated vlan = " + vnInfo.getIsolatedVlanId() +
">";
}
@Override
void create(VncDB vncDB) throws Exception {
if (vncDB.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
setIpAddress(VCenterDB.getVirtualMachineIpAddress(vmInfo.vm, vnInfo.getName()));
}
VCenterNotify.watchVm(vmInfo);
}
vncDB.createVirtualMachineInterface(this);
if (ipAddress != null || vnInfo.getExternalIpam() == false) {
vncDB.createInstanceIp(this);
}
if (!portAdded) {
addPort();
} else {
s_logger.info("Skipping addPort, port already added for VM " + toString());
}
vnInfo.created(this);
vmInfo.created(this);
}
@Override
void update(VCenterObject obj,
VncDB vncDB) throws Exception {
VirtualMachineInterfaceInfo newVmiInfo = (VirtualMachineInterfaceInfo)obj;
if (vnInfo != newVmiInfo.vnInfo
|| (newVmiInfo.macAddress != null && !newVmiInfo.macAddress.equals(macAddress))) {
// change of network or MAC address
delete(vncDB);
vnInfo = newVmiInfo.vnInfo;
setIpAddress(newVmiInfo.ipAddress);
macAddress = newVmiInfo.macAddress;
if (newVmiInfo.uuid != null && !newVmiInfo.uuid.equals(uuid)) {
uuid = newVmiInfo.uuid;
}
create(vncDB);
return;
}
if (newVmiInfo.uuid != null && !newVmiInfo.uuid.equals(uuid)) {
uuid = newVmiInfo.uuid;
}
if (newVmiInfo.ipAddress != null && !newVmiInfo.ipAddress.equals(ipAddress)) {
// change of IP Address
deletePort();
vncDB.deleteInstanceIp(this);
// vmware bug: after vmware tools restart, ip address is incorrectly reset to null
// this check for null is a workaround
if (newVmiInfo.ipAddress != null) {
setIpAddress(newVmiInfo.ipAddress);
}
if (ipAddress != null || vnInfo.getExternalIpam() == false) {
vncDB.createInstanceIp(this);
}
}
if (vmInfo.isPoweredOnState()) {
if (!portAdded) {
addPort();
} else {
s_logger.info("Skipping addPort, port already added for VM " + toString());
}
} else {
deletePort();
}
}
@Override
void sync(VCenterObject obj,
VncDB vncDB) throws Exception {
VirtualMachineInterfaceInfo oldVmiInfo = (VirtualMachineInterfaceInfo)obj;
if (uuid == null && oldVmiInfo.uuid != null) {
uuid = oldVmiInfo.uuid;
}
if (apiVmi == null && oldVmiInfo.apiVmi != null) {
apiVmi = oldVmiInfo.apiVmi;
}
if (vnInfo == oldVmiInfo.vnInfo) {
// network is the same
// reuse the old address
if (apiInstanceIp == null && oldVmiInfo.apiInstanceIp != null) {
apiInstanceIp = oldVmiInfo.apiInstanceIp;
}
if (ipAddress == null && oldVmiInfo.ipAddress != null) {
setIpAddress(oldVmiInfo.ipAddress);
}
if (macAddress == null && oldVmiInfo.macAddress != null) {
macAddress = oldVmiInfo.macAddress;
}
if (uuid == null && oldVmiInfo.uuid != null) {
uuid = oldVmiInfo.uuid;
}
}
if ((oldVmiInfo.ipAddress != null && !oldVmiInfo.ipAddress.equals(ipAddress))
|| (oldVmiInfo.macAddress != null && !oldVmiInfo.macAddress.equals(macAddress))
|| (vnInfo != oldVmiInfo.vnInfo)) {
portAdded = false;
VRouterNotifier.deleted(oldVmiInfo);
}
if ((oldVmiInfo.ipAddress != null && !oldVmiInfo.ipAddress.equals(ipAddress))
|| (vnInfo != oldVmiInfo.vnInfo)) {
vncDB.deleteInstanceIp(oldVmiInfo);
oldVmiInfo.vnInfo.deleted(oldVmiInfo);
}
if (vnInfo != oldVmiInfo.vnInfo) {
oldVmiInfo.vnInfo.deleted(oldVmiInfo);
}
if ((ipAddress != null || vnInfo.getExternalIpam() == false)
&& apiInstanceIp == null) {
vncDB.createInstanceIp(this);
}
addPort();
vnInfo.created(this);
}
public void addPort() {
if (vmInfo.isPoweredOnState()) {
portAdded = true;
VRouterNotifier.created(this);
} else {
s_logger.info("Skipping addPort for powered off VM " + toString());
}
}
public void deletePort() {
if (portAdded) {
VRouterNotifier.deleted(this);
portAdded = false;
}
}
@Override
void delete(VncDB vncDB)
throws IOException {
deletePort();
vncDB.deleteInstanceIp(this);
vncDB.deleteVirtualMachineInterface(this);
vnInfo.deleted(this);
vmInfo.deleted(this);
}
}