Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion agent/src/main/java/com/cloud/agent/Agent.java
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,10 @@ public void processResponse(final Response response, final Link link) {
public void processReadyCommand(final Command cmd) {
final ReadyCommand ready = (ReadyCommand)cmd;
// Set human readable sizes;
NumbersUtil.enableHumanReadableSizes = ready.getEnableHumanReadableSizes();
Boolean humanReadable = ready.getEnableHumanReadableSizes();
if (humanReadable != null){
NumbersUtil.enableHumanReadableSizes = humanReadable;
}

s_logger.info("Processing agent ready command, agent id = " + ready.getHostId());
if (ready.getHostId() != null) {
Expand Down
6 changes: 6 additions & 0 deletions api/src/main/java/com/cloud/agent/api/PvlanSetupCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public enum Type {
private String dhcpIp;
private Type type;
private String networkTag;
private String pvlanType;

protected PvlanSetupCommand() {
}
Expand All @@ -43,6 +44,7 @@ protected PvlanSetupCommand(Type type, String op, URI uri, String networkTag) {
this.op = op;
this.primary = NetUtils.getPrimaryPvlanFromUri(uri);
this.isolated = NetUtils.getIsolatedPvlanFromUri(uri);
this.pvlanType = NetUtils.getPvlanTypeFromUri(uri);
this.networkTag = networkTag;
}

Expand Down Expand Up @@ -116,4 +118,8 @@ public void setDhcpName(String dhcpName) {
public String getNetworkTag() {
return networkTag;
}

public String getPvlanType() {
return pvlanType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3756,6 +3756,7 @@ private NicProfile orchestrateAddVmToNetwork(final VirtualMachine vm, final Netw
try {
result = plugNic(network, nicTO, vmTO, context, dest);
if (result) {
_userVmMgr.setupVmForPvlan(true, vm.getHostId(), nic);
s_logger.debug("Nic is plugged successfully for vm " + vm + " in network " + network + ". Vm is a part of network now");
final long isDefault = nic.isDefaultNic() ? 1 : 0;
// insert nic's Id into DB as resource_name
Expand Down Expand Up @@ -3863,6 +3864,7 @@ private boolean orchestrateRemoveNicFromVm(final VirtualMachine vm, final Nic ni
s_logger.debug("Un-plugging nic " + nic + " for vm " + vm + " from network " + network);
final boolean result = unplugNic(network, nicTO, vmTO, context, dest);
if (result) {
_userVmMgr.setupVmForPvlan(false, vm.getHostId(), nicProfile);
s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network);
final long isDefault = nic.isDefaultNic() ? 1 : 0;
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// under the License.
package org.apache.cloudstack.engine.orchestration;


import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -215,6 +214,7 @@
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.ReservationContextImpl;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
Expand Down Expand Up @@ -299,6 +299,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
RemoteAccessVpnDao _remoteAccessVpnDao;
@Inject
VpcVirtualNetworkApplianceService _routerService;
@Inject
UserVmManager _userVmMgr;

List<NetworkGuru> networkGurus;

Expand Down Expand Up @@ -1792,6 +1794,11 @@ public void prepareNicForMigration(final VirtualMachineProfile vm, final DeployD
s_logger.error("NetworkGuru " + guru + " prepareForMigration failed."); // XXX: Transaction error
}
}

if (network.getGuestType() == Network.GuestType.L2 && vm.getType() == VirtualMachine.Type.User) {
_userVmMgr.setupVmForPvlan(false, vm.getVirtualMachine().getHostId(), profile);
}

final List<Provider> providersToImplement = getNetworkProviders(network.getId());
for (final NetworkElement element : networkElements) {
if (providersToImplement.contains(element.getProvider())) {
Expand Down Expand Up @@ -1912,6 +1919,11 @@ public void commitNicForMigration(final VirtualMachineProfile src, final Virtual
if (guru instanceof NetworkMigrationResponder) {
((NetworkMigrationResponder)guru).commitMigration(nicSrc, network, src, src_context, dst_context);
}

if (network.getGuestType() == Network.GuestType.L2 && src.getType() == VirtualMachine.Type.User) {
_userVmMgr.setupVmForPvlan(true, src.getVirtualMachine().getHostId(), nicSrc);
}

final List<Provider> providersToImplement = getNetworkProviders(network.getId());
for (final NetworkElement element : networkElements) {
if (providersToImplement.contains(element.getProvider())) {
Expand Down Expand Up @@ -1943,6 +1955,11 @@ public void rollbackNicForMigration(final VirtualMachineProfile src, final Virtu
if (guru instanceof NetworkMigrationResponder) {
((NetworkMigrationResponder)guru).rollbackMigration(nicDst, network, dst, src_context, dst_context);
}

if (network.getGuestType() == Network.GuestType.L2 && src.getType() == VirtualMachine.Type.User) {
_userVmMgr.setupVmForPvlan(true, dst.getVirtualMachine().getHostId(), nicDst);
}

final List<Provider> providersToImplement = getNetworkProviders(network.getId());
for (final NetworkElement element : networkElements) {
if (providersToImplement.contains(element.getProvider())) {
Expand Down Expand Up @@ -2498,6 +2515,12 @@ public Network doInTransaction(final TransactionStatus status) {
} else {
uri = BroadcastDomainType.fromString(vlanIdFinal);
}

if (_networksDao.listByPhysicalNetworkPvlan(physicalNetworkId, uri.toString()).size() > 0) {
throw new InvalidParameterValueException("Network with vlan " + vlanIdFinal +
" already exists or overlaps with other network pvlans in zone " + zoneId);
}

userNetwork.setBroadcastUri(uri);
if (!vlanIdFinal.equalsIgnoreCase(Vlan.UNTAGGED)) {
userNetwork.setBroadcastDomainType(BroadcastDomainType.Vlan);
Expand All @@ -2508,7 +2531,7 @@ public Network doInTransaction(final TransactionStatus status) {
if (vlanIdFinal.equalsIgnoreCase(Vlan.UNTAGGED)) {
throw new InvalidParameterValueException("Cannot support pvlan with untagged primary vlan!");
}
URI uri = NetUtils.generateUriForPvlan(vlanIdFinal, isolatedPvlan);
URI uri = NetUtils.generateUriForPvlan(vlanIdFinal, isolatedPvlan, isolatedPvlanType.toString());
if (_networksDao.listByPhysicalNetworkPvlan(physicalNetworkId, uri.toString(), isolatedPvlanType).size() > 0) {
throw new InvalidParameterValueException("Network with primary vlan " + vlanIdFinal +
" and secondary vlan " + isolatedPvlan + " type " + isolatedPvlanType +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,6 @@ public interface NetworkDao extends GenericDao<NetworkVO, Long>, StateDao<State,
List<NetworkVO> listByAccountIdNetworkName(long accountId, String name);

List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType);

List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri);
}
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ public List<NetworkVO> listByAccountIdNetworkName(final long accountId, final St
* - The requested exact PVLAN pair exists
* - The requested secondary VLAN ID is secondary VLAN ID of an existing PVLAN pair
* - The requested secondary VLAN ID is primary VLAN ID of an existing PVLAN pair
* - The requested primary VLAN ID is secondary VLAN ID of an existing PVLAN pair
*/
protected boolean isNetworkOverlappingRequestedPvlan(Integer existingPrimaryVlan, Integer existingSecondaryVlan, Network.PVlanType existingPvlanType,
Integer requestedPrimaryVlan, Integer requestedSecondaryVlan, Network.PVlanType requestedPvlanType) {
Expand All @@ -749,14 +750,20 @@ protected boolean isNetworkOverlappingRequestedPvlan(Integer existingPrimaryVlan
}
boolean exactMatch = existingPrimaryVlan.equals(requestedPrimaryVlan) && existingSecondaryVlan.equals(requestedSecondaryVlan);
boolean secondaryVlanUsed = requestedPvlanType != Network.PVlanType.Promiscuous && requestedSecondaryVlan.equals(existingPrimaryVlan) || requestedSecondaryVlan.equals(existingSecondaryVlan);
boolean primaryVlanUsed = existingPvlanType != Network.PVlanType.Promiscuous && requestedPrimaryVlan.equals(existingSecondaryVlan);
boolean isolatedMax = false;
boolean promiscuousMax = false;
if (requestedPvlanType == Network.PVlanType.Isolated && existingPrimaryVlan.equals(requestedPrimaryVlan) && existingPvlanType.equals(Network.PVlanType.Isolated)) {
isolatedMax = true;
} else if (requestedPvlanType == Network.PVlanType.Promiscuous && existingPrimaryVlan.equals(requestedPrimaryVlan) && existingPvlanType == Network.PVlanType.Promiscuous) {
promiscuousMax = true;
}
return exactMatch || secondaryVlanUsed || isolatedMax || promiscuousMax;
return exactMatch || secondaryVlanUsed || primaryVlanUsed || isolatedMax || promiscuousMax;
}

// True when a VLAN ID overlaps with an existing PVLAN primary or secondary ID
protected boolean isNetworkOverlappingRequestedPvlan(Integer existingPrimaryVlan, Integer existingSecondaryVlan, Integer requestedVlan) {
return requestedVlan.equals(existingPrimaryVlan) || requestedVlan.equals(existingSecondaryVlan);
}

protected Network.PVlanType getNetworkPvlanType(long networkId, List<Integer> existingPvlan) {
Expand All @@ -770,6 +777,38 @@ protected Network.PVlanType getNetworkPvlanType(long networkId, List<Integer> ex
return existingPvlanType;
}

@Override
public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri) {
final URI searchUri = BroadcastDomainType.fromString(broadcastUri);
if (!searchUri.getScheme().equalsIgnoreCase("vlan")) {
throw new CloudRuntimeException("VLAN requested but URI is not in the expected format: " + searchUri.toString());
}
final String searchRange = BroadcastDomainType.getValue(searchUri);
final List<Integer> searchVlans = UriUtils.expandVlanUri(searchRange);
final List<NetworkVO> overlappingNetworks = new ArrayList<>();

final SearchCriteria<NetworkVO> sc = PhysicalNetworkSearch.create();
sc.setParameters("physicalNetworkId", physicalNetworkId);

for (final NetworkVO network : listBy(sc)) {
if (network.getBroadcastUri() == null || !network.getBroadcastUri().getScheme().equalsIgnoreCase("pvlan")) {
continue;
}
// Ensure existing and proposed VLAN don't overlap
final String networkVlanRange = BroadcastDomainType.getValue(network.getBroadcastUri());
if (networkVlanRange == null || networkVlanRange.isEmpty()) {
continue;
}
List<Integer> existingPvlan = UriUtils.expandPvlanUri(networkVlanRange);
if (isNetworkOverlappingRequestedPvlan(existingPvlan.get(0), existingPvlan.get(1), searchVlans.get(0))) {
overlappingNetworks.add(network);
break;
}
}

return overlappingNetworks;
}

@Override
public List<NetworkVO> listByPhysicalNetworkPvlan(long physicalNetworkId, String broadcastUri, Network.PVlanType pVlanType) {
final URI searchUri = BroadcastDomainType.fromString(broadcastUri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -798,14 +798,14 @@ public boolean configure(final String name, final Map<String, Object> params) th
throw new ConfigurationException("Unable to find the router_proxy.sh");
}

_ovsPvlanDhcpHostPath = Script.findScript(networkScriptsDir, "ovs-pvlan-dhcp-host.sh");
_ovsPvlanDhcpHostPath = Script.findScript(networkScriptsDir, "ovs-pvlan-kvm-dhcp-host.sh");
if (_ovsPvlanDhcpHostPath == null) {
throw new ConfigurationException("Unable to find the ovs-pvlan-dhcp-host.sh");
throw new ConfigurationException("Unable to find the ovs-pvlan-kvm-dhcp-host.sh");
}

_ovsPvlanVmPath = Script.findScript(networkScriptsDir, "ovs-pvlan-vm.sh");
_ovsPvlanVmPath = Script.findScript(networkScriptsDir, "ovs-pvlan-kvm-vm.sh");
if (_ovsPvlanVmPath == null) {
throw new ConfigurationException("Unable to find the ovs-pvlan-vm.sh");
throw new ConfigurationException("Unable to find the ovs-pvlan-kvm-vm.sh");
}

String value = (String)params.get("developer");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,17 @@

package com.cloud.hypervisor.kvm.resource.wrapper;

import java.util.List;

import org.apache.log4j.Logger;
import org.joda.time.Duration;
import org.libvirt.Connect;
import org.libvirt.LibvirtException;

import com.cloud.agent.api.Answer;
import com.cloud.agent.api.PvlanSetupCommand;
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
import com.cloud.resource.CommandWrapper;
import com.cloud.resource.ResourceWrapper;
import com.cloud.utils.script.Script;

@ResourceWrapper(handles = PvlanSetupCommand.class)
@ResourceWrapper(handles = PvlanSetupCommand.class)
public final class LibvirtPvlanSetupCommandWrapper extends CommandWrapper<PvlanSetupCommand, Answer, LibvirtComputingResource> {

private static final Logger s_logger = Logger.getLogger(LibvirtPvlanSetupCommandWrapper.class);
Expand All @@ -43,66 +38,50 @@ public final class LibvirtPvlanSetupCommandWrapper extends CommandWrapper<PvlanS
public Answer execute(final PvlanSetupCommand command, final LibvirtComputingResource libvirtComputingResource) {
final String primaryPvlan = command.getPrimary();
final String isolatedPvlan = command.getIsolated();
final String pvlanType = "-" + command.getPvlanType();
final String op = command.getOp();
final String dhcpName = command.getDhcpName();
final String dhcpMac = command.getDhcpMac();
final String vmMac = command.getVmMac();
final String vmMac = command.getVmMac() == null ? dhcpMac : command.getVmMac();
final String dhcpIp = command.getDhcpIp();
boolean add = true;

String opr = "-A";
if (op.equals("delete")) {
opr = "-D";
add = false;
}

String result = null;
try {
final String guestBridgeName = libvirtComputingResource.getGuestBridgeName();
final Duration timeout = libvirtComputingResource.getTimeout();

if (command.getType() == PvlanSetupCommand.Type.DHCP) {
final String ovsPvlanDhcpHostPath = libvirtComputingResource.getOvsPvlanDhcpHostPath();
final Script script = new Script(ovsPvlanDhcpHostPath, timeout, s_logger);

if (add) {
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(dhcpName);

final List<InterfaceDef> ifaces = libvirtComputingResource.getInterfaces(conn, dhcpName);
final InterfaceDef guestNic = ifaces.get(0);
script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac, "-I",
guestNic.getDevName());
} else {
script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-n", dhcpName, "-d", dhcpIp, "-m", dhcpMac);
}

result = script.execute();
final String guestBridgeName = libvirtComputingResource.getGuestBridgeName();
final Duration timeout = libvirtComputingResource.getTimeout();

if (result != null) {
s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac);
return new Answer(command, false, result);
} else {
s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac);
}
} else if (command.getType() == PvlanSetupCommand.Type.VM) {
final String ovsPvlanVmPath = libvirtComputingResource.getOvsPvlanVmPath();
if (command.getType() == PvlanSetupCommand.Type.DHCP) {
final String ovsPvlanDhcpHostPath = libvirtComputingResource.getOvsPvlanDhcpHostPath();
final Script script = new Script(ovsPvlanDhcpHostPath, timeout, s_logger);

final Script script = new Script(ovsPvlanVmPath, timeout, s_logger);
script.add(opr, "-b", guestBridgeName, "-p", primaryPvlan, "-i", isolatedPvlan, "-v", vmMac);
result = script.execute();
script.add(opr, pvlanType, "-b", guestBridgeName, "-p", primaryPvlan, "-s", isolatedPvlan, "-m", dhcpMac,
"-d", dhcpIp);
result = script.execute();

if (result != null) {
s_logger.warn("Failed to program pvlan for vm with mac " + vmMac);
return new Answer(command, false, result);
} else {
s_logger.info("Programmed pvlan for vm with mac " + vmMac);
}
if (result != null) {
s_logger.warn("Failed to program pvlan for dhcp server with mac " + dhcpMac);
} else {
s_logger.info("Programmed pvlan for dhcp server with mac " + dhcpMac);
}
} catch (final LibvirtException e) {
s_logger.error("Error whislt executing OVS Setup command! ==> " + e.getMessage());
return new Answer(command, false, e.getMessage());
}

// We run this even for DHCP servers since they're all vms after all
final String ovsPvlanVmPath = libvirtComputingResource.getOvsPvlanVmPath();
final Script script = new Script(ovsPvlanVmPath, timeout, s_logger);
script.add(opr, pvlanType, "-b", guestBridgeName, "-p", primaryPvlan, "-s", isolatedPvlan, "-m", vmMac);
result = script.execute();

if (result != null) {
s_logger.warn("Failed to program pvlan for vm with mac " + vmMac);
return new Answer(command, false, result);
} else {
s_logger.info("Programmed pvlan for vm with mac " + vmMac);
}

return new Answer(command, true, result);
}
}
Loading