Merge branch '4.4' into resize-root

This commit is contained in:
Marcus Sorensen 2014-03-14 02:27:26 -06:00
commit c02c634945
108 changed files with 5510 additions and 533 deletions

View File

@ -80,4 +80,12 @@ public class NicTO extends NetworkTO {
public List<String> getNicSecIps() {
return nicSecIps;
}
public String getNetworkUuid() {
return super.getUuid();
}
public void setNetworkUuid(String uuid) {
super.setUuid(uuid);
}
}

View File

@ -57,7 +57,7 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
public static final Service PortForwarding = new Service("PortForwarding");
public static final Service SecurityGroup = new Service("SecurityGroup");
public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols);
public static final Service Connectivity = new Service("Connectivity");
public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet);
private final String name;
private final Capability[] caps;
@ -186,6 +186,9 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
public static final Capability SslTermination = new Capability("SslTermination");
public static final Capability LbSchemes = new Capability("LbSchemes");
public static final Capability DhcpAccrossMultipleSubnets = new Capability("DhcpAccrossMultipleSubnets");
public static final Capability DistributedRouter = new Capability("DistributedRouter");
public static final Capability StretchedL2Subnet = new Capability("StretchedL2Subnet");
public static final Capability RegionLevelVpc = new Capability("RegionLevelVpc");
private final String name;
@ -336,4 +339,6 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
Long getNetworkACLId();
void setNetworkACLId(Long networkACLId);
boolean isStrechedL2Network();
}

View File

@ -57,6 +57,7 @@ public class NetworkProfile implements Network {
private final boolean displayNetwork;
private Long networkAclId;
private final String guruName;
private boolean strechedL2Subnet;
public NetworkProfile(Network network) {
id = network.getId();
@ -89,6 +90,7 @@ public class NetworkProfile implements Network {
displayNetwork = network.getDisplayNetwork();
networkAclId = network.getNetworkACLId();
guruName = network.getGuruName();
strechedL2Subnet = network.isStrechedL2Network();
}
public String getDns1() {
@ -282,4 +284,10 @@ public class NetworkProfile implements Network {
public IAMEntityType getEntityType() {
return IAMEntityType.Network;
}
@Override
public boolean isStrechedL2Network() {
return false;
}
}

View File

@ -94,7 +94,7 @@ public interface LoadBalancingRulesService {
/**
* Assign a virtual machine, or list of virtual machines, to a load balancer.
*/
boolean assignToLoadBalancer(long lbRuleId, List<Long> vmIds);
boolean assignToLoadBalancer(long lbRuleId, List<Long> vmIds, Map<Long, List<String>> vmIdIpMap);
boolean assignSSLCertToLoadBalancerRule(Long lbRuleId, String certName, String publicCert, String privateKey);

View File

@ -73,4 +73,16 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity {
boolean isRestartRequired();
boolean isDisplay();
/**
*
* @return true if VPC is configured to use distributed router to provides one-hop forwarding and hypervisor based ACL
*/
boolean usesDistributedRouter();
/**
*
* @return true if VPC spans multiple zones in the region
*/
boolean isRegionLevelVpc();
}

View File

@ -55,4 +55,13 @@ public interface VpcOffering extends InternalIdentity, Identity {
*/
Long getServiceOfferingId();
/**
* @return true if the offering provides a distributed router capable of one-hop forwarding
*/
boolean supportsDistributedRouter();
/**
* @return true if VPC created with the offering can span multiple zones in the region
*/
boolean offersRegionLevelVPC();
}

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.network.vpc;
import java.util.List;
import java.util.Map;
@ -23,8 +24,10 @@ public interface VpcProvisioningService {
public VpcOffering getVpcOffering(long vpcOfferingId);
public VpcOffering createVpcOffering(String name, String displayText, List<String> supportedServices, Map<String, List<String>> serviceProviders,
Long serviceOfferingId);
public VpcOffering createVpcOffering(String name, String displayText, List<String> supportedServices,
Map<String, List<String>> serviceProviders,
Map serviceCapabilitystList,
Long serviceOfferingId);
List<? extends VpcOffering> listVpcOfferings(Long id, String name, String displayText, List<String> supportedServicesStr, Boolean isDefault, String keyword,
String state, Long startIndex, Long pageSizeVal);

View File

@ -129,4 +129,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
Integer getConcurrentConnections();
boolean isKeepAliveEnabled();
boolean getSupportsStrechedL2();
}

View File

@ -102,6 +102,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Identity, I
s_fsm.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping);
s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped);
s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportMigrated, State.Running);
s_fsm.addTransition(State.Running, VirtualMachine.Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating);
s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running);

View File

@ -262,6 +262,8 @@ public class ApiConstants {
public static final String VALUE = "value";
public static final String VIRTUAL_MACHINE_ID = "virtualmachineid";
public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids";
public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap";
public static final String VLAN = "vlan";
public static final String VLAN_RANGE = "vlanrange";
public static final String REMOVE_VLAN = "removevlan";
@ -588,7 +590,10 @@ public class ApiConstants {
public static final String VGPU = "vgpu";
public static final String VGPUTYPE = "vgputype";
public static final String REMAININGCAPACITY = "remainingcapacity";
public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter";
public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc";
public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet";
public static final String REGION_LEVEL_VPC = "regionlevelvpc";
public enum HostDetails {
all, capacity, events, stats, min;

View File

@ -66,6 +66,9 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
+ "If not specified, the provider for the service will be mapped to the default provider on the physical network")
private Map<String, String> serviceProviderList;
@Parameter(name = ApiConstants.SERVICE_CAPABILITY_LIST, type = CommandType.MAP, description = "desired service capabilities as part of vpc offering")
private Map serviceCapabilitystList;
@Parameter(name = ApiConstants.SERVICE_OFFERING_ID,
type = CommandType.UUID,
entityType = ServiceOfferingResponse.class,
@ -112,13 +115,18 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd {
return serviceProviderMap;
}
public Map<String, List<String>> getServiceCapabilitystList() {
return serviceCapabilitystList;
}
public Long getServiceOfferingId() {
return serviceOfferingId;
}
@Override
public void create() throws ResourceAllocationException {
VpcOffering vpcOff = _vpcProvSvc.createVpcOffering(getVpcOfferingName(), getDisplayText(), getSupportedServices(), getServiceProviders(), getServiceOfferingId());
VpcOffering vpcOff = _vpcProvSvc.createVpcOffering(getVpcOfferingName(), getDisplayText(),
getSupportedServices(), getServiceProviders(), getServiceCapabilitystList(), getServiceOfferingId());
if (vpcOff != null) {
setEntityId(vpcOff.getId());
setEntityUuid(vpcOff.getUuid());

View File

@ -16,7 +16,12 @@
// under the License.
package org.apache.cloudstack.api.command.user.loadbalancer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Iterator;
import java.util.ArrayList;
import org.apache.log4j.Logger;
@ -62,10 +67,12 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = UserVmResponse.class,
required = true,
description = "the list of IDs of the virtual machine that are being assigned to the load balancer rule(i.e. virtualMachineIds=1,2,3)")
private List<Long> virtualMachineIds;
@Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID_IP, type = CommandType.MAP, description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].ip=10.1.1.75")
private Map vmIdIpMap;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -78,6 +85,10 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
return virtualMachineIds;
}
public Map<Long, String> getVmIdIpMap() {
return vmIdIpMap;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -106,10 +117,42 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd {
return "applying instances for load balancer: " + getLoadBalancerId() + " (ids: " + StringUtils.join(getVirtualMachineIds(), ",") + ")";
}
public Map<Long, List<String>> getVmIdIpListMap() {
Map<Long, List<String>> vmIdIpsMap = null;
if (vmIdIpMap != null && !vmIdIpMap.isEmpty()) {
vmIdIpsMap = new HashMap<Long, List<String>>();
Collection idIpsCollection = vmIdIpMap.values();
Iterator iter = idIpsCollection.iterator();
while (iter.hasNext()) {
HashMap<String, String> idIpsMap = (HashMap<String, String>)iter.next();
String vmId = idIpsMap.get("vmid");
String vmIp = idIpsMap.get("vmip");
Long longVmId = new Long(vmId);
List<String> ipsList = null;
if (vmIdIpsMap.containsKey(longVmId)) {
ipsList = vmIdIpsMap.get(longVmId);
} else {
ipsList = new ArrayList<String>();
}
ipsList.add(vmIp);
vmIdIpsMap.put(longVmId, ipsList);
}
}
return vmIdIpsMap;
}
@Override
public void execute() {
CallContext.current().setEventDetails("Load balancer Id: " + getLoadBalancerId() + " VmIds: " + StringUtils.join(getVirtualMachineIds(), ","));
boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds);
Map<Long, List<String>> vmIdIpsMap = getVmIdIpListMap();
boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds, vmIdIpsMap);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -68,8 +68,7 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = UserVmResponse.class, description = "the ID of the virtual machine")
private Long id;
@Parameter(name=ApiConstants.IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType=UserVmResponse.class,
description="the IDs of the virtual machines, mutually exclusive with id")
@Parameter(name=ApiConstants.IDS, type=CommandType.LIST, collectionType=CommandType.UUID, entityType=UserVmResponse.class, description="the IDs of the virtual machines, mutually exclusive with id", since = "4.4")
private List<Long> ids;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "name of the virtual machine")

View File

@ -65,7 +65,7 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd {
private Long projectId;
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class,
required = true, description = "the ID of the availability zone")
required = true, description = "the ID of the availability zone")
private Long zoneId;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the VPC")

View File

@ -116,6 +116,10 @@ public class NetworkOfferingResponse extends BaseResponse {
@Param(description = "maximum number of concurrents connections to be handled by lb")
private Integer concurrentConnections;
@SerializedName(ApiConstants.SUPPORTS_STRECHED_L2_SUBNET)
@Param(description = "true if network offering supports network that span multiple zones")
private Boolean supportsStrechedL2Subnet;
public void setId(String id) {
this.id = id;
}
@ -200,4 +204,7 @@ public class NetworkOfferingResponse extends BaseResponse {
this.concurrentConnections = concurrentConnections;
}
public void setSupportsStrechedL2Subnet(Boolean supportsStrechedL2Subnet) {
this.supportsStrechedL2Subnet = supportsStrechedL2Subnet;
}
}

View File

@ -107,6 +107,10 @@ public class StoragePoolResponse extends BaseResponse {
@Param(description = "the scope of the storage pool")
private String scope;
@SerializedName("overprovisionfactor")
@Param(description = "the overprovisionfactor for the storage pool")
private String overprovisionfactor;
@SerializedName(ApiConstants.HYPERVISOR)
@Param(description = "the hypervisor type of the storage pool")
private String hypervisor;
@ -301,4 +305,8 @@ public class StoragePoolResponse extends BaseResponse {
public void setSuitableForMigration(Boolean suitableForMigration) {
this.suitableForMigration = suitableForMigration;
}
public void setOverProvisionFactor(String overProvisionFactor) {
this.overprovisionfactor = overProvisionFactor;
}
}

View File

@ -59,6 +59,14 @@ public class VpcOfferingResponse extends BaseResponse {
@Param(description = "the list of supported services", responseObject = ServiceResponse.class)
private List<ServiceResponse> services;
@SerializedName(ApiConstants.DISTRIBUTED_VPC_ROUTER)
@Param(description = " indicates if the vpc offering supports distributed router for one-hop forwarding")
private Boolean supportsDistributedRouter;
@SerializedName((ApiConstants.SUPPORTS_REGION_LEVEL_VPC))
@Param(description = " indicated if the offering can support region level vpc")
private Boolean supportsRegionLevelVpc;
public void setId(String id) {
this.id = id;
}
@ -86,4 +94,12 @@ public class VpcOfferingResponse extends BaseResponse {
public void setState(String state) {
this.state = state;
}
public void setSupportsDistributedRouter(Boolean supportsDistributedRouter) {
this.supportsDistributedRouter = supportsDistributedRouter;
}
public void setSupportsRegionLevelVpc(Boolean supports) {
this.supportsRegionLevelVpc = supports;
}
}

View File

@ -111,6 +111,14 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons
@Param(description = "is vpc for display to the regular user", since = "4.4", authorized = {RoleType.Admin})
private Boolean forDisplay;
@SerializedName(ApiConstants.DISTRIBUTED_VPC_ROUTER)
@Param(description = "is VPC uses distributed router for one hop forwarding and host based network ACL's")
private boolean usesDistributedRouter;
@SerializedName((ApiConstants.REGION_LEVEL_VPC))
@Param(description = "true if VPC is region level")
private Boolean regionLevelVpc;
public void setId(String id) {
this.id = id;
}
@ -199,4 +207,12 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons
public void setForDisplay(Boolean forDisplay) {
this.forDisplay = forDisplay;
}
public void setRegionLevelVpc(Boolean regionLevelVpc) {
this.regionLevelVpc = regionLevelVpc;
}
public void setUsesDistributedRouter(Boolean usesDistributedRouter) {
this.usesDistributedRouter = usesDistributedRouter;
}
}

View File

@ -1,28 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
DBUSER=cloud
DBPW=cloud
MSLOG=vmops.log
APISERVERLOG=api.log
DBHOST=localhost
DBROOTPW=
AGENTLOGDIR=logs
AGENTLOG=logs/agent.log
MSMNTDIR=/mnt
COMPONENTS-SPEC=components-simulator.xml
AWSAPILOG=awsapi.log

View File

@ -0,0 +1,62 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.agent.api;
import com.cloud.agent.api.routing.GetRouterAlertsCommand;
public class GetRouterAlertsAnswer extends Answer {
String routerName;
String[] alerts;
String timeStamp;
protected GetRouterAlertsAnswer() {
}
public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, String alerts[], String timeStamp) {
super(cmd, true, null);
this.alerts = alerts;
this.timeStamp = timeStamp;
}
public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, Exception ex) {
super(cmd, ex);
}
public void setAlerts(String[] alerts) {
this.alerts = alerts;
}
public String[] getAlerts() {
return alerts;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public String getTimeStamp() {
return timeStamp;
}
public String getRouterName() {
return routerName;
}
}

View File

@ -16,26 +16,38 @@
// under the License.
package com.cloud.agent.api;
import java.util.List;
import java.util.Map;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.utils.Pair;
public class MigrateWithStorageCommand extends Command {
VirtualMachineTO vm;
Map<VolumeTO, StorageFilerTO> volumeToFiler;
List<Pair<VolumeTO, StorageFilerTO>> volumeToFilerAsList;
String tgtHost;
public MigrateWithStorageCommand(VirtualMachineTO vm, Map<VolumeTO, StorageFilerTO> volumeToFiler) {
this.vm = vm;
this.volumeToFiler = volumeToFiler;
this.volumeToFilerAsList = null;
this.tgtHost = null;
}
public MigrateWithStorageCommand(VirtualMachineTO vm, Map<VolumeTO, StorageFilerTO> volumeToFiler, String tgtHost) {
this.vm = vm;
this.volumeToFiler = volumeToFiler;
this.volumeToFilerAsList = null;
this.tgtHost = tgtHost;
}
public MigrateWithStorageCommand(VirtualMachineTO vm, List<Pair<VolumeTO, StorageFilerTO>> volumeToFilerAsList, String tgtHost) {
this.vm = vm;
this.volumeToFiler = null;
this.volumeToFilerAsList = volumeToFilerAsList;
this.tgtHost = tgtHost;
}
@ -47,6 +59,10 @@ public class MigrateWithStorageCommand extends Command {
return volumeToFiler;
}
public List<Pair<VolumeTO, StorageFilerTO>> getVolumeToFilerAsList() {
return volumeToFilerAsList;
}
public String getTargetHost() {
return tgtHost;
}

View File

@ -21,6 +21,7 @@ public class ModifyVmNicConfigCommand extends Command {
String vmName;
int vlan;
String macAddress;
int index;
protected ModifyVmNicConfigCommand() {
}
@ -30,6 +31,12 @@ public class ModifyVmNicConfigCommand extends Command {
this.macAddress = macAddress;
}
public ModifyVmNicConfigCommand(String vmName, int vlan, int position) {
this.vmName = vmName;
this.vlan = vlan;
this.index = position;
}
public String getVmName() {
return vmName;
}

View File

@ -0,0 +1,46 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.agent.api.routing;
public class GetRouterAlertsCommand extends NetworkElementCommand {
private String previousAlertTimeStamp;
protected GetRouterAlertsCommand() {
}
@Override
public boolean executeInSequence() {
return false;
}
public GetRouterAlertsCommand(String timeStamp) {
this.previousAlertTimeStamp = timeStamp;
}
public String getPreviousAlertTimeStamp() {
return previousAlertTimeStamp;
}
@Override
public boolean isQuery() {
return true;
}
}

View File

@ -32,6 +32,8 @@ import com.cloud.agent.api.routing.DeleteIpAliasCommand;
import com.cloud.agent.api.routing.DhcpEntryCommand;
import com.cloud.agent.api.routing.DnsMasqConfigCommand;
import com.cloud.agent.api.routing.GroupAnswer;
import com.cloud.agent.api.routing.GetRouterAlertsCommand;
import com.cloud.agent.api.GetRouterAlertsAnswer;
import com.cloud.agent.api.routing.IpAliasTO;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.IpAssocVpcCommand;
@ -102,6 +104,7 @@ public class VirtualRoutingResource {
protected static final String IPASSOC = "ipassoc.sh";
protected static final String LB = "loadbalancer.sh";
protected static final String MONITOR_SERVICE = "monitor_service.sh";
protected static final String ROUTER_ALERTS = "getRouterAlerts.sh";
protected static final String PASSWORD = "savepassword.sh";
protected static final String RVR_CHECK = "checkrouter.sh";
protected static final String RVR_BUMPUP_PRI = "bumpup_priority.sh";
@ -275,7 +278,9 @@ public class VirtualRoutingResource {
} else if (cmd instanceof GetDomRVersionCmd) {
return execute((GetDomRVersionCmd)cmd);
} else if (cmd instanceof CheckS2SVpnConnectionsCommand) {
return execute((CheckS2SVpnConnectionsCommand)cmd);
return execute((CheckS2SVpnConnectionsCommand) cmd);
} else if (cmd instanceof GetRouterAlertsCommand) {
return execute((GetRouterAlertsCommand)cmd);
} else {
s_logger.error("Unknown query command in VirtualRoutingResource!");
return Answer.createUnsupportedCommandAnswer(cmd);
@ -642,6 +647,29 @@ public class VirtualRoutingResource {
return new CheckS2SVpnConnectionsAnswer(cmd, result.isSuccess(), result.getDetails());
}
private GetRouterAlertsAnswer execute(GetRouterAlertsCommand cmd) {
String args = null;
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
if (cmd.getPreviousAlertTimeStamp() != null) {
args = cmd.getPreviousAlertTimeStamp();
}
ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_ALERTS, args);
String alerts[] = null;
String lastAlertTimestamp = null;
// CallHostPlugin results "success" when there are no alerts on virtual router
if (result.isSuccess()) {
if (!result.getDetails().isEmpty() && !result.getDetails().equals("No Alerts")) {
alerts = result.getDetails().split("\\\\n");
String[] lastAlert = alerts[alerts.length - 1].split(" ");
lastAlertTimestamp = lastAlert[0] + " " + lastAlert[1];
}
}
return new GetRouterAlertsAnswer(cmd, alerts, lastAlertTimestamp);
}
protected Answer execute(CheckRouterCommand cmd) {
final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.RVR_CHECK, null);
if (!result.isSuccess()) {
@ -732,6 +760,21 @@ public class VirtualRoutingResource {
return cfg;
}
protected List<ConfigItem> generateConfig(GetRouterAlertsCommand cmd) {
LinkedList<ConfigItem> cfg = new LinkedList<>();
String args = null;
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
if (cmd.getPreviousAlertTimeStamp() != null) {
args = "getRouterAlerts.sh " + routerIp + " " + cmd.getPreviousAlertTimeStamp();
} else {
args = "getRouterAlerts.sh " + routerIp;
}
cfg.add(new ConfigItem(VRScripts.ROUTER_ALERTS, args));
return cfg;
}
protected List<ConfigItem> generateConfig(SetupGuestNetworkCommand cmd) {
LinkedList<ConfigItem> cfg = new LinkedList<>();

View File

@ -21,5 +21,6 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
public enum StorageAction {
TAKESNAPSHOT,
BACKUPSNAPSHOT,
DELETESNAPSHOT
DELETESNAPSHOT,
MIGRATEVOLUME
}

View File

@ -44,7 +44,7 @@ public interface CapacityManager {
"Percentage (as a value between 0 and 1) of storage utilization above which allocators will disable using the pool for low storage available.", true,
ConfigKey.Scope.Zone);
static final ConfigKey<Double> StorageOverprovisioningFactor = new ConfigKey<Double>("Storage", Double.class, StorageOverprovisioningFactorCK, "2",
"Used for storage overprovisioning calculation; available storage will be (actualStorageSize * storage.overprovisioning.factor)", true, ConfigKey.Scope.Zone);
"Used for storage overprovisioning calculation; available storage will be (actualStorageSize * storage.overprovisioning.factor)", true, ConfigKey.Scope.StoragePool);
static final ConfigKey<Double> StorageAllocatedCapacityDisableThreshold =
new ConfigKey<Double>(
"Alert",

View File

@ -291,7 +291,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
public void setHostAllocators(List<HostAllocator> hostAllocators) {
this.hostAllocators = hostAllocators;
hostAllocators = hostAllocators;
}
protected List<StoragePoolAllocator> _storagePoolAllocators;
@ -3243,9 +3243,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@SuppressWarnings("unchecked")
public AgentVmInfo(String name, VMInstanceVO vm, State state, String host) {
this.name = name;
this.state = state;
this.vm = vm;
name = name;
state = state;
vm = vm;
hostUuid = host;
}
@ -4100,7 +4100,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
VirtualMachine.Type.Instance, vmId);
if (pendingWorkJobs.size() == 0 || !_haMgr.hasPendingHaWork(vmId)) {
if (pendingWorkJobs.size() == 0 && !_haMgr.hasPendingHaWork(vmId)) {
// there is no pending operation job
VMInstanceVO vm = _vmDao.findById(vmId);
if (vm != null) {
@ -4407,7 +4407,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
@Override
public boolean checkCondition() {
VMInstanceVO instance = _vmDao.findById(vmId);
if (instance.getPowerState() == desiredPowerState && (srcHostIdForMigration != null && srcHostIdForMigration.equals(instance.getPowerHostId())))
if ((instance.getPowerState() == desiredPowerState && srcHostIdForMigration == null) ||
(instance.getPowerState() == desiredPowerState && (srcHostIdForMigration != null && instance.getPowerHostId() != srcHostIdForMigration)))
return true;
return false;
}

View File

@ -157,6 +157,7 @@
<bean id="firewallRulesCidrsDaoImpl" class="com.cloud.network.dao.FirewallRulesCidrsDaoImpl" />
<bean id="firewallRulesDaoImpl" class="com.cloud.network.dao.FirewallRulesDaoImpl" />
<bean id="MonitoringServiceDaoImpl" class="com.cloud.network.dao.MonitoringServiceDaoImpl" />
<bean id="OpRouterMonitorServiceDaoImpl" class="com.cloud.network.dao.OpRouterMonitorServiceDaoImpl" />
<bean id="globalLoadBalancerDaoImpl" class="org.apache.cloudstack.region.gslb.GlobalLoadBalancerDaoImpl" />
<bean id="globalLoadBalancerLbRuleMapDaoImpl" class="org.apache.cloudstack.region.gslb.GlobalLoadBalancerLbRuleMapDaoImpl" />
<bean id="guestOSCategoryDaoImpl" class="com.cloud.storage.dao.GuestOSCategoryDaoImpl" />

View File

@ -953,46 +953,49 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
int result = update(ub, sc, null);
assert result <= 1 : "How can this update " + result + " rows? ";
if (status_logger.isDebugEnabled() && result == 0) {
if (result == 0) {
HostVO ho = findById(host.getId());
assert ho != null : "How how how? : " + host.getId();
StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString());
str.append(". Name=").append(host.getName());
str.append("; New=[status=")
.append(newStatus.toString())
.append(":msid=")
.append(newStatus.lostConnection() ? "null" : host.getManagementServerId())
.append(":lastpinged=")
.append(host.getLastPinged())
.append("]");
str.append("; Old=[status=")
.append(oldStatus.toString())
.append(":msid=")
.append(host.getManagementServerId())
.append(":lastpinged=")
.append(oldPingTime)
.append("]");
str.append("; DB=[status=")
.append(vo.getStatus().toString())
.append(":msid=")
.append(vo.getManagementServerId())
.append(":lastpinged=")
.append(vo.getLastPinged())
.append(":old update count=")
.append(oldUpdateCount)
.append("]");
status_logger.debug(str.toString());
} else {
StringBuilder msg = new StringBuilder("Agent status update: [");
msg.append("id = " + host.getId());
msg.append("; name = " + host.getName());
msg.append("; old status = " + oldStatus);
msg.append("; event = " + event);
msg.append("; new status = " + newStatus);
msg.append("; old update count = " + oldUpdateCount);
msg.append("; new update count = " + newUpdateCount + "]");
status_logger.debug(msg.toString());
if (status_logger.isDebugEnabled()) {
StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString());
str.append(". Name=").append(host.getName());
str.append("; New=[status=")
.append(newStatus.toString())
.append(":msid=")
.append(newStatus.lostConnection() ? "null" : host.getManagementServerId())
.append(":lastpinged=")
.append(host.getLastPinged())
.append("]");
str.append("; Old=[status=").append(oldStatus.toString()).append(":msid=").append(host.getManagementServerId()).append(":lastpinged=").append(oldPingTime)
.append("]");
str.append("; DB=[status=")
.append(vo.getStatus().toString())
.append(":msid=")
.append(vo.getManagementServerId())
.append(":lastpinged=")
.append(vo.getLastPinged())
.append(":old update count=")
.append(oldUpdateCount)
.append("]");
status_logger.debug(str.toString());
} else {
StringBuilder msg = new StringBuilder("Agent status update: [");
msg.append("id = " + host.getId());
msg.append("; name = " + host.getName());
msg.append("; old status = " + oldStatus);
msg.append("; event = " + event);
msg.append("; new status = " + newStatus);
msg.append("; old update count = " + oldUpdateCount);
msg.append("; new update count = " + newUpdateCount + "]");
status_logger.debug(msg.toString());
}
if (ho.getState() == newStatus) {
status_logger.debug("Host " + ho.getName() + " state has already been updated to " + newStatus);
return true;
}
}
return result > 0;

View File

@ -34,4 +34,6 @@ public interface LoadBalancerVMMapDao extends GenericDao<LoadBalancerVMMapVO, Lo
LoadBalancerVMMapVO findByLoadBalancerIdAndVmId(long loadBalancerId, long instanceId);
boolean isVmAttachedToLoadBalancer(long loadBalancerId);
List<LoadBalancerVMMapVO> listByInstanceIp(String instanceIp);
}

View File

@ -59,6 +59,14 @@ public class LoadBalancerVMMapDaoImpl extends GenericDaoBase<LoadBalancerVMMapVO
return listBy(sc);
}
@Override
public List<LoadBalancerVMMapVO> listByInstanceIp(String instanceIp) {
SearchCriteria<LoadBalancerVMMapVO> sc = createSearchCriteria();
sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp);
return listBy(sc);
}
@Override
public List<LoadBalancerVMMapVO> listByLoadBalancerId(long loadBalancerId) {
SearchCriteria<LoadBalancerVMMapVO> sc = createSearchCriteria();

View File

@ -39,6 +39,9 @@ public class LoadBalancerVMMapVO implements InternalIdentity {
@Column(name = "instance_id")
private long instanceId;
@Column(name = "instance_ip")
private String instanceIp;
@Column(name = "revoke")
private boolean revoke = false;
@ -59,6 +62,13 @@ public class LoadBalancerVMMapVO implements InternalIdentity {
this.revoke = revoke;
}
public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, String vmIp, boolean revoke) {
this.loadBalancerId = loadBalancerId;
this.instanceId = instanceId;
this.instanceIp = vmIp;
this.revoke = revoke;
}
@Override
public long getId() {
return id;
@ -87,4 +97,13 @@ public class LoadBalancerVMMapVO implements InternalIdentity {
public void setState(String state) {
this.state = state;
}
public String getInstanceIp() {
return instanceIp;
}
public void setInstanceIp(String instanceIp) {
this.instanceIp = instanceIp;
}
}

View File

@ -167,6 +167,9 @@ public class NetworkVO implements Network {
@Column(name = "network_acl_id")
Long networkACLId;
@Column(name = "streched_l2")
boolean strechedL2Network = false;
public NetworkVO() {
uuid = UUID.randomUUID().toString();
}
@ -589,4 +592,13 @@ public class NetworkVO implements Network {
public IAMEntityType getEntityType() {
return IAMEntityType.Network;
}
@Override
public boolean isStrechedL2Network() {
return strechedL2Network;
}
public void setStrechedL2Network(boolean strechedL2Network) {
this.strechedL2Network = strechedL2Network;
}
}

View File

@ -0,0 +1,25 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.network.dao;
import com.cloud.utils.db.GenericDao;
public interface OpRouterMonitorServiceDao extends GenericDao<OpRouterMonitorServiceVO, Long> {
}

View File

@ -0,0 +1,28 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.network.dao;
import com.cloud.utils.db.GenericDaoBase;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
@Component
@Local(value=OpRouterMonitorServiceDao.class)
public class OpRouterMonitorServiceDaoImpl extends GenericDaoBase<OpRouterMonitorServiceVO, Long> implements OpRouterMonitorServiceDao {
}

View File

@ -0,0 +1,69 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.network.dao;
import org.apache.cloudstack.api.InternalIdentity;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;
import javax.persistence.Column;
@Entity
@Table(name = "op_router_monitoring_services")
public class OpRouterMonitorServiceVO implements InternalIdentity {
@Id
@Column(name="vm_id")
Long id;
@Column(name="router_name")
private String name;
@Column(name="last_alert_timestamp")
private String lastAlertTimestamp;
public OpRouterMonitorServiceVO() {}
public OpRouterMonitorServiceVO(long vmId, String name, String lastAlertTimestamp) {
this.id = vmId;
this.name = name;
this.lastAlertTimestamp = lastAlertTimestamp;
}
@Override
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getLastAlertTimestamp() {
return lastAlertTimestamp;
}
public void setLastAlertTimestamp (String timestamp) {
this.lastAlertTimestamp = timestamp;
}
}

View File

@ -67,6 +67,12 @@ public class VpcOfferingVO implements VpcOffering {
@Column(name = "service_offering_id")
Long serviceOfferingId;
@Column(name = "supports_distributed_router")
boolean supportsDistributedRouter=false;
@Column(name = "supports_region_level_vpc")
boolean offersRegionLevelVPC = false;
public VpcOfferingVO() {
this.uuid = UUID.randomUUID().toString();
}
@ -80,9 +86,12 @@ public class VpcOfferingVO implements VpcOffering {
this.state = State.Disabled;
}
public VpcOfferingVO(String name, String displayText, boolean isDefault, Long serviceOfferingId) {
public VpcOfferingVO(String name, String displayText, boolean isDefault, Long serviceOfferingId,
boolean supportsDistributedRouter, boolean offersRegionLevelVPC) {
this(name, displayText, serviceOfferingId);
this.isDefault = isDefault;
this.supportsDistributedRouter = supportsDistributedRouter;
this.offersRegionLevelVPC = offersRegionLevelVPC;
}
@Override
@ -145,4 +154,14 @@ public class VpcOfferingVO implements VpcOffering {
public Long getServiceOfferingId() {
return serviceOfferingId;
}
@Override
public boolean supportsDistributedRouter() {
return supportsDistributedRouter;
}
@Override
public boolean offersRegionLevelVPC() {
return offersRegionLevelVPC;
}
}

View File

@ -81,11 +81,18 @@ public class VpcVO implements Vpc {
@Column(name = "display", updatable = true, nullable = false)
protected boolean display = true;
@Column(name="uses_distributed_router")
boolean usesDistributedRouter = false;
@Column(name = "region_level_vpc")
boolean regionLevelVpc = false;
public VpcVO() {
uuid = UUID.randomUUID().toString();
}
public VpcVO(long zoneId, String name, String displayText, long accountId, long domainId, long vpcOffId, String cidr, String networkDomain) {
public VpcVO(long zoneId, String name, String displayText, long accountId, long domainId, long vpcOffId, String cidr,
String networkDomain, boolean useDistributedRouter, boolean regionLevelVpc) {
this.zoneId = zoneId;
this.name = name;
this.displayText = displayText;
@ -95,7 +102,9 @@ public class VpcVO implements Vpc {
uuid = UUID.randomUUID().toString();
state = State.Enabled;
this.networkDomain = networkDomain;
vpcOfferingId = vpcOffId;
this.vpcOfferingId = vpcOffId;
this.usesDistributedRouter = useDistributedRouter;
this.regionLevelVpc = regionLevelVpc;
}
@Override
@ -188,6 +197,11 @@ public class VpcVO implements Vpc {
this.uuid = uuid;
}
@Override
public boolean isRegionLevelVpc() {
return regionLevelVpc;
}
public void setDisplay(boolean display) {
this.display = display;
@ -202,4 +216,9 @@ public class VpcVO implements Vpc {
public IAMEntityType getEntityType() {
return IAMEntityType.Vpc;
}
@Override
public boolean usesDistributedRouter() {
return usesDistributedRouter;
}
}

View File

@ -139,6 +139,9 @@ public class NetworkOfferingVO implements NetworkOffering {
@Column(name = "keep_alive_enabled")
boolean keepAliveEnabled = false;
@Column(name="supports_streched_l2")
boolean supportsStrechedL2 = false;
@Override
public String getDisplayText() {
return displayText;
@ -331,7 +334,7 @@ public class NetworkOfferingVO implements NetworkOffering {
public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps,
Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb,
boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, boolean specifyIpRanges, boolean inline, boolean isPersistent,
boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy) {
boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2) {
this(name,
displayText,
trafficType,
@ -356,6 +359,7 @@ public class NetworkOfferingVO implements NetworkOffering {
this.inline = inline;
this.eipAssociatePublicIp = associatePublicIP;
this.egressdefaultpolicy = egressdefaultpolicy;
this.supportsStrechedL2 = supportsStrechedL2;
}
public NetworkOfferingVO() {
@ -486,4 +490,9 @@ public class NetworkOfferingVO implements NetworkOffering {
public void setPublicLb(boolean publicLb) {
this.publicLb = publicLb;
}
@Override
public boolean getSupportsStrechedL2() {
return supportsStrechedL2;
}
}

View File

@ -452,41 +452,29 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
ub.set(vmi, _updateTimeAttr, new Date());
int result = update(vmi, sc);
if (result == 0 && s_logger.isDebugEnabled()) {
if (result == 0) {
VMInstanceVO vo = findByIdIncludingRemoved(vm.getId());
if (vo != null) {
StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString());
str.append(": DB Data={Host=")
.append(vo.getHostId())
.append("; State=")
.append(vo.getState().toString())
.append("; updated=")
.append(vo.getUpdated())
.append("; time=")
.append(vo.getUpdateTime());
str.append("} New Data: {Host=")
.append(vm.getHostId())
.append("; State=")
.append(vm.getState().toString())
.append("; updated=")
.append(vmi.getUpdated())
.append("; time=")
.append(vo.getUpdateTime());
str.append("} Stale Data: {Host=")
.append(oldHostId)
.append("; State=")
.append(oldState)
.append("; updated=")
.append(oldUpdated)
.append("; time=")
.append(oldUpdateDate)
.append("}");
s_logger.debug(str.toString());
if (s_logger.isDebugEnabled()) {
if (vo != null) {
StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString());
str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append(vo.getUpdated())
.append("; time=").append(vo.getUpdateTime());
str.append("} New Data: {Host=").append(vm.getHostId()).append("; State=").append(vm.getState().toString()).append("; updated=").append(vmi.getUpdated())
.append("; time=").append(vo.getUpdateTime());
str.append("} Stale Data: {Host=").append(oldHostId).append("; State=").append(oldState).append("; updated=").append(oldUpdated).append("; time=")
.append(oldUpdateDate).append("}");
s_logger.debug(str.toString());
} else {
s_logger.debug("Unable to update the vm id=" + vm.getId() + "; the vm either doesn't exist or already removed");
} else {
s_logger.debug("Unable to update the vm id=" + vm.getId() + "; the vm either doesn't exist or already removed");
}
}
if (vo != null && vo.getState() == newState) {
// allow for concurrent update if target state has already been matched
s_logger.debug("VM " + vo.getInstanceName() + " state has been already been updated to " + newState);
return true;
}
}
return result > 0;

View File

@ -30,5 +30,6 @@
class="org.apache.cloudstack.storage.motion.AncientDataMotionStrategy" />
<bean id="xenserverStorageMotionStrategy"
class="org.apache.cloudstack.storage.motion.XenServerStorageMotionStrategy" />
<bean id="hypervStorageMotionStrategy"
class="org.apache.cloudstack.storage.motion.HypervStorageMotionStrategy" />
</beans>

View File

@ -372,7 +372,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
VolumeInfo volume = (VolumeInfo)srcData;
StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destData.getDataStore().getId(), DataStoreRole.Primary);
MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool, volume.getAttachedVmName());
EndPoint ep = selector.select(volume.getDataStore());
EndPoint ep = selector.select(srcData, StorageAction.MIGRATEVOLUME);
Answer answer = null;
if (ep == null) {
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";

View File

@ -305,6 +305,15 @@ public class DefaultEndPointSelector implements EndPointSelector {
return getEndPointFromHostId(hostId);
}
}
} else if (action == StorageAction.MIGRATEVOLUME) {
VolumeInfo volume = (VolumeInfo)object;
if (volume.getHypervisorType() == Hypervisor.HypervisorType.Hyperv) {
VirtualMachine vm = volume.getAttachedVM();
if ((vm != null) && (vm.getState() == VirtualMachine.State.Running)) {
Long hostId = vm.getHostId();
return getEndPointFromHostId(hostId);
}
}
}
return select(object);
}

View File

@ -77,6 +77,7 @@ import com.cloud.host.Host;
import com.cloud.host.dao.HostDao;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
@ -814,9 +815,16 @@ public class VolumeServiceImpl implements VolumeService {
protected VolumeVO duplicateVolumeOnAnotherStorage(Volume volume, StoragePool pool) {
Long lastPoolId = volume.getPoolId();
String folder = pool.getPath();
// For SMB, pool credentials are also stored in the uri query string. We trim the query string
// part here to make sure the credentials do not get stored in the db unencrypted.
if (pool.getPoolType() == StoragePoolType.SMB && folder != null && folder.contains("?")) {
folder = folder.substring(0, folder.indexOf("?"));
}
VolumeVO newVol = new VolumeVO(volume);
newVol.setPoolId(pool.getId());
newVol.setFolder(pool.getPath());
newVol.setFolder(folder);
newVol.setPodId(pool.getPodId());
newVol.setPoolId(pool.getId());
newVol.setLastPoolId(lastPoolId);

View File

@ -256,13 +256,17 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
}
});
for (Long id : wakeupList) {
// TODO, we assume that all jobs in this category is API job only
AsyncJobVO jobToWakeup = _jobDao.findById(id);
if (jobToWakeup != null && (jobToWakeup.getPendingSignals() & AsyncJob.Constants.SIGNAL_MASK_WAKEUP) != 0)
scheduleExecution(jobToWakeup, false);
}
//
// disable wakeup scheduling now, since all API jobs are currently using block-waiting for sub-jobs
//
/*
for (Long id : wakeupList) {
// TODO, we assume that all jobs in this category is API job only
AsyncJobVO jobToWakeup = _jobDao.findById(id);
if (jobToWakeup != null && (jobToWakeup.getPendingSignals() & AsyncJob.Constants.SIGNAL_MASK_WAKEUP) != 0)
scheduleExecution(jobToWakeup, false);
}
*/
_messageBus.publish(null, AsyncJob.Topics.JOB_STATE, PublishScope.GLOBAL, jobId);
}

View File

@ -173,33 +173,35 @@ namespace HypervResource
PrimaryDataStoreTO store = this.primaryDataStore;
if (store.isLocal)
{
fileName = Path.Combine(store.Path, this.uuid);
String volume = this.path;
if (String.IsNullOrEmpty(volume))
{
volume = this.uuid;
}
fileName = Path.Combine(store.Path, volume);
}
else
{
fileName = @"\\" + store.uri.Host + store.uri.LocalPath + @"\" + this.uuid;
String volume = this.path;
if (String.IsNullOrEmpty(volume))
{
volume = this.uuid;
}
fileName = @"\\" + store.uri.Host + store.uri.LocalPath + @"\" + volume;
fileName = Utils.NormalizePath(fileName);
}
}
else if (this.nfsDataStore != null)
{
if (this.path != null && File.Exists(this.path))
fileName = this.nfsDataStore.UncPath;
if (this.path != null)
{
fileName = this.path;
fileName = Utils.NormalizePath(fileName + @"\" + this.path);
}
else
{
fileName = this.nfsDataStore.UncPath;
if (this.path != null)
{
fileName += @"\" + this.path;
}
fileName = Utils.NormalizePath(fileName);
if (Directory.Exists(fileName))
{
fileName = Utils.NormalizePath(fileName + @"\" + this.uuid);
}
if (fileName != null && !File.Exists(fileName))
{
fileName = Utils.NormalizePath(fileName + @"\" + this.uuid);
}
}
else
@ -344,8 +346,17 @@ namespace HypervResource
}
else if (this.nfsDataStoreTO != null)
{
NFSTO store = this.nfsDataStoreTO;
fileName = store.UncPath + @"\" + this.path + @"\" + this.uuid;
fileName = this.nfsDataStoreTO.UncPath;
if (this.path != null)
{
fileName = Utils.NormalizePath(fileName + @"\" + this.path);
}
if (fileName != null && !File.Exists(fileName))
{
fileName = Utils.NormalizePath(fileName + @"\" + this.uuid);
}
if (!this.format.Equals("RAW"))
{
fileName = fileName + '.' + this.format.ToLowerInvariant();
@ -769,6 +780,8 @@ namespace HypervResource
public const string ManageSnapshotCommand = "com.cloud.agent.api.ManageSnapshotCommand";
public const string MigrateAnswer = "com.cloud.agent.api.MigrateAnswer";
public const string MigrateCommand = "com.cloud.agent.api.MigrateCommand";
public const string MigrateWithStorageAnswer = "com.cloud.agent.api.MigrateWithStorageAnswer";
public const string MigrateWithStorageCommand = "com.cloud.agent.api.MigrateWithStorageCommand";
public const string ModifySshKeysCommand = "com.cloud.agent.api.ModifySshKeysCommand";
public const string ModifyStoragePoolAnswer = "com.cloud.agent.api.ModifyStoragePoolAnswer";
public const string ModifyStoragePoolCommand = "com.cloud.agent.api.ModifyStoragePoolCommand";
@ -853,6 +866,8 @@ namespace HypervResource
public const string CreateCommand = "com.cloud.agent.api.storage.CreateCommand";
public const string CreatePrivateTemplateAnswer = "com.cloud.agent.api.storage.CreatePrivateTemplateAnswer";
public const string DestroyCommand = "com.cloud.agent.api.storage.DestroyCommand";
public const string MigrateVolumeAnswer = "com.cloud.agent.api.storage.MigrateVolumeAnswer";
public const string MigrateVolumeCommand = "com.cloud.agent.api.storage.MigrateVolumeCommand";
public const string PrimaryStorageDownloadAnswer = "com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer";
public const string PrimaryStorageDownloadCommand = "com.cloud.agent.api.storage.PrimaryStorageDownloadCommand";
public const string ResizeVolumeAnswer = "com.cloud.agent.api.storage.ResizeVolumeAnswer";

View File

@ -992,6 +992,7 @@ namespace HypervResource
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
{
logger.Info(CloudStackTypes.PlugNicCommand + cmd.ToString());
object ansContent = new
{
result = true,
@ -1187,7 +1188,7 @@ namespace HypervResource
volumePath = Utils.NormalizePath(volumePath);
Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
}
volume.path = volumePath;
volume.path = volume.uuid;
wmiCallsV2.CreateDynamicVirtualHardDisk(volumeSize, volumePath);
if (File.Exists(volumePath))
{
@ -1299,9 +1300,16 @@ namespace HypervResource
String vmName = cmd.vmName;
uint vlan = (uint)cmd.vlan;
string macAddress = cmd.macAddress;
wmiCallsV2.ModifyVmVLan(vmName, vlan, macAddress);
result = true;
uint pos = cmd.index;
if (macAddress != null)
{
wmiCallsV2.ModifyVmVLan(vmName, vlan, macAddress);
}
else if (pos > 1)
{
wmiCallsV2.ModifyVmVLan(vmName, vlan, pos);
}
result = true;
object ansContent = new
{
@ -1578,7 +1586,7 @@ namespace HypervResource
{
// TODO: thin provision instead of copying the full file.
File.Copy(srcFile, destFile);
destVolumeObjectTO.path = destFile;
destVolumeObjectTO.path = destVolumeObjectTO.uuid;
JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, destVolumeObjectTO);
newData = ansObj;
result = true;
@ -1612,8 +1620,25 @@ namespace HypervResource
// doesn't do anything if the directory is already present.
Directory.CreateDirectory(Path.GetDirectoryName(destFile));
File.Copy(srcFile, destFile);
if (srcVolumeObjectTO.nfsDataStore != null && srcVolumeObjectTO.primaryDataStore == null)
{
logger.Info("Copied volume from secondary data store to primary. Path: " + destVolumeObjectTO.path);
}
else if (srcVolumeObjectTO.primaryDataStore != null && srcVolumeObjectTO.nfsDataStore == null)
{
destVolumeObjectTO.path = destVolumeObjectTO.path + "/" + destVolumeObjectTO.uuid;
if (destVolumeObjectTO.format != null)
{
destVolumeObjectTO.path += "." + destVolumeObjectTO.format.ToLower();
}
}
else
{
logger.Error("Destination volume path wasn't set. Unsupported source volume data store.");
}
// Create volumeto object deserialize and send it
destVolumeObjectTO.path = destFile;
JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, destVolumeObjectTO);
newData = ansObj;
result = true;
@ -1656,7 +1681,11 @@ namespace HypervResource
TemplateObjectTO destTemplateObject = new TemplateObjectTO();
destTemplateObject.size = srcVolumeObjectTO.size.ToString();
destTemplateObject.format = srcVolumeObjectTO.format;
destTemplateObject.path = destFile;
destTemplateObject.path = destTemplateObjectTO.path + "/" + destTemplateObjectTO.uuid;
if (destTemplateObject.format != null)
{
destTemplateObject.path += "." + destTemplateObject.format.ToLower();
}
destTemplateObject.nfsDataStoreTO = destTemplateObjectTO.nfsDataStoreTO;
destTemplateObject.checksum = destTemplateObjectTO.checksum;
newData = destTemplateObject;
@ -1990,6 +2019,113 @@ namespace HypervResource
}
}
// POST api/HypervResource/MigrateVolumeCommand
[HttpPost]
[ActionName(CloudStackTypes.MigrateVolumeCommand)]
public JContainer MigrateVolumeCommand([FromBody]dynamic cmd)
{
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
{
logger.Info(CloudStackTypes.MigrateVolumeCommand + cmd.ToString());
string details = null;
bool result = false;
try
{
string vm = (string)cmd.attachedVmName;
string volume = (string)cmd.volumePath;
wmiCallsV2.MigrateVolume(vm, volume, GetStoragePoolPath(cmd.pool));
result = true;
}
catch (Exception sysEx)
{
details = CloudStackTypes.MigrateVolumeCommand + " failed due to " + sysEx.Message;
logger.Error(details, sysEx);
}
object ansContent = new
{
result = result,
volumePath = (string)cmd.volumePath,
details = details,
contextMap = contextMap
};
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.MigrateVolumeAnswer);
}
}
// POST api/HypervResource/MigrateWithStorageCommand
[HttpPost]
[ActionName(CloudStackTypes.MigrateWithStorageCommand)]
public JContainer MigrateWithStorageCommand([FromBody]dynamic cmd)
{
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
{
logger.Info(CloudStackTypes.MigrateWithStorageCommand + cmd.ToString());
string details = null;
bool result = false;
List<dynamic> volumeTos = new List<dynamic>();
try
{
string vm = (string)cmd.vm.name;
string destination = (string)cmd.tgtHost;
var volumeToPoolList = cmd.volumeToFilerAsList;
var volumeToPool = new Dictionary<string, string>();
foreach (var item in volumeToPoolList)
{
volumeTos.Add(item.t);
string poolPath = GetStoragePoolPath(item.u);
volumeToPool.Add((string)item.t.path, poolPath);
}
wmiCallsV2.MigrateVmWithVolume(vm, destination, volumeToPool);
result = true;
}
catch (Exception sysEx)
{
details = CloudStackTypes.MigrateWithStorageCommand + " failed due to " + sysEx.Message;
logger.Error(details, sysEx);
}
object ansContent = new
{
result = result,
volumeTos = JArray.FromObject(volumeTos),
details = details,
contextMap = contextMap
};
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.MigrateWithStorageAnswer);
}
}
private string GetStoragePoolPath(dynamic pool)
{
string poolTypeStr = pool.type;
StoragePoolType poolType;
if (!Enum.TryParse<StoragePoolType>(poolTypeStr, out poolType))
{
throw new ArgumentException("Invalid pool type " + poolTypeStr);
}
else if (poolType == StoragePoolType.SMB)
{
NFSTO share = new NFSTO();
String uriStr = "cifs://" + (string)pool.host + (string)pool.path;
share.uri = new Uri(uriStr);
return Utils.NormalizePath(share.UncPath);
}
else if (poolType == StoragePoolType.Filesystem)
{
return pool.path;
}
throw new ArgumentException("Couldn't parse path for pool type " + poolTypeStr);
}
// POST api/HypervResource/StartupCommand
[HttpPost]
[ActionName(CloudStackTypes.StartupCommand)]
@ -2016,7 +2152,8 @@ namespace HypervResource
strtRouteCmd.storageNetmask = subnet;
strtRouteCmd.storageMacAddress = storageNic.GetPhysicalAddress().ToString();
strtRouteCmd.gatewayIpAddress = storageNic.GetPhysicalAddress().ToString();
strtRouteCmd.hypervisorVersion = System.Environment.OSVersion.Version.Major.ToString() + "." +
System.Environment.OSVersion.Version.Minor.ToString();
strtRouteCmd.caps = "hvm";
dynamic details = strtRouteCmd.hostDetails;

View File

@ -40,6 +40,8 @@ namespace HypervResource
void DestroyVm(dynamic jsonObj);
void DestroyVm(string displayName);
void MigrateVm(string vmName, string destination);
void MigrateVolume(string vmName, string volume, string destination);
void MigrateVmWithVolume(string vmName, string destination, Dictionary<string, string> volumeToPool);
void DetachDisk(string displayName, string diskFileName);
ComputerSystem GetComputerSystem(string displayName);
ComputerSystem.ComputerSystemCollection GetComputerSystemCollection();
@ -68,5 +70,6 @@ namespace HypervResource
void SetState(ComputerSystem vm, ushort requiredState);
Dictionary<String, VmState> GetVmSync(String privateIpAddress);
void ModifyVmVLan(string vmName, uint vlanid, string mac);
void ModifyVmVLan(string vmName, uint vlanid, uint pos);
}
}

View File

@ -229,6 +229,7 @@ namespace HypervResource
string errMsg = vmName;
var diskDrives = vmInfo.disks;
var bootArgs = vmInfo.bootArgs;
string defaultvlan = "4094";
// assert
errMsg = vmName + ": missing disk information, array empty or missing, agent expects *at least* one disk for a VM";
@ -391,6 +392,8 @@ namespace HypervResource
string vlan = null;
string isolationUri = nic.isolationUri;
string broadcastUri = nic.broadcastUri;
string nicIp = nic.ip;
string nicNetmask = nic.netmask;
if ( (broadcastUri != null ) || (isolationUri != null && isolationUri.StartsWith("vlan://")))
{
if (broadcastUri != null && broadcastUri.StartsWith("storage"))
@ -415,6 +418,10 @@ namespace HypervResource
throw ex;
}
}
if(nicIp.Equals("0.0.0.0") && nicNetmask.Equals("255.255.255.255") ) {
// this is the extra nic added to VR.
vlan = defaultvlan;
}
if (nicCount == 2)
{
@ -913,7 +920,6 @@ namespace HypervResource
ResourceAllocationSettingData defaultDiskDriveSettings = defaultDiskDriveSettingsObjs.OfType<ResourceAllocationSettingData>().First();
return new ResourceAllocationSettingData((ManagementBaseObject)defaultDiskDriveSettings.LateBoundObject.Clone());
}
// Modify the systemvm nic's VLAN id
public void ModifyVmVLan(string vmName, uint vlanid, String mac)
@ -945,6 +951,24 @@ namespace HypervResource
vlanSettings.LateBoundObject.GetText(TextFormat.CimDtd20)});
}
// Modify the systemvm nic's VLAN id
public void ModifyVmVLan(string vmName, uint vlanid, uint pos)
{
ComputerSystem vm = GetComputerSystem(vmName);
SyntheticEthernetPortSettingData[] nicSettingsViaVm = GetEthernetPortSettings(vm);
// Obtain controller for Hyper-V virtualisation subsystem
VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
EthernetPortAllocationSettingData[] ethernetConnections = GetEthernetConnections(vm);
EthernetSwitchPortVlanSettingData vlanSettings = GetVlanSettings(ethernetConnections[pos]);
//Assign configuration to new NIC
vlanSettings.LateBoundObject["AccessVlanId"] = vlanid;
vlanSettings.LateBoundObject["OperationMode"] = 1;
ModifyFeatureVmResources(vmMgmtSvc, vm, new String[] {
vlanSettings.LateBoundObject.GetText(TextFormat.CimDtd20)});
}
public void AttachIso(string displayName, string iso)
{
logger.DebugFormat("Got request to attach iso {0} to vm {1}", iso, displayName);
@ -1058,6 +1082,125 @@ namespace HypervResource
}
}
/// <summary>
/// Migrates the volume of a vm to a given destination storage
/// </summary>
/// <param name="displayName"></param>
/// <param name="volume"></param>
/// <param name="destination storage pool"></param>
public void MigrateVolume(string vmName, string volume, string destination)
{
ComputerSystem vm = GetComputerSystem(vmName);
VirtualSystemSettingData vmSettings = GetVmSettings(vm);
VirtualSystemMigrationSettingData migrationSettingData = VirtualSystemMigrationSettingData.CreateInstance();
VirtualSystemMigrationService service = GetVirtualisationSystemMigrationService();
StorageAllocationSettingData[] sasd = GetStorageSettings(vm);
string[] rasds = null;
if (sasd != null)
{
rasds = new string[sasd.Length];
uint index = 0;
foreach (StorageAllocationSettingData item in sasd)
{
string vhdFileName = Path.GetFileNameWithoutExtension(item.HostResource[0]);
if (!String.IsNullOrEmpty(vhdFileName) && vhdFileName.Equals(volume))
{
string newVhdPath = Path.Combine(destination, Path.GetFileName(item.HostResource[0]));
item.LateBoundObject["HostResource"] = new string[] { newVhdPath };
item.LateBoundObject["PoolId"] = "";
}
rasds[index++] = item.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20);
}
}
migrationSettingData.LateBoundObject["MigrationType"] = MigrationType.Storage;
migrationSettingData.LateBoundObject["TransportType"] = TransportType.TCP;
string migrationSettings = migrationSettingData.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20);
ManagementPath jobPath;
var ret_val = service.MigrateVirtualSystemToHost(vm.Path, null, migrationSettings, rasds, null, out jobPath);
if (ret_val == ReturnCode.Started)
{
MigrationJobCompleted(jobPath);
}
else if (ret_val != ReturnCode.Completed)
{
var errMsg = string.Format(
"Failed migrating volume {0} of VM {1} (GUID {2}) due to {3}",
volume,
vm.ElementName,
vm.Name,
ReturnCode.ToString(ret_val));
var ex = new WmiException(errMsg);
logger.Error(errMsg, ex);
throw ex;
}
}
/// <summary>
/// Migrates the volume of a vm to a given destination storage
/// </summary>
/// <param name="displayName"></param>
/// <param name="destination host"></param>
/// <param name="volumeToPool"> volume to me migrated to which pool</param>
public void MigrateVmWithVolume(string vmName, string destination, Dictionary<string, string> volumeToPool)
{
ComputerSystem vm = GetComputerSystem(vmName);
VirtualSystemSettingData vmSettings = GetVmSettings(vm);
VirtualSystemMigrationSettingData migrationSettingData = VirtualSystemMigrationSettingData.CreateInstance();
VirtualSystemMigrationService service = GetVirtualisationSystemMigrationService();
StorageAllocationSettingData[] sasd = GetStorageSettings(vm);
string[] rasds = null;
if (sasd != null)
{
rasds = new string[sasd.Length];
uint index = 0;
foreach (StorageAllocationSettingData item in sasd)
{
string vhdFileName = Path.GetFileNameWithoutExtension(item.HostResource[0]);
if (!String.IsNullOrEmpty(vhdFileName) && volumeToPool.ContainsKey(vhdFileName))
{
string newVhdPath = Path.Combine(volumeToPool[vhdFileName], Path.GetFileName(item.HostResource[0]));
item.LateBoundObject["HostResource"] = new string[] { newVhdPath };
item.LateBoundObject["PoolId"] = "";
}
rasds[index++] = item.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20);
}
}
IPAddress addr = IPAddress.Parse(destination);
IPHostEntry entry = Dns.GetHostEntry(addr);
string[] destinationHost = new string[] { destination };
migrationSettingData.LateBoundObject["MigrationType"] = MigrationType.VirtualSystemAndStorage;
migrationSettingData.LateBoundObject["TransportType"] = TransportType.TCP;
migrationSettingData.LateBoundObject["DestinationIPAddressList"] = destinationHost;
string migrationSettings = migrationSettingData.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20);
ManagementPath jobPath;
var ret_val = service.MigrateVirtualSystemToHost(vm.Path, entry.HostName, migrationSettings, rasds, null, out jobPath);
if (ret_val == ReturnCode.Started)
{
MigrationJobCompleted(jobPath);
}
else if (ret_val != ReturnCode.Completed)
{
var errMsg = string.Format(
"Failed migrating VM {0} and its volumes to destination {1} (GUID {2}) due to {3}",
vm.ElementName,
destination,
vm.Name,
ReturnCode.ToString(ret_val));
var ex = new WmiException(errMsg);
logger.Error(errMsg, ex);
throw ex;
}
}
/// <summary>
/// Create new storage media resources, e.g. hard disk images and ISO disk images
/// see http://msdn.microsoft.com/en-us/library/hh859775(v=vs.85).aspx
@ -2081,6 +2224,26 @@ namespace HypervResource
return result.ToArray();
}
public StorageAllocationSettingData[] GetStorageSettings(ComputerSystem vm)
{
// ComputerSystem -> VirtualSystemSettingData -> EthernetPortAllocationSettingData
VirtualSystemSettingData vmSettings = GetVmSettings(vm);
var wmiObjQuery = new RelatedObjectQuery(vmSettings.Path.Path, StorageAllocationSettingData.CreatedClassName);
// NB: default scope of ManagementObjectSearcher is '\\.\root\cimv2', which does not contain
// the virtualisation objects.
var wmiObjectSearch = new ManagementObjectSearcher(vmSettings.Scope, wmiObjQuery);
var wmiObjCollection = new StorageAllocationSettingData.StorageAllocationSettingDataCollection(wmiObjectSearch.Get());
var result = new List<StorageAllocationSettingData>(wmiObjCollection.Count);
foreach (StorageAllocationSettingData item in wmiObjCollection)
{
result.Add(item);
}
return result.ToArray();
}
public EthernetSwitchPortVlanSettingData GetVlanSettings(EthernetPortAllocationSettingData ethernetConnection)
{

View File

@ -36,7 +36,7 @@ namespace CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2 {
private static string CreatedWmiNamespace = "ROOT\\virtualization\\v2";
// Private property to hold the name of WMI class which created this class.
private static string CreatedClassName = "Msvm_StorageAllocationSettingData";
public static string CreatedClassName = "Msvm_StorageAllocationSettingData";
// Private member variable to hold the ManagementScope which is used by the various methods.
private static System.Management.ManagementScope statMgmtScope = null;

View File

@ -45,9 +45,9 @@ public class HypervInvestigator extends AdapterBase implements Investigator {
public Boolean isVmAlive(com.cloud.vm.VirtualMachine vm, Host host) {
Status status = isAgentAlive(host);
if (status == null) {
return null;
return false;
}
return status == Status.Up ? true : null;
return status == Status.Up ? true : false;
}
@Override

View File

@ -19,6 +19,7 @@ package com.cloud.hypervisor.hyperv.discoverer;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -254,7 +255,7 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer
// pool in the database
// This GUID may change.
if (cluster.getGuid() == null) {
cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes()).toString());
cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes(Charset.forName("UTF-8"))).toString());
_clusterDao.update(clusterId, cluster);
}
@ -318,7 +319,7 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer
* @return GUID in form of a string.
*/
public static String calcServerResourceGuid(final String uuidSeed) {
String guid = UUID.nameUUIDFromBytes(uuidSeed.getBytes()).toString();
String guid = UUID.nameUUIDFromBytes(uuidSeed.getBytes(Charset.forName("UTF-8"))).toString();
return guid;
}

View File

@ -34,6 +34,7 @@ import com.cloud.storage.dao.GuestOSDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.hypervisor.hyperv.manager.HypervManager;
import com.cloud.network.NetworkModel;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
@ -74,16 +75,20 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
if(vm.getVirtualMachine().getType() == VirtualMachine.Type.DomainRouter) {
NicProfile publicNicProfile = null;
NicProfile controlNicProfile = null;
NicProfile profile = null;
for(NicProfile nicProfile : nicProfiles) {
if(nicProfile.getTrafficType() == TrafficType.Public) {
publicNicProfile = nicProfile;
break;
}
else if (nicProfile.getTrafficType() == TrafficType.Control) {
controlNicProfile = nicProfile;
}
}
if(publicNicProfile != null) {
if(publicNicProfile != null || controlNicProfile != null) {
NicTO[] nics = to.getNics();
// reserve extra NICs
NicTO[] expandedNics = new NicTO[MaxNicSupported];
int i = 0;
@ -95,18 +100,27 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
}
deviceId++;
long networkId = publicNicProfile.getNetworkId();
long networkId = 0;
if(publicNicProfile != null ) {
networkId= publicNicProfile.getNetworkId();
profile = publicNicProfile;
}
else {
networkId = controlNicProfile.getNetworkId();
profile = controlNicProfile;
}
NetworkVO network = _networkDao.findById(networkId);
// for Hyperv Hot Nic plug is not supported and it will support upto 8 nics.
// creating the VR with extra nics (actual nics(3) + extra nics) will be 8
for(; i < MaxNicSupported; i++) {
NicTO nicTo = new NicTO();
nicTo.setDeviceId(deviceId++);
nicTo.setBroadcastType(publicNicProfile.getBroadcastType());
nicTo.setType(publicNicProfile.getTrafficType());
nicTo.setBroadcastType(BroadcastDomainType.Vlan);
nicTo.setType(TrafficType.Public);
nicTo.setIp("0.0.0.0");
nicTo.setNetmask("255.255.255.255");
nicTo.setName(publicNicProfile.getName());
nicTo.setName(profile.getName());
try {
String mac = _networkMgr.getNextAvailableMacAddressInNetwork(networkId);
@ -114,16 +128,16 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
} catch (InsufficientAddressCapacityException e) {
throw new CloudRuntimeException("unable to allocate mac address on network: " + networkId);
}
nicTo.setDns1(publicNicProfile.getDns1());
nicTo.setDns2(publicNicProfile.getDns2());
if (publicNicProfile.getGateway() != null) {
nicTo.setDns1(profile.getDns1());
nicTo.setDns2(profile.getDns2());
if (publicNicProfile != null && publicNicProfile.getGateway() != null) {
nicTo.setGateway(publicNicProfile.getGateway());
} else {
nicTo.setGateway(network.getGateway());
}
nicTo.setDefaultNic(false);
nicTo.setBroadcastUri(publicNicProfile.getBroadCastUri());
nicTo.setIsolationuri(publicNicProfile.getIsolationUri());
nicTo.setBroadcastUri(profile.getBroadCastUri());
nicTo.setIsolationuri(profile.getIsolationUri());
Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null);
nicTo.setNetworkRateMbps(networkRate);
@ -137,9 +151,12 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
for(NicTO nicTo : sortNicsByDeviceId(to.getNics())) {
sbMacSequence.append(nicTo.getMac()).append("|");
}
sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
String bootArgs = to.getBootArgs();
to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
if (!sbMacSequence.toString().isEmpty()) {
sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
String bootArgs = to.getBootArgs();
to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
}
}

View File

@ -24,6 +24,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.rmi.RemoteException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
@ -83,10 +84,14 @@ import com.cloud.agent.api.NetworkUsageCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PingTestCommand;
import com.cloud.agent.api.PlugNicAnswer;
import com.cloud.agent.api.PlugNicCommand;
import com.cloud.agent.api.SetupGuestNetworkCommand;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.UnsupportedAnswer;
@ -172,7 +177,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
protected final int _retry = 24;
protected final int _sleep = 10000;
protected static final int DEFAULT_DOMR_SSHPORT = 3922;
private final int maxid = 4094;
private String _clusterGuid;
// Used by initialize to assert object configured before
@ -477,7 +482,12 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
answer = execute((SetStaticRouteCommand) cmd);
} else if (clazz == SetMonitorServiceCommand.class) {
answer = execute((SetMonitorServiceCommand) cmd);
} else {
} else if (clazz == PlugNicCommand.class) {
answer = execute((PlugNicCommand)cmd);
} else if (clazz == UnPlugNicCommand.class) {
answer = execute((UnPlugNicCommand)cmd);
}
else {
if (clazz == StartCommand.class) {
VirtualMachineTO vmSpec = ((StartCommand)cmd).getVirtualMachine();
if (vmSpec.getType() != VirtualMachine.Type.User) {
@ -509,6 +519,59 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
return answer;
}
private PlugNicAnswer execute(PlugNicCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource PlugNicCommand " + s_gson.toJson(cmd));
}
try {
String vmName = cmd.getVmName();
NicTO nic = cmd.getNic();
URI broadcastUri = nic.getBroadcastUri();
if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
throw new InternalErrorException("Unable to assign a public IP to a VIF on network " + nic.getBroadcastUri());
}
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int publicNicInfo = -1;
publicNicInfo = getVmNics(vmName, maxid);
if (publicNicInfo > 0) {
modifyNicVlan(vmName, vlanId, publicNicInfo);
}
return new PlugNicAnswer(cmd, true, "success");
} catch (Exception e) {
s_logger.error("Unexpected exception: ", e);
return new PlugNicAnswer(cmd, false, "Unable to execute PlugNicCommand due to " + e.toString());
}
}
private UnPlugNicAnswer execute(UnPlugNicCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource UnPlugNicCommand " + s_gson.toJson(cmd));
}
try {
String vmName = cmd.getVmName();
NicTO nic = cmd.getNic();
URI broadcastUri = nic.getBroadcastUri();
if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
throw new InternalErrorException("Unable to unassign a public IP to a VIF on network " + nic.getBroadcastUri());
}
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int publicNicInfo = -1;
publicNicInfo = getVmNics(vmName, vlanId);
if (publicNicInfo > 0) {
modifyNicVlan(vmName, maxid, publicNicInfo);
}
return new UnPlugNicAnswer(cmd, true, "success");
} catch (Exception e) {
s_logger.error("Unexpected exception: ", e);
return new UnPlugNicAnswer(cmd, false, "Unable to execute unPlugNicCommand due to " + e.toString());
}
}
@Override
public ExecutionResult executeInVR(String routerIP, String script, String args) {
Pair<Boolean, String> result;
@ -535,7 +598,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
public ExecutionResult createFileInVR(String routerIp, String filePath, String fileName, String content) {
File keyFile = getSystemVMKeyFile();
try {
SshHelper.scpTo(routerIp, 3922, "root", keyFile, null, filePath, content.getBytes(), fileName, null);
SshHelper.scpTo(routerIp, 3922, "root", keyFile, null, filePath, content.getBytes(Charset.forName("UTF-8")), fileName, null);
} catch (Exception e) {
s_logger.warn("Fail to create file " + filePath + fileName + " in VR " + routerIp, e);
return new ExecutionResult(false, e.getMessage());
@ -621,14 +684,18 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
protected ExecutionResult prepareNetworkElementCommand(SetupGuestNetworkCommand cmd) {
NicTO nic = cmd.getNic();
String routerIp = getRouterSshControlIp(cmd);
String domrName =
cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
try {
int ethDeviceNum = findRouterEthDeviceIndex(domrName, routerIp,
nic.getMac());
nic.setDeviceId(ethDeviceNum);
URI broadcastUri = nic.getBroadcastUri();
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int ethDeviceNum = getVmNics(domrName, vlanId);
if (ethDeviceNum > 0) {
nic.setDeviceId(ethDeviceNum);
} else {
return new ExecutionResult(false, "Prepare SetupGuestNetwork failed due to unable to find the nic");
}
} catch (Exception e) {
String msg = "Prepare SetupGuestNetwork failed due to " + e.toString();
s_logger.warn(msg, e);
@ -640,23 +707,27 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
private ExecutionResult prepareNetworkElementCommand(IpAssocVpcCommand cmd) {
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
try {
IpAddressTO[] ips = cmd.getIpAddresses();
for (IpAddressTO ip : ips) {
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, ip.getVifMacAddress());
if (ethDeviceNum < 0) {
URI broadcastUri = BroadcastDomainType.fromString(ip.getBroadcastUri());
if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
throw new InternalErrorException("Invalid Broadcast URI " + ip.getBroadcastUri());
}
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int publicNicInfo = -1;
publicNicInfo = getVmNics(routerName, vlanId);
if (publicNicInfo < 0) {
if (ip.isAdd()) {
throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with.");
} else {
} else {
s_logger.debug("VIF to deassociate IP with does not exist, return success");
continue;
}
}
ip.setNicDevId(ethDeviceNum);
ip.setNicDevId(publicNicInfo);
}
} catch (Exception e) {
s_logger.error("Prepare Ip Assoc failure on applying one ip due to exception: ", e);
@ -668,12 +739,17 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
protected ExecutionResult prepareNetworkElementCommand(SetSourceNatCommand cmd) {
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
IpAddressTO pubIp = cmd.getIpAddress();
try {
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, pubIp.getVifMacAddress());
pubIp.setNicDevId(ethDeviceNum);
String broadcastUri = pubIp.getBroadcastUri();
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int ethDeviceNum = getVmNics(routerName, vlanId);
if (ethDeviceNum > 0) {
pubIp.setNicDevId(ethDeviceNum);
} else {
return new ExecutionResult(false, "Prepare Ip SNAT failed due to unable to find the nic");
}
} catch (Exception e) {
String msg = "Prepare Ip SNAT failure due to " + e.toString();
s_logger.error(msg, e);
@ -686,12 +762,16 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
NicTO nic = cmd.getNic();
String routerName =
cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
String routerIp = getRouterSshControlIp(cmd);
try {
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp,
nic.getMac());
nic.setDeviceId(ethDeviceNum);
URI broadcastUri = nic.getBroadcastUri();
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
int ethDeviceNum = getVmNics(routerName, vlanId);
if (ethDeviceNum > 0) {
nic.setDeviceId(ethDeviceNum);
} else {
return new ExecutionResult(false, "Prepare SetNetworkACL failed due to unable to find the nic");
}
} catch (Exception e) {
String msg = "Prepare SetNetworkACL failed due to " + e.toString();
s_logger.error(msg, e);
@ -1183,7 +1263,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
}
try {
SshHelper.scpTo(controlIp, DEFAULT_DOMR_SSHPORT, "root", keyFile, null, "/tmp/", tmpCfgFileContents.toString().getBytes(), routerIp.replace('.', '_') +
SshHelper.scpTo(controlIp, DEFAULT_DOMR_SSHPORT, "root", keyFile, null, "/tmp/", tmpCfgFileContents.toString().getBytes(Charset.forName("UTF-8")), routerIp.replace('.', '_') +
".cfg", null);
try {
@ -1380,7 +1460,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
String json = new Gson().toJson(data);
s_logger.debug("VM data JSON IS:" + json);
json = Base64.encodeBase64String(json.getBytes());
json = Base64.encodeBase64String(json.getBytes(Charset.forName("UTF-8")));
String args = "-d " + json;
@ -1730,6 +1810,27 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
}
}
protected void modifyNicVlan(String vmName, int vlanId, int pos) {
ModifyVmNicConfigCommand modifynic = new ModifyVmNicConfigCommand(vmName, vlanId, pos);
URI agentUri = null;
try {
String cmdName = ModifyVmNicConfigCommand.class.getName();
agentUri =
new URI("https", null, _agentIp, _port,
"/api/HypervResource/" + cmdName, null, null);
} catch (URISyntaxException e) {
String errMsg = "Could not generate URI for Hyper-V agent";
s_logger.error(errMsg, e);
}
String ansStr = postHttpRequest(s_gson.toJson(modifynic), agentUri);
Answer[] result = s_gson.fromJson(ansStr, Answer[].class);
s_logger.debug("executeRequest received response "
+ s_gson.toJson(result));
if (result.length > 0) {
ModifyVmNicConfigAnswer ans = ((ModifyVmNicConfigAnswer)result[0]);
}
}
protected void assignPublicIpAddress(final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP,
final boolean sourceNat, final String broadcastId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress) throws Exception {

View File

@ -0,0 +1,179 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.cloudstack.storage.motion;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.MigrateWithStorageAnswer;
import com.cloud.agent.api.MigrateWithStorageCommand;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.VMInstanceDao;
@Component
public class HypervStorageMotionStrategy implements DataMotionStrategy {
private static final Logger s_logger = Logger.getLogger(HypervStorageMotionStrategy.class);
@Inject AgentManager agentMgr;
@Inject VolumeDao volDao;
@Inject VolumeDataFactory volFactory;
@Inject PrimaryDataStoreDao storagePoolDao;
@Inject VMInstanceDao instanceDao;
@Override
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
return StrategyPriority.CANT_HANDLE;
}
@Override
public StrategyPriority canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
if (srcHost.getHypervisorType() == HypervisorType.Hyperv &&
destHost.getHypervisorType() == HypervisorType.Hyperv) {
return StrategyPriority.HYPERVISOR;
}
return StrategyPriority.CANT_HANDLE;
}
@Override
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
throw new UnsupportedOperationException();
}
@Override
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
CopyCommandResult result = new CopyCommandResult(null, null);
result.setResult("Unsupported operation requested for copying data.");
callback.complete(result);
return null;
}
@Override
public Void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost,
AsyncCompletionCallback<CopyCommandResult> callback) {
Answer answer = null;
String errMsg = null;
try {
VMInstanceVO instance = instanceDao.findById(vmTo.getId());
if (instance != null) {
answer = migrateVmWithVolumes(instance, vmTo, srcHost, destHost, volumeMap);
} else {
throw new CloudRuntimeException("Unsupported operation requested for moving data.");
}
} catch (Exception e) {
s_logger.error("copy failed", e);
errMsg = e.toString();
}
CopyCommandResult result = new CopyCommandResult(null, answer);
result.setResult(errMsg);
callback.complete(result);
return null;
}
private Answer migrateVmWithVolumes(VMInstanceVO vm, VirtualMachineTO to, Host srcHost,
Host destHost, Map<VolumeInfo, DataStore> volumeToPool) throws AgentUnavailableException {
// Initiate migration of a virtual machine with it's volumes.
try {
List<Pair<VolumeTO, StorageFilerTO>> volumeToFilerto = new ArrayList<Pair<VolumeTO, StorageFilerTO>>();
for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
VolumeInfo volume = entry.getKey();
VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId()));
StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue());
volumeToFilerto.add(new Pair<VolumeTO, StorageFilerTO>(volumeTo, filerTo));
}
MigrateWithStorageCommand command = new MigrateWithStorageCommand(to, volumeToFilerto, destHost.getPrivateIpAddress());
MigrateWithStorageAnswer answer = (MigrateWithStorageAnswer) agentMgr.send(srcHost.getId(), command);
if (answer == null) {
s_logger.error("Migration with storage of vm " + vm + " failed.");
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
} else if (!answer.getResult()) {
s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + answer.getDetails());
throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost +
". " + answer.getDetails());
} else {
// Update the volume details after migration.
updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos());
}
return answer;
} catch (OperationTimedoutException e) {
s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e);
throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId());
}
}
private void updateVolumePathsAfterMigration(Map<VolumeInfo, DataStore> volumeToPool, List<VolumeObjectTO> volumeTos) {
for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
boolean updated = false;
VolumeInfo volume = entry.getKey();
StoragePool pool = (StoragePool)entry.getValue();
for (VolumeObjectTO volumeTo : volumeTos) {
if (volume.getId() == volumeTo.getId()) {
VolumeVO volumeVO = volDao.findById(volume.getId());
Long oldPoolId = volumeVO.getPoolId();
volumeVO.setPath(volumeTo.getPath());
volumeVO.setFolder(pool.getPath());
volumeVO.setPodId(pool.getPodId());
volumeVO.setPoolId(pool.getId());
volumeVO.setLastPoolId(oldPoolId);
volDao.update(volume.getId(), volumeVO);
updated = true;
break;
}
}
if (!updated) {
s_logger.error("Volume path wasn't updated for volume " + volume + " after it was migrated.");
}
}
}
}

View File

@ -78,6 +78,8 @@ import com.cloud.agent.api.OvsDestroyTunnelCommand;
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
import com.cloud.agent.api.OvsFetchInterfaceCommand;
import com.cloud.agent.api.OvsSetupBridgeCommand;
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
@ -1360,6 +1362,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return execute((OvsCreateTunnelCommand)cmd);
} else if (cmd instanceof OvsDestroyTunnelCommand) {
return execute((OvsDestroyTunnelCommand)cmd);
} else if (cmd instanceof OvsVpcPhysicalTopologyConfigCommand) {
return execute((OvsVpcPhysicalTopologyConfigCommand) cmd);
} else if (cmd instanceof OvsVpcRoutingPolicyConfigCommand) {
return execute((OvsVpcRoutingPolicyConfigCommand) cmd);
} else {
s_logger.warn("Unsupported command ");
return Answer.createUnsupportedCommandAnswer(cmd);
@ -1388,23 +1394,63 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
private Answer execute(OvsSetupBridgeCommand cmd) {
findOrCreateTunnelNetwork(cmd.getKey());
findOrCreateTunnelNetwork(cmd.getBridgeName());
configureTunnelNetwork(cmd.getNetworkId(), cmd.getHostId(),
cmd.getKey());
cmd.getBridgeName());
s_logger.debug("OVS Bridge configured");
return new Answer(cmd, true, null);
}
private Answer execute(OvsDestroyBridgeCommand cmd) {
destroyTunnelNetwork(cmd.getKey());
destroyTunnelNetwork(cmd.getBridgeName());
s_logger.debug("OVS Bridge destroyed");
return new Answer(cmd, true, null);
}
private synchronized void destroyTunnelNetwork(int key) {
public Answer execute(OvsVpcPhysicalTopologyConfigCommand cmd) {
String bridge = cmd.getBridgeName();
try {
findOrCreateTunnelNetwork(key);
String bridge = "OVSTunnel" + key;
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
command.add("configure_ovs_bridge_for_network_topology");
command.add("--bridge", bridge);
command.add("--config", cmd.getVpcConfigInJson());
String result = command.execute();
if (result.equalsIgnoreCase("SUCCESS")) {
return new Answer(cmd, true, result);
} else {
return new Answer(cmd, false, result);
}
} catch (Exception e) {
s_logger.warn("caught exception while updating host with latest routing polcies", e);
return new Answer(cmd, false, e.getMessage());
}
}
public Answer execute(OvsVpcRoutingPolicyConfigCommand cmd) {
try {
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
command.add("configure_ovs_bridge_for_routing_policies");
command.add("--bridge", cmd.getBridgeName());
command.add("--config", cmd.getVpcConfigInJson());
String result = command.execute();
if (result.equalsIgnoreCase("SUCCESS")) {
return new Answer(cmd, true, result);
} else {
return new Answer(cmd, false, result);
}
} catch (Exception e) {
s_logger.warn("caught exception while updating host with latest VPC topology", e);
return new Answer(cmd, false, e.getMessage());
}
}
private synchronized void destroyTunnelNetwork(String bridge) {
try {
findOrCreateTunnelNetwork(bridge);
Script cmd = new Script(_ovsTunnelPath, _timeout, s_logger);
cmd.add("destroy_ovs_bridge");
cmd.add("--bridge", bridge);
@ -1423,9 +1469,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
}
private synchronized boolean findOrCreateTunnelNetwork(long key) {
private synchronized boolean findOrCreateTunnelNetwork(String nwName) {
try {
String nwName = "OVSTunnel" + key;
if (checkNetwork(nwName)) {
return true;
}
@ -1443,10 +1488,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
private synchronized boolean configureTunnelNetwork(long networkId,
long hostId, int key) {
long hostId, String nwName) {
try {
findOrCreateTunnelNetwork(key);
String nwName = "OVSTunnel" + key;
findOrCreateTunnelNetwork(nwName);
String configuredHosts = Script
.runSimpleBashScript("ovs-vsctl get bridge " + nwName
+ " other_config:ovs_host_setup");
@ -1463,7 +1507,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
if (!configured) {
Script cmd = new Script(_ovsTunnelPath, _timeout, s_logger);
cmd.add("setup_ovs_bridge");
cmd.add("--key", String.valueOf(key));
cmd.add("--key", nwName);
cmd.add("--cs_host_id", ((Long)hostId).toString());
cmd.add("--bridge", nwName);
String result = cmd.execute();
@ -1481,16 +1525,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
}
private OvsCreateTunnelAnswer execute(OvsCreateTunnelCommand cmd) {
String bridge = "OVSTunnel" + cmd.getKey();
String bridge = cmd.getNetworkName();
try {
if (!findOrCreateTunnelNetwork(cmd.getKey())) {
if (!findOrCreateTunnelNetwork(bridge)) {
s_logger.debug("Error during bridge setup");
return new OvsCreateTunnelAnswer(cmd, false,
"Cannot create network", bridge);
}
configureTunnelNetwork(cmd.getNetworkId(), cmd.getFrom(),
cmd.getKey());
cmd.getNetworkName());
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
command.add("create_tunnel");
command.add("--bridge", bridge);
@ -1515,16 +1559,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
private Answer execute(OvsDestroyTunnelCommand cmd) {
try {
if (!findOrCreateTunnelNetwork(cmd.getKey())) {
if (!findOrCreateTunnelNetwork(cmd.getBridgeName())) {
s_logger.warn("Unable to find tunnel network for GRE key:"
+ cmd.getKey());
+ cmd.getBridgeName());
return new Answer(cmd, false, "No network found");
}
String bridge = "OVSTunnel" + cmd.getKey();
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
command.add("destroy_tunnel");
command.add("--bridge", bridge);
command.add("--bridge", cmd.getBridgeName());
command.add("--iface_name", cmd.getInPortName());
String result = command.execute();
if (result == null) {

View File

@ -16,7 +16,6 @@
// under the License.
package com.cloud.hypervisor.xen.resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@ -148,6 +147,8 @@ import com.cloud.agent.api.OvsFetchInterfaceCommand;
import com.cloud.agent.api.OvsSetTagAndFlowAnswer;
import com.cloud.agent.api.OvsSetTagAndFlowCommand;
import com.cloud.agent.api.OvsSetupBridgeCommand;
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
import com.cloud.agent.api.PerformanceMonitorAnswer;
import com.cloud.agent.api.PerformanceMonitorCommand;
import com.cloud.agent.api.PingCommand;
@ -507,6 +508,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return execute((OvsSetTagAndFlowCommand)cmd);
} else if (clazz == OvsDeleteFlowCommand.class) {
return execute((OvsDeleteFlowCommand)cmd);
} else if (clazz == OvsVpcPhysicalTopologyConfigCommand.class) {
return execute((OvsVpcPhysicalTopologyConfigCommand) cmd);
} else if (clazz == OvsVpcRoutingPolicyConfigCommand.class) {
return execute((OvsVpcRoutingPolicyConfigCommand) cmd);
} else if (clazz == CleanupNetworkRulesCmd.class) {
return execute((CleanupNetworkRulesCmd)cmd);
} else if (clazz == NetworkRulesSystemVmCommand.class) {
@ -530,7 +535,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} else if (clazz == PlugNicCommand.class) {
return execute((PlugNicCommand)cmd);
} else if (clazz == UnPlugNicCommand.class) {
return execute((UnPlugNicCommand)cmd);
return execute((UnPlugNicCommand) cmd);
} else if (cmd instanceof StorageSubSystemCommand) {
return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd);
} else if (clazz == CreateVMSnapshotCommand.class) {
@ -964,15 +969,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
/**
* This method just creates a XenServer network following the tunnel network naming convention
*/
private synchronized Network findOrCreateTunnelNetwork(Connection conn, long key) {
private synchronized Network findOrCreateTunnelNetwork(Connection conn, String nwName) {
try {
String nwName = "OVSTunnel" + key;
Network nw = null;
Network.Record rec = new Network.Record();
Set<Network> networks = Network.getByNameLabel(conn, nwName);
if (networks.size() == 0) {
rec.nameDescription = "tunnel network id# " + key;
rec.nameDescription = "tunnel network id# " + nwName;
rec.nameLabel = nwName;
//Initialize the ovs-host-setup to avoid error when doing get-param in plugin
Map<String, String> otherConfig = new HashMap<String, String>();
@ -981,7 +985,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
nw = Network.create(conn, rec);
// Plug dom0 vif only when creating network
if (!is_xcp())
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + key);
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + nwName);
s_logger.debug("### Xen Server network for tunnels created:" + nwName);
} else {
nw = networks.iterator().next();
@ -997,10 +1001,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
/**
* This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network
*/
private synchronized Network configureTunnelNetwork(Connection conn, long networkId, long hostId, int key) {
private synchronized Network configureTunnelNetwork(Connection conn, Long networkId, long hostId, String bridgeName) {
try {
Network nw = findOrCreateTunnelNetwork(conn, key);
String nwName = "OVSTunnel" + key;
Network nw = findOrCreateTunnelNetwork(conn, bridgeName);
String nwName = bridgeName;
//Invoke plugin to setup the bridge which will be used by this network
String bridge = nw.getBridge(conn);
Map<String, String> nwOtherConfig = nw.getOtherConfig(conn);
@ -1018,16 +1022,25 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
if (!configured) {
// Plug dom0 vif only if not done before for network and host
if (!is_xcp())
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + key);
String result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge,
"key", String.valueOf(key),
"xs_nw_uuid", nw.getUuid(conn),
"cs_host_id", ((Long)hostId).toString());
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + bridgeName);
String result;
if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) {
result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge,
"key", bridgeName,
"xs_nw_uuid", nw.getUuid(conn),
"cs_host_id", ((Long)hostId).toString());
} else {
result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge,
"key", bridgeName,
"xs_nw_uuid", nw.getUuid(conn),
"cs_host_id", ((Long)hostId).toString());
}
//Note down the fact that the ovs bridge has been setup
String[] res = result.split(":");
if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
//TODO: Should make this error not fatal?
throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge + " for network ID:" + networkId + " - " + res);
throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge );
}
}
return nw;
@ -1037,9 +1050,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
}
private synchronized void destroyTunnelNetwork(Connection conn, int key) {
private synchronized void destroyTunnelNetwork(Connection conn, String bridgeName) {
try {
Network nw = findOrCreateTunnelNetwork(conn, key);
Network nw = findOrCreateTunnelNetwork(conn, bridgeName);
String bridge = nw.getBridge(conn);
String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge);
String[] res = result.split(":");
@ -1079,8 +1092,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
_isOvs = true;
return setupvSwitchNetwork(conn);
} else {
long vnetId = Long.parseLong(BroadcastDomainType.getValue(uri));
return findOrCreateTunnelNetwork(conn, vnetId);
return findOrCreateTunnelNetwork(conn, getOvsTunnelNetworkName(uri.getAuthority()));
}
} else if (type == BroadcastDomainType.Storage) {
if (uri == null) {
@ -1102,6 +1114,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri());
}
private String getOvsTunnelNetworkName(String broadcastUri) {
if (broadcastUri.contains(".")) {
String[] parts = broadcastUri.split("\\.");
return "OVS-DR-VPC-Bridge"+parts[0];
} else {
try {
return "OVSTunnel" + broadcastUri;
} catch (Exception e) {
return null;
}
}
}
protected VIF createVif(Connection conn, String vmName, VM vm, VirtualMachineTO vmSpec, NicTO nic) throws XmlRpcException, XenAPIException {
assert (nic.getUuid() != null) : "Nic should have a uuid value";
@ -1123,6 +1148,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
vifr.otherConfig.put("cloudstack-vm-id", vmSpec.getUuid());
}
// OVS plugin looks at network UUID in the vif 'otherconfig' details to group VIF's & tunnel ports as part of tier
// when bridge is setup for distributed routing
vifr.otherConfig.put("cloudstack-network-id", nic.getNetworkUuid());
vifr.network = getNetwork(conn, nic);
if (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) {
@ -5220,15 +5249,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
private Answer execute(OvsSetupBridgeCommand cmd) {
Connection conn = getConnection();
findOrCreateTunnelNetwork(conn, cmd.getKey());
configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getHostId(), cmd.getKey());
findOrCreateTunnelNetwork(conn, cmd.getBridgeName());
configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getHostId(), cmd.getBridgeName());
s_logger.debug("OVS Bridge configured");
return new Answer(cmd, true, null);
}
private Answer execute(OvsDestroyBridgeCommand cmd) {
Connection conn = getConnection();
destroyTunnelNetwork(conn, cmd.getKey());
destroyTunnelNetwork(conn, cmd.getBridgeName());
s_logger.debug("OVS Bridge destroyed");
return new Answer(cmd, true, null);
}
@ -5236,14 +5265,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
private Answer execute(OvsDestroyTunnelCommand cmd) {
Connection conn = getConnection();
try {
Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkId());
Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName());
if (nw == null) {
s_logger.warn("Unable to find tunnel network for GRE key:" + cmd.getKey());
s_logger.warn("Unable to find tunnel network for GRE key:" + cmd.getBridgeName());
return new Answer(cmd, false, "No network found");
}
String bridge = nw.getBridge(conn);
String result = callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", cmd.getInPortName());
if (result.equalsIgnoreCase("SUCCESS")) {
return new Answer(cmd, true, result);
} else {
@ -5255,6 +5285,44 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
}
public Answer execute(OvsVpcPhysicalTopologyConfigCommand cmd) {
Connection conn = getConnection();
try {
Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName());
String bridgeName = nw.getBridge(conn);
String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_network_topology", "bridge",
bridgeName, "config", cmd.getVpcConfigInJson(), "host-id", ((Long)cmd.getHostId()).toString());
if (result.startsWith("SUCCESS")) {
return new Answer(cmd, true, result);
} else {
return new Answer(cmd, false, result);
}
} catch (Exception e) {
s_logger.warn("caught exception while updating host with latest VPC topology", e);
return new Answer(cmd, false, e.getMessage());
}
}
public Answer execute(OvsVpcRoutingPolicyConfigCommand cmd) {
Connection conn = getConnection();
try {
Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName());
String bridgeName = nw.getBridge(conn);
String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_routing_policies", "bridge",
bridgeName, "host-id", ((Long)cmd.getHostId()).toString(), "config",
cmd.getVpcConfigInJson());
if (result.startsWith("SUCCESS")) {
return new Answer(cmd, true, result);
} else {
return new Answer(cmd, false, result);
}
} catch (Exception e) {
s_logger.warn("caught exception while updating host with latest routing policies", e);
return new Answer(cmd, false, e.getMessage());
}
}
private Answer execute(UpdateHostPasswordCommand cmd) {
_password.add(cmd.getNewPassword());
return new Answer(cmd, true, null);
@ -5264,17 +5332,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
Connection conn = getConnection();
String bridge = "unknown";
try {
Network nw = findOrCreateTunnelNetwork(conn, cmd.getKey());
Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkName());
if (nw == null) {
s_logger.debug("Error during bridge setup");
return new OvsCreateTunnelAnswer(cmd, false, "Cannot create network", bridge);
}
configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom(), cmd.getKey());
configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom(), cmd.getNetworkName());
bridge = nw.getBridge(conn);
String result =
callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(), "key", cmd.getKey().toString(), "from",
cmd.getFrom().toString(), "to", cmd.getTo().toString());
callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(),
"key", cmd.getKey().toString(), "from",
cmd.getFrom().toString(), "to", cmd.getTo().toString(), "cloudstack-network-id",
cmd.getNetworkUuid());
String[] res = result.split(":");
if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) {
return new OvsCreateTunnelAnswer(cmd, true, result, res[1], bridge);

View File

@ -281,7 +281,7 @@ public class ContrailManagerImpl extends ManagerBase implements ContrailManager
for (String svc: services) {
serviceProviderMap.put(svc, providerSet);
}
vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null);
vpcOffer = _vpcProvSvc.createVpcOffering(juniperVPCOfferingName, juniperVPCOfferingDisplayText, services, serviceProviderMap, null, null);
((VpcOfferingVO)vpcOffer).setState(VpcOffering.State.Enabled);
long id = vpcOffer.getId();
_vpcOffDao.update(id, (VpcOfferingVO)vpcOffer);

View File

@ -38,5 +38,5 @@
<bean id="ovsTunnelManagerImpl" class="com.cloud.network.ovs.OvsTunnelManagerImpl" />
<bean id="ovsTunnelInterfaceDaoImpl" class="com.cloud.network.ovs.dao.OvsTunnelInterfaceDaoImpl" />
<bean id="ovsTunnelNetworkDaoImpl" class="com.cloud.network.ovs.dao.OvsTunnelNetworkDaoImpl" />
<bean id="ovsNetworkTopologyGuruImpl" class="com.cloud.network.ovs.OvsNetworkTopologyGuruImpl"/>
</beans>

View File

@ -20,10 +20,13 @@ package com.cloud.agent.api;
public class OvsCreateTunnelCommand extends Command {
Integer key;
String remoteIp;
String networkName;
Long from;
Long to;
long networkId;
String networkUuid;
// for debug info
String fromIp;
@ -33,13 +36,15 @@ public class OvsCreateTunnelCommand extends Command {
}
public OvsCreateTunnelCommand(String remoteIp, Integer key, Long from,
Long to, long networkId, String fromIp) {
Long to, long networkId, String fromIp, String networkName, String networkUuid) {
this.remoteIp = remoteIp;
this.key = key;
this.from = from;
this.to = to;
this.networkId = networkId;
this.fromIp = fromIp;
this.networkName = networkName;
this.networkUuid = networkUuid;
}
public Integer getKey() {
@ -66,4 +71,16 @@ public class OvsCreateTunnelCommand extends Command {
return fromIp;
}
public String getNetworkName() {
return networkName;
}
public String getNetworkUuid() {
return networkUuid;
}
public void setNetworkUuid(String networkUuid) {
this.networkUuid = networkUuid;
}
}

View File

@ -21,19 +21,19 @@ package com.cloud.agent.api;
public class OvsDestroyBridgeCommand extends Command {
Long networkId;
Integer key;
String name;
public OvsDestroyBridgeCommand(Long networkId, Integer key) {
public OvsDestroyBridgeCommand(Long networkId, String name) {
this.networkId = networkId;
this.key = key;
this.name = name;
}
public Long getNetworkId() {
return networkId;
}
public Integer getKey() {
return key;
public String getBridgeName() {
return name;
}
@Override

View File

@ -20,14 +20,14 @@ package com.cloud.agent.api;
public class OvsDestroyTunnelCommand extends Command {
Long networkId;
Integer key;
String networkName;
String inPortName;
public OvsDestroyTunnelCommand(Long networkId, Integer key,
public OvsDestroyTunnelCommand(Long networkId, String networkName,
String inPortName) {
this.networkId = networkId;
this.inPortName = inPortName;
this.key = key;
this.networkName = networkName;
}
public Long getNetworkId() {
@ -38,8 +38,8 @@ public class OvsDestroyTunnelCommand extends Command {
return inPortName;
}
public Integer getKey() {
return key;
public String getBridgeName() {
return networkName;
}
@Override

View File

@ -19,7 +19,7 @@ package com.cloud.agent.api;
public class OvsSetupBridgeCommand extends Command {
Integer key;
String name;
Long hostId;
Long networkId;
@ -28,14 +28,14 @@ public class OvsSetupBridgeCommand extends Command {
return true;
}
public OvsSetupBridgeCommand(Integer key, Long hostId, Long networkId) {
this.key = key;
public OvsSetupBridgeCommand(String name, Long hostId, Long networkId) {
this.name = name;
this.hostId = hostId;
this.networkId = networkId;
}
public Integer getKey() {
return key;
public String getBridgeName() {
return name;
}
public Long getHostId() {

View File

@ -0,0 +1,130 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.agent.api;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* This command represents physical view of how a VPC is laid out on the physical infrastructure. Contains information:
* - on which hypervisor hosts VPC spans (host running at least one VM from the VPC)
* - information of tiers, so we can figure how one VM can talk to a different VM in same tier or different tier
* - information on all the VM's in the VPC.
* - information of NIC's of each VM in the VPC
*/
public class OvsVpcPhysicalTopologyConfigCommand extends Command {
VpcConfig vpcConfig =null;
long hostId;
String bridgeName;
public static class Host {
long hostId;
String ipAddress;
public Host (long hostId, String ipAddress) {
this.hostId = hostId;
this.ipAddress = ipAddress;
}
}
public static class Nic {
String ipAddress;
String macAddress;
String networkUuid;
public Nic (String ipAddress, String macAddress, String networkUuid) {
this.ipAddress = ipAddress;
this.macAddress = macAddress;
this.networkUuid = networkUuid;
}
}
public static class Tier {
long greKey;
String networkUuid;
String gatewayIp;
String gatewayMac;
String cidr;
public Tier(long greKey, String networkUuid, String gatewayIp, String gatewayMac, String cidr) {
this.greKey = greKey;
this.networkUuid = networkUuid;
this.gatewayIp = gatewayIp;
this.gatewayMac = gatewayMac;
this.cidr = cidr;
}
}
public static class Vm {
long hostId;
Nic[] nics;
public Vm(long hostId, Nic[] nics) {
this.hostId = hostId;
this.nics = nics;
}
}
public static class Vpc {
String cidr;
Host[] hosts;
Tier[] tiers;
Vm[] vms;
public Vpc(Host[] hosts, Tier[] tiers, Vm[] vms, String cidr) {
this.hosts = hosts;
this.tiers = tiers;
this.vms = vms;
this.cidr = cidr;
}
}
public static class VpcConfig {
Vpc vpc;
public VpcConfig(Vpc vpc) {
this.vpc = vpc;
}
}
public OvsVpcPhysicalTopologyConfigCommand(Host[] hosts, Tier[] tiers, Vm[] vms, String cidr) {
Vpc vpc = new Vpc(hosts, tiers, vms, cidr);
vpcConfig = new VpcConfig(vpc);
}
public String getVpcConfigInJson() {
Gson gson = new GsonBuilder().create();
return gson.toJson(vpcConfig).toLowerCase();
}
@Override
public boolean executeInSequence() {
return false;
}
public void setHostId(long hostId) {
this.hostId = hostId;
}
public long getHostId() {
return hostId;
}
public String getBridgeName() {
return bridgeName;
}
public void setBridgeName(String bridgeName) {
this.bridgeName = bridgeName;
}
}

View File

@ -0,0 +1,123 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.agent.api;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* This command represents logical view of VM's connectivity in VPC.
*/
public class OvsVpcRoutingPolicyConfigCommand extends Command {
VpcConfig vpcConfig =null;
long hostId;
String bridgeName;
public static class AclItem {
int number;
String uuid;
String action;
String direction;
String sourcePortStart;
String sourcePortEnd;
String protocol;
String[] sourceCidrs;
public AclItem(int number, String uuid, String action, String direction, String sourcePortStart,
String sourcePortEnd, String protocol, String[] sourceCidrs) {
this.number = number;
this.uuid =uuid;
this.action = action;
this.direction = direction;
this.sourceCidrs = sourceCidrs;
this.sourcePortStart = sourcePortStart;
this.sourcePortEnd = sourcePortEnd;
this.protocol = protocol;
}
}
public static class Acl {
String id;
AclItem[] aclItems;
public Acl(String uuid, AclItem[] aclItems) {
this.id = uuid;
this.aclItems = aclItems;
}
}
public static class Tier {
String id;
String cidr;
String aclId;
public Tier(String uuid, String cidr, String aclId) {
this.id = uuid;
this.cidr = cidr;
this.aclId = aclId;
}
}
public class Vpc {
String cidr;
String id;
Acl[] acls;
Tier[] tiers;
public Vpc(String id, String cidr, Acl[] acls, Tier[] tiers) {
this.id = id;
this.cidr = cidr;
this.acls = acls;
this.tiers = tiers;
}
}
public static class VpcConfig {
Vpc vpc;
public VpcConfig(Vpc vpc) {
this.vpc = vpc;
}
}
public OvsVpcRoutingPolicyConfigCommand(String id, String cidr, Acl[] acls, Tier[] tiers) {
Vpc vpc = new Vpc(id, cidr, acls, tiers);
vpcConfig = new VpcConfig(vpc);
}
public String getVpcConfigInJson() {
Gson gson = new GsonBuilder().create();
return gson.toJson(vpcConfig).toLowerCase();
}
public void setHostId(long hostId) {
this.hostId = hostId;
}
public long getHostId() {
return hostId;
}
public String getBridgeName() {
return bridgeName;
}
public void setBridgeName(String bridgeName) {
this.bridgeName = bridgeName;
}
@Override
public boolean executeInSequence() {
return false;
}
}

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.network.element;
import com.cloud.host.dao.HostDao;
import com.cloud.vm.dao.UserVmDao;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -73,6 +75,7 @@ import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.VirtualMachine;
@Local(value = {NetworkElement.class, ConnectivityProvider.class,
SourceNatServiceProvider.class, StaticNatServiceProvider.class,
@ -93,6 +96,10 @@ StaticNatServiceProvider, IpDeployer {
DomainRouterDao _routerDao;
@Inject
VpcVirtualNetworkApplianceManager _routerMgr;
@Inject
UserVmDao _userVmDao;
@Inject
HostDao _hostDao;
private static final Logger s_logger = Logger.getLogger(OvsElement.class);
private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
@ -171,7 +178,12 @@ StaticNatServiceProvider, IpDeployer {
return false;
}
_ovsTunnelMgr.vmCheckAndCreateTunnel(vm, network, dest);
if (vm.getType() != VirtualMachine.Type.User && vm.getType() != VirtualMachine.Type.DomainRouter) {
return false;
}
// prepare the tunnel network on the host, in order for VM to get launched
_ovsTunnelMgr.checkAndPrepareHostForTunnelNetwork(network, dest.getHost());
return true;
}
@ -192,7 +204,8 @@ StaticNatServiceProvider, IpDeployer {
return false;
}
_ovsTunnelMgr.checkAndDestroyTunnel(vm.getVirtualMachine(), network);
HostVO host = _hostDao.findById(vm.getVirtualMachine().getHostId());
_ovsTunnelMgr.checkAndRemoveHostFromTunnelNetwork(network, host);
return true;
}
@ -246,7 +259,12 @@ StaticNatServiceProvider, IpDeployer {
Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
// L2 Support : SDN provisioning
capabilities.put(Service.Connectivity, null);
Map<Capability, String> connectivityCapabilities = new HashMap<Capability, String>();
connectivityCapabilities.put(Capability.DistributedRouter, null);
connectivityCapabilities.put(Capability.StretchedL2Subnet, null);
connectivityCapabilities.put(Capability.RegionLevelVpc, null);
capabilities.put(Service.Connectivity, connectivityCapabilities);
// L3 Support : Port Forwarding
capabilities.put(Service.PortForwarding, null);

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.network.guru;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import javax.ejb.Local;
import javax.inject.Inject;
@ -61,6 +63,8 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
OvsTunnelManager _ovsTunnelMgr;
@Inject
NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
@Inject
VpcDao _vpcDao;
OvsGuestNetworkGuru() {
super();
@ -145,10 +149,15 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
implemented.setCidr(network.getCidr());
}
// do we need to create switch right now?
implemented.setBroadcastDomainType(BroadcastDomainType.Vswitch);
// for the networks that are part of VPC enabled for distributed routing use scheme vs://vpcid.GRE key for network
if (network.getVpcId() != null && isVpcEnabledForDistributedRouter(network.getVpcId())) {
String keyStr = BroadcastDomainType.getValue(implemented.getBroadcastUri());
Long vpcid= network.getVpcId();
implemented.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(vpcid.toString() + "." + keyStr));
}
return implemented;
}
@ -215,4 +224,9 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
implemented.setBroadcastUri(network.getBroadcastUri());
}
}
boolean isVpcEnabledForDistributedRouter(long vpcId) {
VpcVO vpc = _vpcDao.findById(vpcId);
return vpc.usesDistributedRouter();
}
}

View File

@ -0,0 +1,64 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.network.ovs;
import com.cloud.utils.component.Manager;
import java.util.List;
public interface OvsNetworkTopologyGuru extends Manager {
/**
* get the list of hypervisor hosts id's on which VM's belonging to the network currently spans
*/
public List<Long> getNetworkSpanedHosts(long networkId);
/**
* get the list of hypervisor hosts id's on which VM's belonging to a VPC spans
*/
public List<Long> getVpcSpannedHosts(long vpId);
/**
* get the list of VPC id's of the vpc's for which one or more VM's from the VPC are running on the host
*/
public List<Long> getVpcOnHost(long hostId);
/**
* get the list of all active Vm id's in a network
*/
public List<Long> getAllActiveVmsInNetwork(long networkId);
/**
* get the list of all active Vm id's in the VPC for all ther tiers
*/
public List<Long> getAllActiveVmsInVpc(long vpcId);
/**
* get the list of all Vm id's in the VPC for all the tiers that are running on the host
*/
public List<Long> getActiveVmsInVpcOnHost(long vpcId, long hostId);
/**
* get the list of all Vm id's in the network that are running on the host
*/
public List<Long> getActiveVmsInNetworkOnHost(long vpcId, long hostId);
/**
* get the list of all Vpc id's in which, a VM has a nic in the network that is part of VPC
*/
public List<Long> getVpcIdsVmIsPartOf(long vmId);
}

View File

@ -0,0 +1,240 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.network.ovs;
import com.cloud.network.Network;
import com.cloud.network.Networks;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.vpc.VpcManager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.NicVO;
import com.cloud.vm.Nic;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
@Component
@Local(value = {OvsNetworkTopologyGuru.class})
public class OvsNetworkTopologyGuruImpl extends ManagerBase implements OvsNetworkTopologyGuru {
@Inject
UserVmDao _userVmDao;
@Inject
DomainRouterDao _routerDao;
@Inject
VpcManager _vpcMgr;
@Inject
VMInstanceDao _vmInstanceDao;
@Inject
NicDao _nicDao;
@Inject
NetworkDao _networkDao;
/**
* get the list of hypervisor hosts on which VM's belonging to a network currently spans
*/
public List<Long> getNetworkSpanedHosts(long networkId) {
List<Long> hostIds = new ArrayList<Long>();
// Find active VMs with a NIC on the target network
List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(networkId,
VirtualMachine.State.Running, VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Unknown,
VirtualMachine.State.Migrating);
// Find routers for the network
List<DomainRouterVO> routers = _routerDao.findByNetwork(networkId);
List<VMInstanceVO> ins = new ArrayList<VMInstanceVO>();
if (vms != null) {
ins.addAll(vms);
}
if (routers.size() != 0) {
ins.addAll(routers);
}
for (VMInstanceVO v : ins) {
Long rh = v.getHostId();
if (rh == null) {
continue;
}
if (!hostIds.contains(rh)) {
hostIds.add(rh);
}
}
return hostIds;
}
/**
* get the list of hypervisor hosts on which VM's belonging to a VPC currently spans
*/
@Override
public List<Long> getVpcSpannedHosts(long vpcId) {
List<? extends Network> vpcNetworks = _vpcMgr.getVpcNetworks(vpcId);
List<Long> vpcHostIds = new ArrayList<>();
for (Network vpcNetwork : vpcNetworks) {
List<Long> networkHostIds = new ArrayList<Long>();
networkHostIds = getNetworkSpanedHosts(vpcNetwork.getId());
if (networkHostIds != null && !networkHostIds.isEmpty()) {
for (Long hostId : networkHostIds) {
if (!vpcHostIds.contains(hostId)) {
vpcHostIds.add(hostId);
}
}
}
}
return vpcHostIds;
}
/**
* get the list of VPC id's of the vpc's for which one or more VM's from the VPC are running on the host
*/
@Override
public List<Long> getVpcOnHost(long hostId) {
List<Long> vpcIds = new ArrayList<>();
List<VMInstanceVO> vmInstances = _vmInstanceDao.listByHostId(hostId);
for (VMInstanceVO instance : vmInstances) {
List<NicVO> nics = _nicDao.listByVmId(instance.getId());
for (Nic nic: nics) {
Network network = _networkDao.findById(nic.getNetworkId());
if (network.getTrafficType() == Networks.TrafficType.Guest && network.getVpcId() != null) {
if (!vpcIds.contains(network.getVpcId())) {
vpcIds.add(network.getVpcId());
}
}
}
}
return vpcIds;
}
/**
* get the list of all active Vm id's in a network
*/
@Override
public List<Long> getAllActiveVmsInNetwork(long networkId) {
List <Long> vmIds = new ArrayList<>();
List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(networkId,
VirtualMachine.State.Running, VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Unknown,
VirtualMachine.State.Migrating);
// Find routers for the network
List<DomainRouterVO> routers = _routerDao.findByNetwork(networkId);
if (vms != null) {
for (UserVmVO vm : vms) {
vmIds.add(vm.getId());
}
}
if (routers.size() != 0) {
for (DomainRouterVO router: routers) {
vmIds.add(router.getId());
}
}
return vmIds;
}
/**
* get the list of all active Vm id's in the VPC for all ther tiers
*/
@Override
public List<Long> getAllActiveVmsInVpc(long vpcId) {
Set<Long> vmIdsSet = new HashSet<>();
List<? extends Network> vpcNetworks = _vpcMgr.getVpcNetworks(vpcId);
for (Network network : vpcNetworks) {
List<Long> networkVmIds = getAllActiveVmsInNetwork(network.getId());
if (networkVmIds != null && !networkVmIds.isEmpty()) {
vmIdsSet.addAll(networkVmIds);
}
}
List<Long> vmIds = new ArrayList<>();
vmIds.addAll(vmIdsSet);
return vmIds;
}
/**
* get the list of all Vm id's in the VPC for all the tiers that are running on the host
*/
@Override
public List<Long> getActiveVmsInVpcOnHost(long vpcId, long hostId) {
Set<Long> vmIdsSet = new HashSet<>();
List<? extends Network> vpcNetworks = _vpcMgr.getVpcNetworks(vpcId);
for (Network network : vpcNetworks) {
List<Long> networkVmIds = getActiveVmsInNetworkOnHost(network.getId(), hostId);
if (networkVmIds != null && !networkVmIds.isEmpty()) {
vmIdsSet.addAll(networkVmIds);
}
}
List<Long> vmIds = new ArrayList<>();
vmIds.addAll(vmIdsSet);
return vmIds;
}
/**
* get the list of all Vm id's in the network that are running on the host
*/
@Override
public List<Long> getActiveVmsInNetworkOnHost(long networkId, long hostId) {
List <Long> vmIds = new ArrayList<>();
List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(networkId,
VirtualMachine.State.Running, VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Unknown,
VirtualMachine.State.Migrating);
// Find routers for the network
List<DomainRouterVO> routers = _routerDao.findByNetwork(networkId);
if (vms != null) {
for (UserVmVO vm : vms) {
if (vm.getHostId() == hostId)
vmIds.add(vm.getId());
}
}
if (routers.size() != 0) {
for (DomainRouterVO router: routers) {
if (router.getHostId() == hostId)
vmIds.add(router.getId());
}
}
return vmIds;
}
/**
* get the list of all Vpc id's in which, a VM has a nic in the network that is part of VPC
*/
@Override
public List<Long> getVpcIdsVmIsPartOf(long vmId) {
List<Long> vpcIds = new ArrayList<>();
List<NicVO> nics = _nicDao.listByVmId(vmId);
if (nics == null)
return null;
for (Nic nic: nics) {
Network network = _networkDao.findById(nic.getNetworkId());
if (network != null && network.getTrafficType() == Networks.TrafficType.Guest && network.getVpcId() != null) {
if (!vpcIds.contains(network.getVpcId())) {
vpcIds.add(network.getVpcId());
}
}
}
return vpcIds;
}
}

View File

@ -16,18 +16,24 @@
// under the License.
package com.cloud.network.ovs;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.network.Network;
import com.cloud.utils.component.Manager;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface OvsTunnelManager extends Manager {
boolean isOvsTunnelEnabled();
public void vmCheckAndCreateTunnel(VirtualMachineProfile vm, Network nw, DeployDestination dest);
/**
* create a bridge on the host if not already created for the network and establish full tunnel mesh with
* the rest of the hosts on which network spans
*/
public void checkAndPrepareHostForTunnelNetwork(Network nw, Host host);
public void checkAndDestroyTunnel(VirtualMachine vm, Network nw);
/**
* remove the bridge and tunnels to the hosts on which network spans if there are no other VM's
* belonging to the network are running on the host
*/
public void checkAndRemoveHostFromTunnelNetwork(Network nw, Host host);
}

View File

@ -16,6 +16,31 @@
// under the License.
package com.cloud.network.ovs;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.OvsCreateTunnelAnswer;
import com.cloud.agent.api.OvsCreateTunnelCommand;
import com.cloud.agent.api.OvsDestroyBridgeCommand;
import com.cloud.agent.api.OvsDestroyTunnelCommand;
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
import com.cloud.agent.api.OvsFetchInterfaceCommand;
import com.cloud.agent.api.OvsSetupBridgeCommand;
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.vpc.NetworkACLVO;
import com.cloud.network.vpc.NetworkACLItemDao;
import com.cloud.network.vpc.NetworkACLItemVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpc.VpcManager;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.NetworkACLDao;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.Nic;
import com.cloud.vm.NicVO;
import com.cloud.vm.VirtualMachine;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -27,24 +52,16 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import javax.persistence.EntityExistsException;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.OvsCreateTunnelAnswer;
import com.cloud.agent.api.OvsCreateTunnelCommand;
import com.cloud.agent.api.OvsDestroyBridgeCommand;
import com.cloud.agent.api.OvsDestroyTunnelCommand;
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
import com.cloud.agent.api.OvsFetchInterfaceCommand;
import com.cloud.agent.api.OvsSetupBridgeCommand;
import com.cloud.agent.manager.Commands;
import com.cloud.configuration.Config;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.Host;
@ -60,23 +77,18 @@ import com.cloud.network.ovs.dao.OvsTunnelInterfaceDao;
import com.cloud.network.ovs.dao.OvsTunnelInterfaceVO;
import com.cloud.network.ovs.dao.OvsTunnelNetworkDao;
import com.cloud.network.ovs.dao.OvsTunnelNetworkVO;
import com.cloud.network.ovs.dao.OvsTunnel;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.fsm.StateListener;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Component
@Local(value = {OvsTunnelManager.class})
public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManager {
public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManager, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualMachine> {
public static final Logger s_logger = Logger.getLogger(OvsTunnelManagerImpl.class.getName());
// boolean _isEnabled;
@ -91,8 +103,7 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
HostDao _hostDao;
@Inject
PhysicalNetworkTrafficTypeDao _physNetTTDao;
@Inject
UserVmDao _userVmDao;
@Inject
DomainRouterDao _routerDao;
@Inject
@ -101,6 +112,22 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
OvsTunnelInterfaceDao _tunnelInterfaceDao;
@Inject
AgentManager _agentMgr;
@Inject
OvsNetworkTopologyGuru _ovsNetworkToplogyGuru;
@Inject
VpcDao _vpcDao;
@Inject
VpcManager _vpcMgr;
@Inject
protected VMInstanceDao _vmInstanceDao;
@Inject
NetworkDao _networkDao;
@Inject
MessageBus _messageBus;
@Inject
NetworkACLDao _networkACLDao;
@Inject
NetworkACLItemDao _networkACLItemDao;
@Override
public boolean configure(String name, Map<String, Object> params)
@ -108,6 +135,12 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
_executorPool = Executors.newScheduledThreadPool(10, new NamedThreadFactory("OVS"));
_cleanupExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("OVS-Cleanup"));
// register for network ACL updated for a VPC.
_messageBus.subscribe("Network_ACL_Replaced", new NetworkAclEventsSubscriber());
// register for VM state transition updates
VirtualMachine.State.getStateMachine().registerListener(this);
return true;
}
@ -182,13 +215,13 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
from, to, networkId));
}
if (!r.getResult()) {
tunnel.setState("FAILED");
s_logger.warn("Create GRE tunnel failed due to " + r.getDetails()
tunnel.setState(OvsTunnel.State.Failed.name());
s_logger.warn("Create GRE tunnel from " + from + " to " + to + " failed due to " + r.getDetails()
+ s);
} else {
tunnel.setState("SUCCESS");
tunnel.setState(OvsTunnel.State.Established.name());
tunnel.setPortName(r.getInPortName());
s_logger.warn("Create GRE tunnel " + r.getDetails() + s);
s_logger.info("Create GRE tunnel from " + from + " to " + to + " succeeded." + r.getDetails() + s);
}
_tunnelNetworkDao.update(tunnel.getId(), tunnel);
}
@ -249,13 +282,14 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
int key = 0;
try {
//The GRE key is actually in the host part of the URI
// this is not true for lswitch/NiciraNvp!
String keyStr = BroadcastDomainType.getValue(network.getBroadcastUri());
// The key is most certainly and int if network is a vlan.
// !! not in the case of lswitch/pvlan/(possibly)vswitch
// So we now feel quite safe in converting it into a string
// by calling the appropriate BroadcastDomainType method
key = Integer.parseInt(keyStr);
String keyStr = network.getBroadcastUri().getAuthority();
if (keyStr.contains(".")) {
String[] parts = keyStr.split("\\.");
key = Integer.parseInt(parts[1]);
} else {
key = Integer.parseInt(keyStr);
}
return key;
} catch (NumberFormatException e) {
s_logger.debug("Well well, how did '" + key
@ -268,41 +302,23 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
}
@DB
protected void checkAndCreateTunnel(VirtualMachine instance, Network nw, DeployDestination dest) {
protected void checkAndCreateTunnel(Network nw, Host host) {
s_logger.debug("Creating tunnels with OVS tunnel manager");
if (instance.getType() != VirtualMachine.Type.User
&& instance.getType() != VirtualMachine.Type.DomainRouter) {
s_logger.debug("Will not work if you're not"
+ "an instance or a virtual router");
return;
}
long hostId = dest.getHost().getId();
long hostId = host.getId();
int key = getGreKey(nw);
// Find active VMs with a NIC on the target network
List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(nw.getId(),
State.Running, State.Starting, State.Stopping, State.Unknown,
State.Migrating);
// Find routers for the network
List<DomainRouterVO> routers = _routerDao.findByNetwork(nw.getId());
List<VMInstanceVO> ins = new ArrayList<VMInstanceVO>();
if (vms != null) {
ins.addAll(vms);
}
if (routers.size() != 0) {
ins.addAll(routers);
}
String bridgeName = generateBridgeName(nw, key);
List<Long> toHostIds = new ArrayList<Long>();
List<Long> fromHostIds = new ArrayList<Long>();
for (VMInstanceVO v : ins) {
Long rh = v.getHostId();
if (rh == null || rh.longValue() == hostId) {
List<Long> networkSpannedHosts = _ovsNetworkToplogyGuru.getNetworkSpanedHosts(nw.getId());
for (Long rh : networkSpannedHosts) {
if (rh == hostId) {
continue;
}
OvsTunnelNetworkVO ta = _tunnelNetworkDao.getByFromToNetwork(hostId, rh.longValue(), nw.getId());
// Try and create the tunnel even if a previous attempt failed
if (ta == null || ta.getState().equals("FAILED")) {
if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + rh.longValue());
if (ta == null) {
createTunnelRecord(hostId, rh.longValue(), nw.getId(), key);
@ -315,7 +331,7 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
ta = _tunnelNetworkDao.getByFromToNetwork(rh.longValue(),
hostId, nw.getId());
// Try and create the tunnel even if a previous attempt failed
if (ta == null || ta.getState().equals("FAILED")) {
if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
s_logger.debug("Attempting to create tunnel from:" +
rh.longValue() + " to:" + hostId);
if (ta == null) {
@ -329,9 +345,9 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
}
//TODO: Should we propagate the exception here?
try {
String myIp = getGreEndpointIP(dest.getHost(), nw);
String myIp = getGreEndpointIP(host, nw);
if (myIp == null)
throw new GreTunnelException("Unable to retrieve the source " + "endpoint for the GRE tunnel." + "Failure is on host:" + dest.getHost().getId());
throw new GreTunnelException("Unable to retrieve the source " + "endpoint for the GRE tunnel." + "Failure is on host:" + host.getId());
boolean noHost = true;
for (Long i : toHostIds) {
HostVO rHost = _hostDao.findById(i);
@ -343,7 +359,8 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
+ "Failure is on host:" + rHost.getId());
Commands cmds = new Commands(
new OvsCreateTunnelCommand(otherIp, key,
Long.valueOf(hostId), i, nw.getId(), myIp));
Long.valueOf(hostId), i, nw.getId(), myIp, bridgeName, nw.getUuid()));
s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + i + " for the network " + nw.getId());
s_logger.debug("Ask host " + hostId
+ " to create gre tunnel to " + i);
Answer[] answers = _agentMgr.send(hostId, cmds);
@ -355,21 +372,19 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
HostVO rHost = _hostDao.findById(i);
String otherIp = getGreEndpointIP(rHost, nw);
Commands cmds = new Commands(new OvsCreateTunnelCommand(myIp,
key, i, Long.valueOf(hostId), nw.getId(), otherIp));
key, i, Long.valueOf(hostId), nw.getId(), otherIp, bridgeName, nw.getUuid()));
s_logger.debug("Ask host " + i + " to create gre tunnel to "
+ hostId);
Answer[] answers = _agentMgr.send(i, cmds);
handleCreateTunnelAnswer(answers);
noHost = false;
}
// If no tunnels have been configured, perform the bridge setup
// anyway
// This will ensure VIF rules will be triggered
// anyway. This will ensure VIF rules will be triggered
if (noHost) {
Commands cmds = new Commands(new OvsSetupBridgeCommand(key,
hostId, nw.getId()));
s_logger.debug("Ask host " + hostId
+ " to configure bridge for network:" + nw.getId());
Commands cmds = new Commands(new OvsSetupBridgeCommand(bridgeName, hostId, nw.getId()));
s_logger.debug("Ask host " + hostId + " to configure bridge for network:" + nw.getId());
Answer[] answers = _agentMgr.send(hostId, cmds);
handleSetupBridgeAnswer(answers);
}
@ -384,10 +399,20 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
return true;
}
boolean isVpcEnabledForDistributedRouter(long vpcId) {
VpcVO vpc = _vpcDao.findById(vpcId);
return vpc.usesDistributedRouter();
}
@Override
public void vmCheckAndCreateTunnel(VirtualMachineProfile vm,
Network nw, DeployDestination dest) {
checkAndCreateTunnel(vm.getVirtualMachine(), nw, dest);
public void checkAndPrepareHostForTunnelNetwork(Network nw, Host host) {
if (nw.getVpcId() != null && isVpcEnabledForDistributedRouter(nw.getVpcId())) {
// check and setup host to be in full tunnel mesh with each of the network in the VPC
checkAndCreateVpcTunnelNetworks(host, nw.getVpcId());
} else {
// check and setup host to be in full tunnel mesh with the network
checkAndCreateTunnel(nw, host);
}
}
@DB
@ -440,54 +465,430 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
}
@Override
public void checkAndDestroyTunnel(VirtualMachine vm, Network nw) {
// if (!_isEnabled) {
// return;
// }
public void checkAndRemoveHostFromTunnelNetwork(Network nw, Host host) {
List<UserVmVO> userVms = _userVmDao.listByAccountIdAndHostId(vm.getAccountId(), vm.getHostId());
if (vm.getType() == VirtualMachine.Type.User) {
if (userVms.size() > 1) {
if (nw.getVpcId() != null && isVpcEnabledForDistributedRouter(nw.getVpcId())) {
List<Long> vmIds = _ovsNetworkToplogyGuru.getActiveVmsInVpcOnHost(nw.getVpcId(), host.getId());
if (vmIds != null && !vmIds.isEmpty()) {
return;
}
List<DomainRouterVO> routers = _routerDao.findByNetwork(nw.getId());
for (DomainRouterVO router : routers) {
if (router.getHostId().equals(vm.getHostId())) {
return;
List<? extends Network> vpcNetworks = _vpcMgr.getVpcNetworks(nw.getVpcId());
try {
for (Network network: vpcNetworks) {
int key = getGreKey(nw);
String bridgeName = generateBridgeName(nw, key);
/* Then ask hosts have peer tunnel with me to destroy them */
List<OvsTunnelNetworkVO> peers = _tunnelNetworkDao.listByToNetwork(host.getId(),nw.getId());
for (OvsTunnelNetworkVO p : peers) {
// If the tunnel was not successfully created don't bother to remove it
if (p.getState().equals(OvsTunnel.State.Established.name())) {
Command cmd= new OvsDestroyTunnelCommand(p.getNetworkId(), bridgeName,
p.getPortName());
s_logger.debug("Destroying tunnel to " + host.getId() +
" from " + p.getFrom());
Answer ans = _agentMgr.send(p.getFrom(), cmd);
handleDestroyTunnelAnswer(ans, p.getFrom(), p.getTo(), p.getNetworkId());
}
}
}
}
} else if (vm.getType() == VirtualMachine.Type.DomainRouter && userVms.size() != 0) {
return;
}
try {
/* Now we are last one on host, destroy the bridge with all
* the tunnels for this network */
int key = getGreKey(nw);
Command cmd = new OvsDestroyBridgeCommand(nw.getId(), key);
s_logger.debug("Destroying bridge for network " + nw.getId() + " on host:" + vm.getHostId());
Answer ans = _agentMgr.send(vm.getHostId(), cmd);
handleDestroyBridgeAnswer(ans, vm.getHostId(), nw.getId());
/* Then ask hosts have peer tunnel with me to destroy them */
List<OvsTunnelNetworkVO> peers =
_tunnelNetworkDao.listByToNetwork(vm.getHostId(),
nw.getId());
for (OvsTunnelNetworkVO p : peers) {
// If the tunnel was not successfully created don't bother to remove it
if (p.getState().equals("SUCCESS")) {
cmd = new OvsDestroyTunnelCommand(p.getNetworkId(), key,
p.getPortName());
s_logger.debug("Destroying tunnel to " + vm.getHostId() +
" from " + p.getFrom());
ans = _agentMgr.send(p.getFrom(), cmd);
handleDestroyTunnelAnswer(ans, p.getFrom(),
p.getTo(), p.getNetworkId());
}
Command cmd = new OvsDestroyBridgeCommand(nw.getId(), generateBridgeNameForVpc(nw.getVpcId()));
s_logger.debug("Destroying bridge for network " + nw.getId() + " on host:" + host.getId());
Answer ans = _agentMgr.send(host.getId(), cmd);
handleDestroyBridgeAnswer(ans, host.getId(), nw.getId());
} catch (Exception e) {
}
} else {
List<Long> vmIds = _ovsNetworkToplogyGuru.getActiveVmsInNetworkOnHost(nw.getId(), host.getId());
if (vmIds != null && !vmIds.isEmpty()) {
return;
}
try {
/* Now we are last one on host, destroy the bridge with all
* the tunnels for this network */
int key = getGreKey(nw);
String bridgeName = generateBridgeName(nw, key);
Command cmd = new OvsDestroyBridgeCommand(nw.getId(), bridgeName);
s_logger.debug("Destroying bridge for network " + nw.getId() + " on host:" + host.getId());
Answer ans = _agentMgr.send(host.getId(), cmd);
handleDestroyBridgeAnswer(ans, host.getId(), nw.getId());
/* Then ask hosts have peer tunnel with me to destroy them */
List<OvsTunnelNetworkVO> peers =
_tunnelNetworkDao.listByToNetwork(host.getId(),
nw.getId());
for (OvsTunnelNetworkVO p : peers) {
// If the tunnel was not successfully created don't bother to remove it
if (p.getState().equals(OvsTunnel.State.Established.name())) {
cmd = new OvsDestroyTunnelCommand(p.getNetworkId(), bridgeName,
p.getPortName());
s_logger.debug("Destroying tunnel to " + host.getId() +
" from " + p.getFrom());
ans = _agentMgr.send(p.getFrom(), cmd);
handleDestroyTunnelAnswer(ans, p.getFrom(),
p.getTo(), p.getNetworkId());
}
}
} catch (Exception e) {
s_logger.warn("Destroy tunnel failed", e);
}
} catch (Exception e) {
s_logger.warn(String.format("Destroy tunnel(account:%1$s," + "hostId:%2$s) failed", vm.getAccountId(), vm.getHostId()), e);
}
}
private String generateBridgeName(Network nw, int key) {
if (nw.getVpcId() != null && isVpcEnabledForDistributedRouter(nw.getVpcId())) {
return "OVS-DR-VPC-Bridge" + nw.getVpcId();
} else {
return "OVSTunnel"+key;
}
}
private String generateBridgeNameForVpc(long vpcId) {
return "OVS-DR-VPC-Bridge" + vpcId;
}
@DB
protected void checkAndCreateVpcTunnelNetworks(Host host, long vpcId) {
long hostId = host.getId();
List<? extends Network> vpcNetworks = _vpcMgr.getVpcNetworks(vpcId);
List<Long> vpcSpannedHostIds = _ovsNetworkToplogyGuru.getVpcSpannedHosts(vpcId);
String bridgeName=generateBridgeNameForVpc(vpcId);
boolean bridgeNotSetup = true;
for (Network vpcNetwork: vpcNetworks) {
int key = getGreKey(vpcNetwork);
List<Long> toHostIds = new ArrayList<Long>();
List<Long> fromHostIds = new ArrayList<Long>();
for (Long rh : vpcSpannedHostIds) {
if (rh == hostId) {
continue;
}
OvsTunnelNetworkVO ta = _tunnelNetworkDao.getByFromToNetwork(hostId, rh.longValue(), vpcNetwork.getId());
// Try and create the tunnel even if a previous attempt failed
if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + rh.longValue());
if (ta == null) {
createTunnelRecord(hostId, rh.longValue(), vpcNetwork.getId(), key);
}
if (!toHostIds.contains(rh)) {
toHostIds.add(rh);
}
}
ta = _tunnelNetworkDao.getByFromToNetwork(rh.longValue(),
hostId, vpcNetwork.getId());
// Try and create the tunnel even if a previous attempt failed
if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
s_logger.debug("Attempting to create tunnel from:" +
rh.longValue() + " to:" + hostId);
if (ta == null) {
createTunnelRecord(rh.longValue(), hostId,
vpcNetwork.getId(), key);
}
if (!fromHostIds.contains(rh)) {
fromHostIds.add(rh);
}
}
}
try {
String myIp = getGreEndpointIP(host, vpcNetwork);
if (myIp == null)
throw new GreTunnelException("Unable to retrieve the source " + "endpoint for the GRE tunnel."
+ "Failure is on host:" + host.getId());
boolean noHost = true;
for (Long i : toHostIds) {
HostVO rHost = _hostDao.findById(i);
String otherIp = getGreEndpointIP(rHost, vpcNetwork);
if (otherIp == null)
throw new GreTunnelException(
"Unable to retrieve the remote "
+ "endpoint for the GRE tunnel."
+ "Failure is on host:" + rHost.getId());
Commands cmds = new Commands(
new OvsCreateTunnelCommand(otherIp, key,
Long.valueOf(hostId), i, vpcNetwork.getId(), myIp, bridgeName,
vpcNetwork.getUuid()));
s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + i + " for the network "
+ vpcNetwork.getId());
s_logger.debug("Ask host " + hostId
+ " to create gre tunnel to " + i);
Answer[] answers = _agentMgr.send(hostId, cmds);
handleCreateTunnelAnswer(answers);
bridgeNotSetup = false;
}
for (Long i : fromHostIds) {
HostVO rHost = _hostDao.findById(i);
String otherIp = getGreEndpointIP(rHost, vpcNetwork);
Commands cmds = new Commands(new OvsCreateTunnelCommand(myIp,
key, i, Long.valueOf(hostId), vpcNetwork.getId(), otherIp, bridgeName,
vpcNetwork.getUuid()));
s_logger.debug("Ask host " + i + " to create gre tunnel to "
+ hostId);
Answer[] answers = _agentMgr.send(i, cmds);
handleCreateTunnelAnswer(answers);
bridgeNotSetup = false;
}
} catch (GreTunnelException | OperationTimedoutException | AgentUnavailableException e) {
// I really thing we should do a better handling of these exceptions
s_logger.warn("Ovs Tunnel network created tunnel failed", e);
}
}
// If no tunnels have been configured, perform the bridge setup
// anyway. This will ensure VIF rules will be triggered
if (bridgeNotSetup) {
try {
Commands cmds = new Commands(new OvsSetupBridgeCommand(bridgeName, hostId, null));
s_logger.debug("Ask host " + hostId + " to configure bridge for vpc");
Answer[] answers = _agentMgr.send(hostId, cmds);
handleSetupBridgeAnswer(answers);
} catch (OperationTimedoutException | AgentUnavailableException e) {
// I really thing we should do a better handling of these exceptions
s_logger.warn("Ovs Tunnel network created tunnel failed", e);
}
}
}
@Override
public boolean preStateTransitionEvent(VirtualMachine.State oldState,
VirtualMachine.Event event, VirtualMachine.State newState,
VirtualMachine vo, boolean status, Object opaque) {
return true;
}
@Override
public boolean postStateTransitionEvent(VirtualMachine.State oldState, VirtualMachine.Event event,
VirtualMachine.State newState, VirtualMachine vm,
boolean status, Object opaque) {
if (!status) {
return false;
}
if (VirtualMachine.State.isVmStarted(oldState, event, newState)) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Security Group Mgr: handling start of vm id" + vm.getId());
}
handleVmStateChange((VMInstanceVO)vm);
} else if (VirtualMachine.State.isVmStopped(oldState, event, newState)) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Security Group Mgr: handling stop of vm id" + vm.getId());
}
handleVmStateChange((VMInstanceVO)vm);
} else if (VirtualMachine.State.isVmMigrated(oldState, event, newState)) {
if (s_logger.isTraceEnabled()) {
s_logger.trace("Security Group Mgr: handling migration of vm id" + vm.getId());
}
handleVmStateChange((VMInstanceVO)vm);
}
return true;
}
public void handleVmStateChange(VMInstanceVO vm) {
// get the VPC's impacted with the VM start
List<Long> vpcIds = _ovsNetworkToplogyGuru.getVpcIdsVmIsPartOf(vm.getId());
if (vpcIds == null || vpcIds.isEmpty()) {
return;
}
for (Long vpcId: vpcIds) {
VpcVO vpc = _vpcDao.findById(vpcId);
if (vpc == null || !vpc.usesDistributedRouter()) {
return;
}
// get the list of hosts on which VPC spans (i.e hosts that need to be aware of VPC topology change update)
List<Long> vpcSpannedHostIds = _ovsNetworkToplogyGuru.getVpcSpannedHosts(vpcId);
String bridgeName=generateBridgeNameForVpc(vpcId);
OvsVpcPhysicalTopologyConfigCommand topologyConfigCommand = prepareVpcTopologyUpdate(vpcId);
for (Long id: vpcSpannedHostIds) {
if (!sendVpcTopologyChangeUpdate(topologyConfigCommand, id, bridgeName)) {
s_logger.debug("Failed to send VPC topology change update to host : " + id + ". Moving on " +
"with rest of the host update.");
}
}
}
}
public boolean sendVpcTopologyChangeUpdate(OvsVpcPhysicalTopologyConfigCommand updateCmd, long hostId, String bridgeName) {
try {
s_logger.debug("Sending VPC topology change update to the host " + hostId);
updateCmd.setHostId(hostId);
updateCmd.setBridgeName(bridgeName);
Answer ans = _agentMgr.send(hostId, updateCmd);
if (ans.getResult()) {
s_logger.debug("Successfully updated the host " + hostId + " with latest VPC topology." );
return true;
} else {
s_logger.debug("Failed to update the host " + hostId + " with latest VPC topology." );
return false;
}
} catch (Exception e) {
s_logger.debug("Failed to updated the host " + hostId + " with latest VPC topology.", e );
return false;
}
}
OvsVpcPhysicalTopologyConfigCommand prepareVpcTopologyUpdate(long vpcId) {
VpcVO vpc = _vpcDao.findById(vpcId);
assert (vpc != null): "invalid vpc id";
List<? extends Network> vpcNetworks = _vpcMgr.getVpcNetworks(vpcId);
List<Long> hostIds = _ovsNetworkToplogyGuru.getVpcSpannedHosts(vpcId);
List<Long> vmIds = _ovsNetworkToplogyGuru.getAllActiveVmsInVpc(vpcId);
List<OvsVpcPhysicalTopologyConfigCommand.Host> hosts = new ArrayList<>();
List<OvsVpcPhysicalTopologyConfigCommand.Tier> tiers = new ArrayList<>();
List<OvsVpcPhysicalTopologyConfigCommand.Vm> vms = new ArrayList<>();
for (Long hostId : hostIds) {
HostVO hostDetails = _hostDao.findById(hostId);
String remoteIp = null;
for (Network network: vpcNetworks) {
try {
remoteIp = getGreEndpointIP(hostDetails, network);
} catch (Exception e) {
}
}
OvsVpcPhysicalTopologyConfigCommand.Host host = new OvsVpcPhysicalTopologyConfigCommand.Host(hostId, remoteIp);
hosts.add(host);
}
for (Network network: vpcNetworks) {
String key = network.getBroadcastUri().getAuthority();
long gre_key;
if (key.contains(".")) {
String[] parts = key.split("\\.");
gre_key = Long.parseLong(parts[1]);
} else {
try {
gre_key = Long.parseLong(BroadcastDomainType.getValue(key));
} catch (Exception e) {
return null;
}
}
NicVO nic = _nicDao.findByIp4AddressAndNetworkId(network.getGateway(), network.getId());
OvsVpcPhysicalTopologyConfigCommand.Tier tier = new OvsVpcPhysicalTopologyConfigCommand.Tier(gre_key,
network.getUuid(), network.getGateway(), nic.getMacAddress(), network.getCidr());
tiers.add(tier);
}
for (long vmId: vmIds) {
VirtualMachine vmInstance = _vmInstanceDao.findById(vmId);
List<OvsVpcPhysicalTopologyConfigCommand.Nic> vmNics = new ArrayList<OvsVpcPhysicalTopologyConfigCommand.Nic>();
for (Nic vmNic :_nicDao.listByVmId(vmId)) {
Network network = _networkDao.findById(vmNic.getNetworkId());
if (network.getTrafficType() == TrafficType.Guest) {
OvsVpcPhysicalTopologyConfigCommand.Nic nic = new OvsVpcPhysicalTopologyConfigCommand.Nic(
vmNic.getIp4Address(), vmNic.getMacAddress(), network.getUuid());
vmNics.add(nic);
}
}
OvsVpcPhysicalTopologyConfigCommand.Vm vm = new OvsVpcPhysicalTopologyConfigCommand.Vm(
vmInstance.getHostId(), vmNics.toArray(new OvsVpcPhysicalTopologyConfigCommand.Nic[vmNics.size()]));
vms.add(vm);
}
return new OvsVpcPhysicalTopologyConfigCommand(
hosts.toArray(new OvsVpcPhysicalTopologyConfigCommand.Host[hosts.size()]),
tiers.toArray(new OvsVpcPhysicalTopologyConfigCommand.Tier[tiers.size()]),
vms.toArray(new OvsVpcPhysicalTopologyConfigCommand.Vm[vms.size()]),
vpc.getCidr());
}
// Subscriber to ACL replace events. On acl replace event, if the vpc for the tier is enabled for
// distributed routing send the ACL update to all the hosts on which VPC spans
public class NetworkAclEventsSubscriber implements MessageSubscriber {
@Override
public void onPublishMessage(String senderAddress, String subject, Object args) {
try {
NetworkVO network = (NetworkVO) args;
String bridgeName=generateBridgeNameForVpc(network.getVpcId());
if (network.getVpcId() != null && isVpcEnabledForDistributedRouter(network.getVpcId())) {
long vpcId = network.getVpcId();
OvsVpcRoutingPolicyConfigCommand cmd = prepareVpcRoutingPolicyUpdate(vpcId);
List<Long> vpcSpannedHostIds = _ovsNetworkToplogyGuru.getVpcSpannedHosts(vpcId);
for (Long id: vpcSpannedHostIds) {
if (!sendVpcRoutingPolicyChangeUpdate(cmd, id, bridgeName)) {
s_logger.debug("Failed to send VPC routing policy change update to host : " + id +
". But moving on with sending the updates to the rest of the hosts.");
}
}
}
} catch (Exception e) {
s_logger.debug("Failed to send VPC routing policy change updates all hosts in vpc", e);
}
}
}
private OvsVpcRoutingPolicyConfigCommand prepareVpcRoutingPolicyUpdate(long vpcId) {
List<OvsVpcRoutingPolicyConfigCommand.Acl> acls = new ArrayList<>();
List<OvsVpcRoutingPolicyConfigCommand.Tier> tiers = new ArrayList<>();
VpcVO vpc = _vpcDao.findById(vpcId);
List<? extends Network> vpcNetworks = _vpcMgr.getVpcNetworks(vpcId);
assert (vpc != null && (vpcNetworks != null && !vpcNetworks.isEmpty())): "invalid vpc id";
for (Network network : vpcNetworks) {
Long networkAclId = network.getNetworkACLId();
if (networkAclId == null)
continue;
NetworkACLVO networkAcl = _networkACLDao.findById(networkAclId);
List<OvsVpcRoutingPolicyConfigCommand.AclItem> aclItems = new ArrayList<>();
List<NetworkACLItemVO> aclItemVos = _networkACLItemDao.listByACL(networkAclId);
for (NetworkACLItemVO aclItem : aclItemVos) {
String[] sourceCidrs = aclItem.getSourceCidrList().toArray(new String[aclItem.getSourceCidrList().size()]);
aclItems.add(new OvsVpcRoutingPolicyConfigCommand.AclItem(
aclItem.getNumber(), aclItem.getUuid(), aclItem.getAction().name(),
aclItem.getTrafficType().name(),
((aclItem.getSourcePortStart() != null) ?aclItem.getSourcePortStart().toString() :null),
((aclItem.getSourcePortEnd() != null) ?aclItem.getSourcePortEnd().toString() :null),
aclItem.getProtocol(),
sourceCidrs));
}
OvsVpcRoutingPolicyConfigCommand.Acl acl = new OvsVpcRoutingPolicyConfigCommand.Acl(networkAcl.getUuid(),
aclItems.toArray(new OvsVpcRoutingPolicyConfigCommand.AclItem[aclItems.size()]));
acls.add(acl);
OvsVpcRoutingPolicyConfigCommand.Tier tier = new OvsVpcRoutingPolicyConfigCommand.Tier(network.getUuid(),
network.getCidr(), networkAcl.getUuid());
tiers.add(tier);
}
OvsVpcRoutingPolicyConfigCommand cmd = new OvsVpcRoutingPolicyConfigCommand(vpc.getUuid(), vpc.getCidr(),
acls.toArray(new OvsVpcRoutingPolicyConfigCommand.Acl[acls.size()]),
tiers.toArray(new OvsVpcRoutingPolicyConfigCommand.Tier[tiers.size()]));
return cmd;
}
public boolean sendVpcRoutingPolicyChangeUpdate(OvsVpcRoutingPolicyConfigCommand updateCmd, long hostId, String bridgeName) {
try {
s_logger.debug("Sending VPC routing policies change update to the host " + hostId);
updateCmd.setHostId(hostId);
updateCmd.setBridgeName(bridgeName);
Answer ans = _agentMgr.send(hostId, updateCmd);
if (ans.getResult()) {
s_logger.debug("Successfully updated the host " + hostId + " with latest VPC routing policies." );
return true;
} else {
s_logger.debug("Failed to update the host " + hostId + " with latest routing policies." );
return false;
}
} catch (Exception e) {
s_logger.debug("Failed to updated the host " + hostId + " with latest routing policies due to" , e );
return false;
}
}
}

View File

@ -0,0 +1,24 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.cloud.network.ovs.dao;
public interface OvsTunnel {
public enum State {
Created, Established, Failed
}
}

View File

@ -62,7 +62,7 @@ public class OvsTunnelNetworkVO implements InternalIdentity {
this.key = key;
this.networkId = networkId;
this.portName = "[]";
this.state = "FAILED";
this.state = OvsTunnel.State.Created.name();
}
public void setKey(int key) {

View File

@ -21,6 +21,7 @@ import ConfigParser
import logging
import os
import subprocess
import simplejson as json
from time import localtime, asctime
@ -176,10 +177,11 @@ def _build_flow_expr(**kwargs):
dl_dst = 'dl_dst' in kwargs and ",dl_dst=%s" % kwargs['dl_dst'] or ''
nw_src = 'nw_src' in kwargs and ",nw_src=%s" % kwargs['nw_src'] or ''
nw_dst = 'nw_dst' in kwargs and ",nw_dst=%s" % kwargs['nw_dst'] or ''
table = 'table' in kwargs and ",table=%s" % kwargs['table'] or ''
proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or ''
ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or ''
flow = (flow + in_port + dl_type + dl_src + dl_dst +
(ip or proto) + nw_src + nw_dst)
(ip or proto) + nw_src + nw_dst + table)
return flow
@ -219,3 +221,259 @@ def del_all_flows(bridge):
def del_port(bridge, port):
delPort = [VSCTL_PATH, "del-port", bridge, port]
do_cmd(delPort)
def get_network_id_for_vif(vif_name):
domain_id, device_id = vif_name[3:len(vif_name)].split(".")
dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "--minimal"])
vif_uuid = do_cmd([XE_PATH, "vif-list", "vm-uuid=%s" % dom_uuid, "device=%s" % device_id, "--minimal"])
vnet = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=other-config",
"param-key=cloudstack-network-id"])
return vnet
def get_network_id_for_tunnel_port(tunnelif_name):
vnet = do_cmd([VSCTL_PATH, "get", "interface", tunnelif_name, "options:cloudstack-network-id"])
return vnet
def clear_flooding_rules_for_port(bridge, ofport):
del_flows(bridge, in_port=ofport, table=2)
def add_flooding_rules_for_port(bridge, in_ofport, out_ofports):
action = "".join("output:%s," %ofport for ofport in out_ofports)[:-1]
add_flow(bridge, priority=1100, in_port=in_ofport, table=2, actions=action)
def get_ofport_for_vif(vif_name):
return do_cmd([VSCTL_PATH, "get", "interface", vif_name, "ofport"])
def get_macaddress_of_vif(vif_name):
domain_id, device_id = vif_name[3:len(vif_name)].split(".")
dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "--minimal"])
vif_uuid = do_cmd([XE_PATH, "vif-list", "vm-uuid=%s" % dom_uuid, "device=%s" % device_id, "--minimal"])
mac = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=MAC"])
return mac
def get_vif_name_from_macaddress(macaddress):
vif_uuid = do_cmd([XE_PATH, "vif-list", "MAC=%s" % macaddress, "--minimal"])
vif_device_id = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=device"])
vm_uuid = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=vm-uuid"])
vm_domain_id = do_cmd([XE_PATH, "vm-param-get", "uuid=%s" % vm_uuid, "param-name=dom-id"])
return "vif"+vm_domain_id+"."+vif_device_id
def add_mac_lookup_table_entry(bridge, mac_address, out_of_port):
action = "output=%s" %out_of_port
add_flow(bridge, priority=1100, dl_dst=mac_address, table=1, actions=action)
def delete_mac_lookup_table_entry(bridge, mac_address):
del_flows(bridge, dl_dst=mac_address, table=1)
def add_ip_lookup_table_entry(bridge, ip, dst_tier_gateway_mac, dst_vm_mac):
action_str = "mod_dl_src:%s" % dst_tier_gateway_mac + ",mod_dl_dst:%s" % dst_vm_mac + ",resubmit(,5)"
action_str = "table=4, ip, nw_dst=%s" % ip + ", actions=%s" %action_str
addflow = [OFCTL_PATH, "add-flow", bridge, action_str]
do_cmd(addflow)
def get_vms_on_host(vpc, host_id):
all_vms = vpc.vms
vms_on_host = []
for vm in all_vms:
if str(vm.hostid) == (host_id):
vms_on_host.append(vm)
return vms_on_host
def get_network_details(vpc, network_uuid):
tiers = vpc.tiers
for tier in tiers:
if str(tier.networkuuid) == (network_uuid):
return tier
return None
class jsonLoader(object):
def __init__(self, obj):
for k in obj:
v = obj[k]
if isinstance(v, dict):
setattr(self, k, jsonLoader(v))
elif isinstance(v, (list, tuple)):
if len(v) > 0 and isinstance(v[0], dict):
setattr(self, k, [jsonLoader(elem) for elem in v])
else:
setattr(self, k, v)
else:
setattr(self, k, v)
def __getattr__(self, val):
if val in self.__dict__:
return self.__dict__[val]
else:
return None
def __repr__(self):
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v)
in self.__dict__.iteritems()))
def __str__(self):
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v)
in self.__dict__.iteritems()))
def configure_bridge_for_network_topology(bridge, this_host_id, json_config):
vpconfig = jsonLoader(json.loads(json_config)).vpc
if vpconfig is None:
logging.debug("WARNING:Can't find VPC info in json config file")
return "FAILURE:IMPROPER_JSON_CONFG_FILE"
try:
# get the list of Vm's in the VPC from the JSON config
this_host_vms = get_vms_on_host(vpconfig, this_host_id)
for vm in this_host_vms:
for nic in vm.nics:
mac_addr = nic.macaddress
ip = nic.ipaddress
vif_name = get_vif_name_from_macaddress(mac_addr)
of_port = get_ofport_for_vif(vif_name)
network = get_network_details(vpconfig, nic.networkuuid)
# Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet on the found OFPORT
add_mac_lookup_table_entry(bridge, mac_addr, of_port)
# Add flow rule in L3 look up table: if the destination IP = VM's IP then modify the packet
# to set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table
add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr)
# Add flow entry to send with intra tier traffic from the NIC to L2 lookup path)
action_str = "table=0, in_port=%s," %of_port + " ip, nw_dst=%s," %network.cidr + " actions=resubmit(,1)"
addflow = [OFCTL_PATH, "add-flow", bridge, action_str]
do_cmd(addflow)
#add flow entry to send inter-tier traffic from the NIC to egress ACL table(to L3 lookup path)
action_str = "table=0, in_port=%s," % of_port + " ip, dl_dst=%s," %network.gatewaymac +\
"nw_dst=%s," %vpconfig.cidr + "actions=resubmit(,3)"
addflow = [OFCTL_PATH, "add-flow", bridge, action_str]
do_cmd(addflow)
# get the list of hosts on which VPC spans from the JSON config
vpc_spanning_hosts = vpconfig.hosts
for host in vpc_spanning_hosts:
if str(this_host_id) == str(host.hostid):
continue
other_host_vms = get_vms_on_host(vpconfig, host.hostid)
for vm in other_host_vms:
for nic in vm.nics:
mac_addr = nic.macaddress
ip = nic.ipaddress
network = get_network_details(vpconfig, nic.networkuuid)
gre_key = network.grekey
# generate tunnel name from tunnel naming convention
tunnel_name = "t%s-%s-%s" % (gre_key, this_host_id, host.hostid)
of_port = get_ofport_for_vif(tunnel_name)
# Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet tunnel port
add_mac_lookup_table_entry(bridge, mac_addr, of_port)
# Add flow tule in L3 look up table: if the destination IP = VM's IP then modify the packet
# set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table
add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr)
return "SUCCESS: successfully configured bridge as per the VPC topology"
except:
logging.debug("An unexpected error occurred while configuring bridge as per VPC topology.")
raise
def get_acl(vpcconfig, required_acl_id):
acls = vpcconfig.acls
for acl in acls:
if acl.id == required_acl_id:
return acl
return None
def configure_ovs_bridge_for_routing_policies(bridge, json_config):
vpconfig = jsonLoader(json.loads(json_config)).vpc
if vpconfig is None:
logging.debug("WARNING:Can't find VPC info in json config file")
return "FAILURE:IMPROPER_JSON_CONFG_FILE"
try:
# First flush current egress ACL's before re-applying the ACL's
del_flows(bridge, table=3)
egress_rules_added = False
ingress_rules_added = False
tiers = vpconfig.tiers
for tier in tiers:
tier_cidr = tier.cidr
acl = get_acl(vpconfig, tier.aclid)
acl_items = acl.aclitems
for acl_item in acl_items:
number = acl_item.number
action = acl_item.action
direction = acl_item.direction
source_port_start = acl_item.sourceportstart
source_port_end = acl_item.sourceportend
protocol = acl_item.protocol
source_cidrs = acl_item.sourcecidrs
acl_priority = 1000 + number
for source_cidr in source_cidrs:
if direction is "ingress":
ingress_rules_added = True
if source_port_start is None and source_port_end is None:
if action is "deny":
add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr,
nw_proto=protocol, actions='drop')
if action is "allow":
add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr,
nw_proto=protocol, actions='resubmit(,1)')
continue
# add flow rule to do action (allow/deny) for flows where source IP of the packet is in
# source_cidr and destination ip is in tier_cidr
port = source_port_start
while (port < source_port_end):
if action is "deny":
add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port,
nw_proto=protocol, actions='drop')
if action is "allow":
add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port,
nw_proto=protocol, actions='resubmit(,1)')
port = port + 1
elif direction in "egress":
egress_rules_added = True
if source_port_start is None and source_port_end is None:
if action is "deny":
add_flow(bridge, priority= acl_priority, table=3, nw_src=source_cidr, nw_dst=tier_cidr,
nw_proto=protocol, actions='drop')
if action is "allow":
add_flow(bridge, priority= acl_priority,table=3, nw_src=source_cidr, nw_dst=tier_cidr,
nw_proto=protocol, actions='resubmit(,1)')
continue
# add flow rule to do action (allow/deny) for flows where destination IP of the packet is in
# source_cidr and source ip is in tier_cidr
port = source_port_start
while (port < source_port_end):
if action is "deny":
add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port,
nw_proto=protocol, actions='drop')
if action is "allow":
add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port,
nw_proto=protocol, actions='resubmit(,1)')
port = port + 1
if egress_rules_added is False:
# add a default rule in egress table to forward packet to L3 lookup table
add_flow(bridge, priority=0, table=3, actions='resubmit(,4)')
if ingress_rules_added is False:
# add a default rule in egress table drop packets
add_flow(bridge, priority=0, table=5, actions='drop')
except:
logging.debug("An unexpected error occurred while configuring bridge as per VPC's routing policies.")
raise

View File

@ -18,11 +18,14 @@
# A simple script for enabling and disabling per-vif rules for explicitly
# allowing broadcast/multicast traffic on the port where the VIF is attached
import copy
import os
import sys
import logging
import cloudstack_pluginlib as pluginlib
pluginlib.setup_logging("/var/log/cloud/ovstunnel.log")
def clear_flows(bridge, this_vif_ofport, vif_ofports):
# Remove flow entries originating from given ofport
@ -65,7 +68,6 @@ def clear_rules(vif):
except:
pass
def main(command, vif_raw):
if command not in ('online', 'offline'):
return
@ -83,42 +85,125 @@ def main(command, vif_raw):
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'iface-to-br', this_vif])
# find xs network for this bridge, verify is used for ovs tunnel network
# find xs network for this bridge, verify is used for ovs tunnel network
xs_nw_uuid = pluginlib.do_cmd([pluginlib.XE_PATH, "network-list",
"bridge=%s" % bridge, "--minimal"])
result = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get",
ovs_tunnel_network = False
try:
ovs_tunnel_network = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=is-ovs-tun-network", "--minimal"])
except:
pass
if result != 'True':
return
vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge])
if vlan != '0':
# We need the REAL bridge name
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'br-to-parent', bridge])
ovs_vpc_distributed_vr_network = False
try:
ovs_vpc_distributed_vr_network = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=is-ovs_vpc_distributed_vr_network", "--minimal"])
except:
pass
vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'list-ports', bridge])
vifs = vsctl_output.split('\n')
vif_ofports = []
for vif in vifs:
vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get',
'Interface', vif, 'ofport'])
if this_vif == vif:
this_vif_ofport = vif_ofport
if vif.startswith('vif'):
vif_ofports.append(vif_ofport)
if ovs_tunnel_network == 'True':
vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge])
if vlan != '0':
# We need the REAL bridge name
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'br-to-parent', bridge])
vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'list-ports', bridge])
vifs = vsctl_output.split('\n')
vif_ofports = []
for vif in vifs:
vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get',
'Interface', vif, 'ofport'])
if this_vif == vif:
this_vif_ofport = vif_ofport
if vif.startswith('vif'):
vif_ofports.append(vif_ofport)
if command == 'offline':
clear_flows(bridge, this_vif_ofport, vif_ofports)
if command == 'offline':
clear_flows(bridge, this_vif_ofport, vif_ofports)
if command == 'online':
apply_flows(bridge, this_vif_ofport, vif_ofports)
if command == 'online':
apply_flows(bridge, this_vif_ofport, vif_ofports)
# handle case where brdige is setup for VPC and VPC is enabled for distributed routing
if ovs_vpc_distributed_vr_network == 'True':
vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge])
if vlan != '0':
# We need the REAL bridge name
bridge = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'br-to-parent', bridge])
vsctl_output = pluginlib.do_cmd([pluginlib.VSCTL_PATH,
'list-ports', bridge])
vif_network_id = pluginlib.get_network_id_for_vif(this_vif)
vnet_vif_ofports = []
vnet_tunnelif_ofports = []
vnet_all_ofports = []
ports = vsctl_output.split('\n')
for port in ports:
if_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', port, 'ofport'])
if port.startswith('vif'):
# check VIF is in same network as that of plugged vif
if vif_network_id != pluginlib.get_network_id_for_vif(port):
continue
vnet_vif_ofports.append(if_ofport)
vnet_all_ofports.append(if_ofport)
if port.startswith('t'):
# check tunnel port is in same network as that of plugged vif
if vif_network_id != pluginlib.get_network_id_for_tunnel_port(port):
continue
vnet_tunnelif_ofports.append(if_ofport)
vnet_all_ofports.append(if_ofport)
if command == 'online':
for port in vnet_all_ofports:
pluginlib.clear_flooding_rules_for_port(bridge, port)
# for a packet arrived from tunnel port, flood only on VIF ports
for port in vnet_tunnelif_ofports:
pluginlib.add_flooding_rules_for_port(bridge, port, vnet_vif_ofports)
# for a packet arrived from VIF port send on all VIF and tunnel port excluding the port
# on which packet arrived
for port in vnet_vif_ofports:
vnet_all_ofports_copy = copy.copy(vnet_all_ofports)
vnet_all_ofports_copy.remove(port)
pluginlib.add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy)
#learn that MAC is reachable through the VIF port
mac = pluginlib.get_macaddress_of_vif(this_vif)
this_vif_ofport = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'get', 'Interface', this_vif, 'ofport'])
pluginlib.add_mac_lookup_table_entry(bridge, mac, this_vif_ofport)
if command == 'offline':
for port in vnet_all_ofports:
pluginlib.clear_flooding_rules_for_port(bridge, port)
vnet_all_ofports.remove(this_vif_ofport)
vnet_vif_ofports.remove(this_vif_ofport)
# for a packet arrived from tunnel port, flood only on VIF ports
for port in vnet_tunnelif_ofports:
pluginlib.add_flooding_rules_for_port(bridge, port, vnet_vif_ofports)
# for a packet from VIF port send on all VIF's and tunnel ports excluding the port on which packet arrived
for port in vnet_vif_ofports:
vnet_all_ofports_copy = copy.copy(vnet_all_ofports)
vnet_all_ofports_copy.remove(port)
pluginlib.add_flooding_rules_for_port(bridge, port, vnet_all_ofports_copy)
#un-learn that MAC is reachable through the VIF port
mac = pluginlib.get_macaddress_of_vif(this_vif)
pluginlib.delete_mac_lookup_table_entry(bridge, mac)
return
if __name__ == "__main__":
if len(sys.argv) != 3:
print "usage: %s [online|offline] vif-domid-idx" % \

View File

@ -124,6 +124,73 @@ def setup_ovs_bridge(session, args):
logging.debug("Setup_ovs_bridge completed with result:%s" % result)
return result
@echo
def setup_ovs_bridge_for_distributed_routing(session, args):
bridge = args.pop("bridge")
key = args.pop("key")
xs_nw_uuid = args.pop("xs_nw_uuid")
cs_host_id = args.pop("cs_host_id")
res = lib.check_switch()
if res != "SUCCESS":
return "FAILURE:%s" % res
logging.debug("About to manually create the bridge:%s" % bridge)
# create a bridge with the same name as the xapi network
res = lib.do_cmd([lib.VSCTL_PATH, "--", "--may-exist", "add-br", bridge])
logging.debug("Bridge has been manually created:%s" % res)
# TODO: Make sure xs-network-uuid is set into external_ids
lib.do_cmd([lib.VSCTL_PATH, "set", "Bridge", bridge,
"external_ids:xs-network-uuid=%s" % xs_nw_uuid])
# Non empty result means something went wrong
if res:
result = "FAILURE:%s" % res
else:
# Verify the bridge actually exists, with the gre_key properly set
res = lib.do_cmd([lib.VSCTL_PATH, "list", "bridge", bridge])
# Finally note in the xenapi network object that the network has
# been configured
xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list",
"bridge=%s" % bridge, "--minimal"])
lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid,
"other-config:is-ovs_vpc_distributed_vr_network=True"])
conf_hosts = lib.do_cmd([lib.XE_PATH, "network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=ovs-host-setup", "--minimal"])
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid,
"other-config:ovs-host-setup=%s" % conf_hosts])
# add a default flow rule to send broadcast and multi-cast packets to L2 flooding table
lib.add_flow(bridge, priority=1000, dl_dst='ff:ff:ff:ff:ff:ff', table=0, actions='resubmit(,2)')
lib.add_flow(bridge, priority=1000, nw_dst='224.0.0.0/24', table=0, actions='resubmit(,2)')
# add a default flow rule to send uni-cast traffic to L2 lookup table
lib.add_flow(bridge, priority=0, table=0, actions='resubmit(,1)')
# add a default rule to send unknown mac address to L2 flooding table
lib.add_flow(bridge, priority=0, table=1, actions='resubmit(,2)')
# add a default rule in L2 flood table to drop packet
lib.add_flow(bridge, priority=0, table=2, actions='drop')
# add a default rule in egress table to forward packet to L3 lookup table
lib.add_flow(bridge, priority=0, table=3, actions='resubmit(,4)')
# add a default rule in L3 lookup table to forward packet to L2 lookup table
lib.add_flow(bridge, priority=0, table=4, actions='resubmit(,1)')
# add a default rule in ingress table to drop in bound packets
lib.add_flow(bridge, priority=0, table=5, actions='drop')
result = "SUCCESS: successfully setup bridge with flow rules"
logging.debug("Setup_ovs_bridge completed with result:%s" % result)
return result
@echo
def destroy_ovs_bridge(session, args):
@ -155,6 +222,7 @@ def create_tunnel(session, args):
gre_key = args.pop("key")
src_host = args.pop("from")
dst_host = args.pop("to")
network_uuid = args.pop("cloudstack-network-id")
logging.debug("Entering create_tunnel")
@ -220,13 +288,37 @@ def create_tunnel(session, args):
# Ensure no trailing LF
if tun_ofport.endswith('\n'):
tun_ofport = tun_ofport[:-1]
# add flow entryies for dropping broadcast coming in from gre tunnel
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
# find xs network for this bridge, verify is used for ovs tunnel network
xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list",
"bridge=%s" % bridge, "--minimal"])
ovs_tunnel_network = lib.do_cmd([lib.XE_PATH,"network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=is-ovs-tun-network", "--minimal"])
ovs_vpc_distributed_vr_network = lib.do_cmd([lib.XE_PATH,"network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=is-ovs_vpc_distributed_vr_network", "--minimal"])
if ovs_tunnel_network == 'True':
# add flow entryies for dropping broadcast coming in from gre tunnel
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
nw_dst='224.0.0.0/24', actions='drop')
drop_flow_setup = True
logging.debug("Broadcast drop rules added")
drop_flow_setup = True
logging.debug("Broadcast drop rules added")
if ovs_vpc_distributed_vr_network == 'True':
# add flow rules for dropping broadcast coming in from tunnel ports
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0,
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0,
nw_dst='224.0.0.0/24', actions='drop')
# add flow rule to send the traffic from tunnel ports to L2 switching table only
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, actions='resubmit(,1)')
lib.do_cmd([lib.VSCTL_PATH, "set", "interface", name, "options:cloudstack-network-id=%s" % network_uuid])
return "SUCCESS:%s" % name
except:
logging.debug("An unexpected error occured. Rolling back")
@ -293,10 +385,28 @@ def getLabel(session, args):
return label
return False
@echo
def configure_ovs_bridge_for_network_topology(session, args):
bridge = args.pop("bridge")
json_config = args.pop("config")
this_host_id = args.pop("host-id")
return lib.configure_bridge_for_network_topology(bridge, this_host_id, json_config)
@echo
def configure_ovs_bridge_for_routing_policies(session, args):
bridge = args.pop("bridge")
json_config = args.pop("config")
return lib.configure_ovs_bridge_for_router_policies(bridge, json_config)
if __name__ == "__main__":
XenAPIPlugin.dispatch({"create_tunnel": create_tunnel,
"destroy_tunnel": destroy_tunnel,
"setup_ovs_bridge": setup_ovs_bridge,
"destroy_ovs_bridge": destroy_ovs_bridge,
"is_xcp": is_xcp,
"getLabel": getLabel})
"getLabel": getLabel,
"setup_ovs_bridge_for_distributed_routing": setup_ovs_bridge_for_distributed_routing,
"configure_ovs_bridge_for_network_topology": configure_ovs_bridge_for_network_topology,
"configure_ovs_bridge_for_routing_policies": "configure_ovs_bridge_for_routing_policies"})

View File

@ -174,6 +174,7 @@ def _build_flow_expr(**kwargs):
dl_dst = 'dl_dst' in kwargs and ",dl_dst=%s" % kwargs['dl_dst'] or ''
nw_src = 'nw_src' in kwargs and ",nw_src=%s" % kwargs['nw_src'] or ''
nw_dst = 'nw_dst' in kwargs and ",nw_dst=%s" % kwargs['nw_dst'] or ''
table = 'table' in kwargs and ",table=%s" % kwargs['table'] or ''
proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or ''
ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or ''
flow = (flow + in_port + dl_type + dl_src + dl_dst +
@ -217,3 +218,228 @@ def del_all_flows(bridge):
def del_port(bridge, port):
delPort = [VSCTL_PATH, "del-port", bridge, port]
do_cmd(delPort)
def get_network_id_for_vif(vif_name):
domain_id, device_id = vif_name[3:len(vif_name)].split(".")
dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "--minimal"])
vif_uuid = do_cmd([XE_PATH, "vif-list", "vm-uuid=%s" % dom_uuid, "device=%s" % device_id, "--minimal"])
vnet = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=other-config",
"param-key=cloudstack-network-id"])
return vnet
def get_network_id_for_tunnel_port(tunnelif_name):
vnet = do_cmd([VSCTL_PATH, "get", "interface", tunnelif_name, "options:cloudstack-network-id"])
return vnet
def clear_flooding_rules_for_port(bridge, ofport):
del_flows(bridge, in_port=ofport, table=2)
def add_flooding_rules_for_port(bridge, in_ofport, out_ofports):
action = "".join("output:%s," %ofport for ofport in out_ofports)[:-1]
add_flow(bridge, priority=1100, in_port=in_ofport, table=1, actions=action)
def get_ofport_for_vif(vif_name):
return do_cmd([VSCTL_PATH, "get", "interface", vif_name, "ofport"])
def get_macaddress_of_vif(vif_name):
domain_id, device_id = vif_name[3:len(vif_name)].split(".")
dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "--minimal"])
vif_uuid = do_cmd([XE_PATH, "vif-list", "vm-uuid=%s" % dom_uuid, "device=%s" % device_id, "--minimal"])
mac = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=MAC"])
return mac
def get_vif_name_from_macaddress(macaddress):
vif_uuid = do_cmd([XE_PATH, "vif-list", "MAC=%s" % macaddress, "--minimal"])
vif_device_id = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=device"])
vm_uuid = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=vm-uuid"])
vm_domain_id = do_cmd([XE_PATH, "vm-param-get", "uuid=%s" % vm_uuid, "param-name=dom-id"])
return "vif"+vm_domain_id+"."+vif_device_id
def add_mac_lookup_table_entry(bridge, mac_address, out_of_port):
add_flow(bridge, priority=1100, dl_dst=mac_address, table=1, actions="output:%s" % out_of_port)
def delete_mac_lookup_table_entry(bridge, mac_address):
del_flows(bridge, dl_dst=mac_address, table=1)
def add_ip_lookup_table_entry(bridge, ip, dst_tier_gateway_mac, dst_vm_mac):
action_str = "mod_dl_sr:%s" % dst_tier_gateway_mac + ",mod_dl_dst:%s" % dst_vm_mac +",resubmit(,5)"
addflow = [OFCTL_PATH, "add-flow", bridge, "table=4", "nw_dst=%s" % ip, "actions=%s" %action_str]
do_cmd(addflow)
def get_vms_on_host(vpc, host_id):
all_vms = vpc.vms
vms_on_host = []
for vm in all_vms:
if vm.hostid == host_id:
vms_on_host.append(vm)
return vms_on_host
def get_network_details(vpc, network_uuid):
tiers = vpc.tiers
for tier in tiers:
if tier.networkuuid == network_uuid:
return tier
return None
class jsonLoader(object):
def __init__(self, obj):
for k in obj:
v = obj[k]
if isinstance(v, dict):
setattr(self, k, jsonLoader(v))
elif isinstance(v, (list, tuple)):
if len(v) > 0 and isinstance(v[0], dict):
setattr(self, k, [jsonLoader(elem) for elem in v])
else:
setattr(self, k, v)
else:
setattr(self, k, v)
def __getattr__(self, val):
if val in self.__dict__:
return self.__dict__[val]
else:
return None
def __repr__(self):
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v)
in self.__dict__.iteritems()))
def __str__(self):
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v)
in self.__dict__.iteritems()))
def configure_bridge_for_network_topology(bridge, this_host_id, json_config):
vpconfig = jsonLoader(json.loads(json_config)).vpc
if vpconfig is None:
logging.debug("WARNING:Can't find VPC info in json config file")
return "FAILURE:IMPROPER_JSON_CONFG_FILE"
# get the list of Vm's in the VPC from the JSON config
this_host_vms = get_vms_on_host(vpconfig, this_host_id)
for vm in this_host_vms:
for nic in vm.nics:
mac_addr = nic.macaddress
ip = nic.ipaddress
vif_name = get_vif_name_from_macaddress(mac_addr)
of_port = get_ofport_for_vif(vif_name)
network = get_network_details(vpconfig, nic.networkuuid)
# Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet on the found OFPORT
add_mac_lookup_table_entry(bridge, mac_addr, of_port)
# Add flow rule in L3 look up table: if the destination IP = VM's IP then modify the packet
# to set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table
add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr)
# Add flow entry to send with intra tier traffic from the NIC to L2 lookup path)
addflow = [OFCTL_PATH, "add-flow", bridge, "table=0", "in_port=%s" % of_port,
"nw_dst=%s" %network.cidr, "actions=resubmit(,1)"]
do_cmd(addflow)
#add flow entry to send inter-tier traffic from the NIC to egress ACL table(to L3 lookup path)
addflow = [OFCTL_PATH, "add-flow", bridge, "table=0", "in_port=%s" % of_port,
"dl_dst=%s" %network.gatewaymac, "nw_dst=%s" %vpconfig.cidr, "actions=resubmit(,3)"]
do_cmd(addflow)
# get the list of hosts on which VPC spans from the JSON config
vpc_spanning_hosts = vpconfig.hosts
for host in vpc_spanning_hosts:
if this_host_id == host.hostid:
continue
other_host_vms = get_vms_on_host(vpconfig, host.hostid)
for vm in other_host_vms:
for nic in vm.nics:
mac_addr = nic.macaddress
ip = nic.ipaddress
network = get_network_details(vpconfig, nic.networkuuid)
gre_key = network.grekey
# generate tunnel name from tunnel naming convention
tunnel_name = "t%s-%s-%s" % (gre_key, this_host_id, host.hostid)
of_port = get_ofport_for_vif(tunnel_name)
# Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet tunnel port
add_mac_lookup_table_entry(bridge, mac_addr, of_port)
# Add flow tule in L3 look up table: if the destination IP = VM's IP then modify the packet
# set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table
add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr)
return "SUCCESS: successfully configured bridge as per the VPC topology"
def get_acl(vpcconfig, required_acl_id):
acls = vpcconfig.acls
for acl in acls:
if acl.id == required_acl_id:
return acl
return None
def configure_ovs_bridge_for_routing_policies(bridge, json_config):
vpconfig = jsonLoader(json.loads(json_config)).vpc
if vpconfig is None:
logging.debug("WARNING:Can't find VPC info in json config file")
return "FAILURE:IMPROPER_JSON_CONFG_FILE"
# First flush current egress ACL's before re-applying the ACL's
del_flows(bridge, table=3)
egress_rules_added = False
ingress_rules_added = False
tiers = vpconfig.tiers
for tier in tiers:
tier_cidr = tier.cidr
acl = get_acl(vpconfig, tier.aclid)
acl_items = acl.aclitems
for acl_item in acl_items:
number = acl_item.number
action = acl_item.action
direction = acl_item.direction
source_port_start = acl_item.sourceportstart
source_port_end = acl_item.sourceportend
protocol = acl_item.protocol
source_cidrs = acl_item.sourcecidrs
acl_priority = 1000 + number
for source_cidr in source_cidrs:
if direction is "ingress":
ingress_rules_added = True
# add flow rule to do action (allow/deny) for flows where source IP of the packet is in
# source_cidr and destination ip is in tier_cidr
port = source_port_start
while (port < source_port_end):
if action is "deny":
add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port,
nw_proto=protocol, actions='drop')
if action is "allow":
add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port,
nw_proto=protocol, actions='resubmit(,1)')
port = port + 1
elif direction in "egress":
egress_rules_added = True
# add flow rule to do action (allow/deny) for flows where destination IP of the packet is in
# source_cidr and source ip is in tier_cidr
port = source_port_start
while (port < source_port_end):
if action is "deny":
add_flow(bridge, priority= acl_priority, table=5, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port,
nw_proto=protocol, actions='drop')
if action is "allow":
add_flow(bridge, priority= acl_priority, table=5, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port,
nw_proto=protocol, actions='resubmit(,1)')
port = port + 1
if egress_rules_added is False:
# add a default rule in egress table to forward packet to L3 lookup table
add_flow(bridge, priority=0, table=3, actions='resubmit(,4)')
if ingress_rules_added is False:
# add a default rule in egress table drop packets
add_flow(bridge, priority=0, table=5, actions='drop')

View File

@ -27,6 +27,7 @@ import os
import sys
import subprocess
import time
import simplejson as json
from optparse import OptionParser, OptionGroup, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
from time import localtime as _localtime, asctime as _asctime
@ -72,6 +73,58 @@ def setup_ovs_bridge(bridge, key, cs_host_id):
logging.debug("Setup_ovs_bridge completed with result:%s" % result)
return result
@echo
def setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id):
res = lib.check_switch()
if res != "SUCCESS":
return "FAILURE:%s" % res
logging.debug("About to manually create the bridge:%s" % bridge)
res = lib.do_cmd([lib.VSCTL_PATH, "--", "--may-exist", "add-br", bridge])
logging.debug("Bridge has been manually created:%s" % res)
# Non empty result means something went wrong
if res:
result = "FAILURE:%s" % res
else:
# Verify the bridge actually exists
res = lib.do_cmd([lib.VSCTL_PATH, "list", "bridge", bridge])
res = lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs_vpc_distributed_vr_network=True"])
conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get","bridge", bridge,"other:ovs-host-setup"])
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge,
"other_config:ovs-host-setup=%s" % conf_hosts])
# add a default flow rule to send broadcast and multi-cast packets to L2 flooding table
lib.add_flow(bridge, priority=1000, dl_dst='ff:ff:ff:ff:ff:ff', table=0, actions='resubmit(,2)')
lib.add_flow(bridge, priority=1000, nw_dst='224.0.0.0/24', table=0, actions='resubmit(,2)')
# add a default flow rule to send uni-cast traffic to L2 lookup table
lib.add_flow(bridge, priority=0, table=0, actions='resubmit(,1)')
# add a default rule to send unknown mac address to L2 flooding table
lib.add_flow(bridge, priority=0, table=1, actions='resubmit(,2)')
# add a default rule in L2 flood table to drop packet
lib.add_flow(bridge, priority=0, table=2, actions='drop')
# add a default rule in egress table to forward packet to L3 lookup table
lib.add_flow(bridge, priority=0, table=3, actions='resubmit(,4)')
# add a default rule in L3 lookup table to forward packet to L2 lookup table
lib.add_flow(bridge, priority=0, table=4, actions='resubmit(,1)')
# add a default rule in ingress table to drop in bound packets
lib.add_flow(bridge, priority=0, table=5, actions='drop')
result = "SUCCESS: successfully setup bridge with flow rules"
logging.debug("Setup_ovs_bridge completed with result:%s" % result)
return result
def destroy_ovs_bridge(bridge):
res = lib.check_switch()
@ -163,12 +216,30 @@ def create_tunnel(bridge, remote_ip, key, src_host, dst_host):
# Ensure no trailing LF
if tun_ofport.endswith('\n'):
tun_ofport = tun_ofport[:-1]
# add flow entryies for dropping broadcast coming in from gre tunnel
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
ovs_tunnel_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other_config:is-ovs-tun-network"])
ovs_vpc_distributed_vr_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge,
"other_config:is-ovs_vpc_distributed_vr_network"])
if ovs_tunnel_network == 'True':
# add flow entryies for dropping broadcast coming in from gre tunnel
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
nw_dst='224.0.0.0/24', actions='drop')
drop_flow_setup = True
drop_flow_setup = True
if ovs_vpc_distributed_vr_network == 'True':
# add flow rules for dropping broadcast coming in from tunnel ports
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0,
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0,
nw_dst='224.0.0.0/24', actions='drop')
# add flow rule to send the traffic from tunnel ports to L2 switching table only
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, actions='resubmit(,1)')
lib.do_cmd([lib.VSCTL_PATH, "set", "interface", name, "options:cloudstack-network-id=%s" % network_uuid])
logging.debug("Broadcast drop rules added")
# return "SUCCESS:%s" % name
return 'true'
@ -210,6 +281,7 @@ if __name__ == '__main__':
parser.add_option("--src_host", dest="src_host")
parser.add_option("--dst_host", dest="dst_host")
parser.add_option("--iface_name", dest="iface_name")
parser.ad_option("--config", dest="config")
(option, args) = parser.parse_args()
if len(args) == 0:
logging.debug("No command to execute")
@ -223,6 +295,12 @@ if __name__ == '__main__':
create_tunnel(option.bridge, option.remote_ip, option.key, option.src_host, option.dst_host)
elif cmd == "destroy_tunnel":
destroy_tunnel(option.bridge, option.iface_name)
elif cmd == "setup_ovs_bridge_for_distributed_routing":
setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id)
elif cmd == "configure_ovs_bridge_for_network_topology":
configure_bridge_for_network_topology(brdige, cs_host_id, config)
elif cmd == "configure_ovs_bridge_for_routing_policies":
configure_ovs_bridge_for_routing_policies(bridge, config)
else:
logging.debug("Unknown command: " + cmd)
sys.exit(1)

View File

@ -1901,6 +1901,7 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId()));
response.setEgressDefaultPolicy(offering.getEgressDefaultPolicy());
response.setConcurrentConnections(offering.getConcurrentConnections());
response.setSupportsStrechedL2Subnet(offering.getSupportsStrechedL2());
Long so = null;
if (offering.getServiceOfferingId() != null) {
so = offering.getServiceOfferingId();
@ -2765,6 +2766,8 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setDisplayText(offering.getDisplayText());
response.setIsDefault(offering.isDefault());
response.setState(offering.getState().name());
response.setSupportsDistributedRouter(offering.supportsDistributedRouter());
response.setSupportsRegionLevelVpc(offering.offersRegionLevelVPC());
Map<Service, Set<Provider>> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId());
List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();
@ -2807,6 +2810,8 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setRestartRequired(vpc.isRestartRequired());
response.setNetworkDomain(vpc.getNetworkDomain());
response.setForDisplay(vpc.isDisplay());
response.setUsesDistributedRouter(vpc.usesDistributedRouter());
response.setRegionLevelVpc(vpc.isRegionLevelVpc());
Map<Service, Set<Provider>> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId());
List<ServiceResponse> serviceResponses = new ArrayList<ServiceResponse>();

View File

@ -24,13 +24,13 @@ import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.StoragePoolJoinVO;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityManager;
import com.cloud.storage.ScopeType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StorageStats;
@ -103,6 +103,7 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Lo
poolResponse.setClusterId(pool.getClusterUuid());
poolResponse.setClusterName(pool.getClusterName());
poolResponse.setTags(pool.getTag());
poolResponse.setOverProvisionFactor(Double.toString(CapacityManager.StorageOverprovisioningFactor.valueIn(pool.getId())));
// set async job
if (pool.getJobId() != null) {
@ -156,6 +157,7 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Lo
poolResponse.setDiskSizeTotal(pool.getCapacityBytes());
poolResponse.setDiskSizeAllocated(allocatedSize);
poolResponse.setCapacityIops(pool.getCapacityIops());
poolResponse.setOverProvisionFactor(Double.toString(CapacityManager.StorageOverprovisioningFactor.valueIn(pool.getId())));
// TODO: StatsCollector does not persist data
StorageStats stats = ApiDBUtils.getStoragePoolStatistics(pool.getId());

View File

@ -67,7 +67,7 @@ public class StorageCapacityListener implements Listener {
StartupStorageCommand ssCmd = (StartupStorageCommand)startup;
if (ssCmd.getResourceType() == Storage.StorageResourceType.STORAGE_HOST) {
BigDecimal overProvFactor = _storageMgr.getStorageOverProvisioningFactor(server.getDataCenterId());
BigDecimal overProvFactor = BigDecimal.valueOf(CapacityManager.StorageOverprovisioningFactor.value());
CapacityVO capacity =
new CapacityVO(server.getId(), server.getDataCenterId(), server.getPodId(), server.getClusterId(), 0L, (overProvFactor.multiply(new BigDecimal(
server.getTotalSize()))).longValue(), Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED);

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.configuration;
import com.cloud.network.element.NetworkElement;
import java.net.URI;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -3814,10 +3815,21 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
validateStaticNatServiceCapablities(staticNatServiceCapabilityMap);
// validate the 'Connectivity' service capabilities specified in the network offering, if 'Connectivity' service
// is in the supported services of network offering
Map<Capability, String> connectivityServiceCapabilityMap = cmd.getServiceCapabilities(Service.Connectivity);
if (!serviceProviderMap.containsKey(Service.Connectivity) &&
(connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty())) {
throw new InvalidParameterValueException("Capabilities for 'Connectivity' service can be specified " +
"only when Connectivity service is enabled for network offering.");
}
validateConnectivityServiceCapablities(serviceProviderMap.get(Service.Connectivity), connectivityServiceCapabilityMap);
Map<Service, Map<Capability, String>> serviceCapabilityMap = new HashMap<Service, Map<Capability, String>>();
serviceCapabilityMap.put(Service.Lb, lbServiceCapabilityMap);
serviceCapabilityMap.put(Service.SourceNat, sourceNatServiceCapabilityMap);
serviceCapabilityMap.put(Service.StaticNat, staticNatServiceCapabilityMap);
serviceCapabilityMap.put(Service.Connectivity, connectivityServiceCapabilityMap);
// if Firewall service is missing, add Firewall service/provider
// combination
@ -3952,6 +3964,36 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
}
void validateConnectivityServiceCapablities(Set<Provider> providers, Map<Capability, String> connectivityServiceCapabilityMap) {
if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) {
for (Capability capability: connectivityServiceCapabilityMap.keySet()) {
if (capability == Capability.StretchedL2Subnet) {
String value = connectivityServiceCapabilityMap.get(capability).toLowerCase();
if (!(value.contains("true") ^ value.contains("false"))) {
throw new InvalidParameterValueException("Invalid value (" + value + ") for " + capability +
" should be true/false");
}
} else {
throw new InvalidParameterValueException("Capability " + capability.getName() + " can not be "
+ " specified with connectivity service.");
}
}
}
if (providers != null && !providers.isEmpty()) {
for (Provider provider: providers) {
NetworkElement element = _networkModel.getElementImplementingProvider(provider.getName());
Map<Service, Map<Capability, String>> capabilities = element.getCapabilities();
if (capabilities != null && !capabilities.isEmpty()) {
Map<Capability, String> connectivityCapabilities = capabilities.get(Service.Connectivity);
if (connectivityCapabilities == null || (connectivityCapabilities != null && !connectivityCapabilities.keySet().contains(Capability.StretchedL2Subnet))) {
throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support "
+ Capability.StretchedL2Subnet.getName());
}
}
}
}
}
@Override
@DB
public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability,
@ -4012,6 +4054,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
boolean inline = false;
boolean publicLb = false;
boolean internalLb = false;
boolean strechedL2Subnet = false;
if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) {
Map<Capability, String> lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb);
@ -4079,6 +4123,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
}
}
Map<Capability, String> connectivityServiceCapabilityMap = serviceCapabilityMap.get(Service.Connectivity);
if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) {
String value = connectivityServiceCapabilityMap.get(Capability.StretchedL2Subnet);
if ("true".equalsIgnoreCase(value)) {
strechedL2Subnet = true;
}
}
}
if (serviceProviderMap != null && serviceProviderMap.containsKey(Service.Lb) && !internalLb && !publicLb) {
@ -4088,7 +4140,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
final NetworkOfferingVO offeringFinal = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability,
tags, type, conserveMode, dedicatedLb, sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp, publicLb,
internalLb, egressDefaultPolicy);
internalLb, egressDefaultPolicy, strechedL2Subnet);
if (serviceOfferingId != null) {
offeringFinal.setServiceOfferingId(serviceOfferingId);

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.hypervisor;
import com.cloud.network.dao.NetworkVO;
import java.util.List;
import java.util.Map;
@ -41,6 +42,7 @@ import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
@ -52,6 +54,8 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
@Inject
NicDao _nicDao;
@Inject
NetworkDao _networkDao;
@Inject
VMInstanceDao _virtualMachineDao;
@Inject
UserVmDetailsDao _userVmDetailsDao;
@ -87,6 +91,9 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
to.setName(profile.getName());
to.setSecurityGroupEnabled(profile.isSecurityGroupEnabled());
NetworkVO network = _networkDao.findById(profile.getNetworkId());
to.setNetworkUuid(network.getUuid());
// Workaround to make sure the TO has the UUID we need for Niciri integration
NicVO nicVO = _nicDao.findById(profile.getId());
to.setUuid(nicVO.getUuid());

View File

@ -113,10 +113,12 @@ import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.OvsProviderDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
import com.cloud.network.dao.PhysicalNetworkVO;
import com.cloud.network.dao.LoadBalancerVMMapVO;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.OvsProviderVO;
import com.cloud.network.element.VirtualRouterElement;
@ -307,6 +309,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
IpAddressManager _ipAddrMgr;
@Inject
EntityManager _entityMgr;
@Inject
LoadBalancerVMMapDao _lbVmMapDao;
int _cidrLimit;
boolean _allowSubdomainNetworkAccess;
@ -806,7 +810,15 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
s_logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId());
throw new InvalidParameterValueException("Can' remove the ip " + secondaryIp + "is associate with static NAT rule public IP address id " + publicIpVO.getId());
}
} else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
List<LoadBalancerVMMapVO> lbVmMap = _lbVmMapDao.listByInstanceIp(secondaryIp);
if (lbVmMap != null && lbVmMap.size() != 0) {
s_logger.debug("VM nic IP " + secondaryIp + " is mapped to load balancing rule");
throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is mapped to load balancing rule");
}
} else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(secIpVO.getNetworkId(), secIpVO.getIp4Address());
if (ip != null) {
Transaction.execute(new TransactionCallbackNoReturn() {
@ -3819,12 +3831,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId);
DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId());
if (dvo.getNetworkType() == NetworkType.Basic) {
Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider");
if (provider == null) {
Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider");
if (provider == null) {
// baremetal is not loaded
return null;
}
}
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalDhcpProvider", null, null);
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null);

View File

@ -1414,7 +1414,7 @@ public class AutoScaleManagerImpl<Type> extends ManagerBase implements AutoScale
}
}
lstVmId.add(new Long(vmId));
return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId);
return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId, null);
}

View File

@ -107,6 +107,10 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
@Override
public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
if (_networkModel.areServicesSupportedByNetworkOffering(offering.getId(), Network.Service.Connectivity)) {
return null;
}
NetworkVO config = (NetworkVO)super.design(offering, plan, userSpecified, owner);
if (config == null) {
return null;
@ -123,6 +127,10 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
throws InsufficientVirtualNetworkCapcityException {
assert (config.getState() == State.Implementing) : "Why are we implementing " + config;
if (_networkModel.areServicesSupportedInNetwork(config.getId(), Network.Service.Connectivity)) {
return null;
}
if (!_networkModel.networkIsConfiguredForExternalNetworking(config.getDataCenterId(), config.getId())) {
return super.implement(config, offering, dest, context);
}

View File

@ -30,6 +30,7 @@ import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import com.cloud.vm.dao.NicSecondaryIpDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBHealthCheckPolicyCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBStickinessPolicyCmd;
@ -258,6 +259,9 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
@Inject
LoadBalancerCertMapDao _lbCertMapDao;
@Inject
NicSecondaryIpDao _nicSecondaryIpDao;
// Will return a string. For LB Stickiness this will be a json, for
// autoscale this will be "," separated values
@Override
@ -923,7 +927,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true)
public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds) {
public boolean assignToLoadBalancer(long loadBalancerId, List<Long> instanceIds, Map<Long, List<String>> vmIdIpMap) {
CallContext ctx = CallContext.current();
Account caller = ctx.getCallingAccount();
@ -932,22 +936,68 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found.");
}
if (instanceIds == null && vmIdIpMap == null) {
throw new InvalidParameterValueException("Both instanceids and vmidipmap can't be null");
}
// instanceIds and vmIdipmap is passed
if (instanceIds != null && vmIdIpMap != null) {
for(long instanceId: instanceIds) {
if (!vmIdIpMap.containsKey(instanceId)) {
vmIdIpMap.put(instanceId, null);
}
}
}
//only instanceids list passed
if (instanceIds != null && vmIdIpMap == null){
vmIdIpMap = new HashMap<Long, List<String>>();
for (long instanceId: instanceIds){
vmIdIpMap.put(instanceId, null);
}
}
List<LoadBalancerVMMapVO> mappedInstances = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false);
Set<Long> mappedInstanceIds = new HashSet<Long>();
for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId()));
}
final List<UserVm> vmsToAdd = new ArrayList<UserVm>();
Map<Long, List<String>> existingVmIdIps = new HashMap<Long, List<String>>();
// now get the ips of vm and add it to map
for (LoadBalancerVMMapVO mappedInstance : mappedInstances) {
if (instanceIds == null || instanceIds.isEmpty()) {
s_logger.warn("List of vms to assign to the lb, is empty");
return false;
List<String> ipsList = null;
if (existingVmIdIps.containsKey(mappedInstance.getInstanceId())) {
ipsList = existingVmIdIps.get(mappedInstance.getInstanceId());
} else {
ipsList = new ArrayList<String>();
}
ipsList.add(mappedInstance.getInstanceIp());
existingVmIdIps.put(mappedInstance.getInstanceId(), ipsList);
}
for (Long instanceId : instanceIds) {
if (mappedInstanceIds.contains(instanceId)) {
throw new InvalidParameterValueException("VM " + instanceId + " is already mapped to load balancer.");
final List<UserVm> vmsToAdd = new ArrayList<UserVm>();
// check for conflict
Set<Long> passedInstanceIds = vmIdIpMap.keySet();
for (Long instanceId : passedInstanceIds) {
if (existingVmIdIps.containsKey(instanceId)) {
// now check for ip address
List<String> mappedIps = existingVmIdIps.get(instanceId);
List<String> newIps = vmIdIpMap.get(instanceId);
if (newIps != null) {
for (String newIp: newIps) {
if (mappedIps.contains(newIp)) {
throw new InvalidParameterValueException("VM " + instanceId + " with " + newIp +" is already mapped to load balancer.");
}
}
}
}
UserVm vm = _vmDao.findById(instanceId);
@ -985,18 +1035,43 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
throw ex;
}
String priIp = nicInSameNetwork.getIp4Address();
List<String> vmIpsList = vmIdIpMap.get(instanceId);
String vmLbIp = null;
if (vmIpsList == null) {
vmIpsList = new ArrayList<String>();
vmIpsList.add(priIp);
vmIdIpMap.put(instanceId, vmIpsList);
} else {
//check if the ips belongs to nic secondary ip
for (String ip: vmIpsList) {
if(_nicSecondaryIpDao.findByIp4AddressAndNicId(ip,nicInSameNetwork.getId()) == null) {
throw new InvalidParameterValueException("VM ip specified " + ip + " is not belongs to nic in network " + nicInSameNetwork.getNetworkId());
}
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding " + vm + " to the load balancer pool");
}
vmsToAdd.add(vm);
}
final Set<Long> vmIds = vmIdIpMap.keySet();
final Map<Long, List<String>> newMap = vmIdIpMap;
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
for (UserVm vm : vmsToAdd) {
LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vm.getId(), false);
for (Long vmId : vmIds) {
final List<String> lbVmIps = newMap.get(vmId);
for (String vmIp: lbVmIps) {
LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vmId, vmIp, false);
map = _lb2VmMapDao.persist(map);
}
}
}
});
@ -1020,8 +1095,8 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
for (UserVm vm : vmsToAdd) {
vmInstanceIds.add(vm.getId());
for (Long vmId : vmIds) {
vmInstanceIds.add(vmId);
}
}
});
@ -1875,7 +1950,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) {
UserVm vm = _vmDao.findById(lbVmMap.getInstanceId());
Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(lb.getNetworkId(), vm.getId());
dstIp = nic.getIp4Address();
dstIp = lbVmMap.getInstanceIp() == null ? nic.getIp4Address(): lbVmMap.getInstanceIp();
LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, lbVmMap.isRevoke());
dstList.add(lbDst);
}

View File

@ -55,6 +55,7 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.cloudstack.alert.AlertService.AlertType;
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
@ -73,6 +74,8 @@ import com.cloud.agent.api.NetworkUsageAnswer;
import com.cloud.agent.api.NetworkUsageCommand;
import com.cloud.agent.api.PvlanSetupCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.routing.GetRouterAlertsCommand;
import com.cloud.agent.api.GetRouterAlertsAnswer;
import com.cloud.agent.api.check.CheckSshAnswer;
import com.cloud.agent.api.check.CheckSshCommand;
import com.cloud.agent.api.routing.AggregationControlCommand;
@ -179,6 +182,7 @@ import com.cloud.network.dao.MonitoringServiceDao;
import com.cloud.network.dao.MonitoringServiceVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.OpRouterMonitorServiceDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.Site2SiteCustomerGatewayDao;
@ -188,6 +192,7 @@ import com.cloud.network.dao.Site2SiteVpnGatewayDao;
import com.cloud.network.dao.UserIpv6AddressDao;
import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.dao.OpRouterMonitorServiceVO;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy;
@ -394,6 +399,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
AsyncJobManager _asyncMgr;
@Inject
protected ApiAsyncJobDispatcher _asyncDispatcher;
@Inject
OpRouterMonitorServiceDao _opRouterMonitorServiceDao;
int _routerRamSize;
int _routerCpuMHz;
@ -1348,6 +1355,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
updateSite2SiteVpnConnectionState(routers);
getRouterAlerts();
final List<NetworkVO> networks = _networkDao.listRedundantNetworks();
s_logger.debug("Found " + networks.size() + " networks to update RvR status. ");
for (final NetworkVO network : networks) {
@ -1362,6 +1371,64 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
}
}
private void getRouterAlerts() {
try{
List<DomainRouterVO> routersInIsolatedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Isolated, mgmtSrvrId);
List<DomainRouterVO> routersInSharedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Shared, mgmtSrvrId);
List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
routers.addAll(routersInIsolatedNetwork);
routers.addAll(routersInSharedNetwork);
s_logger.debug("Found " + routers.size() + " running routers. ");
for (final DomainRouterVO router : routers) {
if (router.getVpcId() != null) {
continue;
}
String privateIP = router.getPrivateIpAddress();
if (privateIP != null) {
OpRouterMonitorServiceVO opRouterMonitorServiceVO = _opRouterMonitorServiceDao.findById(router.getId());
GetRouterAlertsCommand command = null;
if (opRouterMonitorServiceVO == null) {
command = new GetRouterAlertsCommand(null);
} else {
command = new GetRouterAlertsCommand(opRouterMonitorServiceVO.getLastAlertTimestamp());
}
command.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress());
command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName());
GetRouterAlertsAnswer answer = null;
try {
answer = (GetRouterAlertsAnswer) _agentMgr.easySend(router.getHostId(), command);
String alerts[] = answer.getAlerts();
if (alerts != null ) {
for (String alert: alerts) {
_alertMgr.sendAlert(AlertType.ALERT_TYPE_DOMAIN_ROUTER, router.getDataCenterId(), router.getPodIdToDeployIn(), "Monitoring Service on VR " + router.getInstanceName(), alert);
}
String lastAlertTimeStamp = answer.getTimeStamp();
if (opRouterMonitorServiceVO == null) {
opRouterMonitorServiceVO = new OpRouterMonitorServiceVO(router.getId(), router.getHostName(), lastAlertTimeStamp);
_opRouterMonitorServiceDao.persist(opRouterMonitorServiceVO);
} else {
opRouterMonitorServiceVO.setLastAlertTimestamp(lastAlertTimeStamp);
_opRouterMonitorServiceDao.update(opRouterMonitorServiceVO.getId(), opRouterMonitorServiceVO);
}
}
} catch (Exception e) {
s_logger.warn("Error while collecting alerts from router: " + router.getInstanceName() + " from host: " + router.getHostId(), e);
continue;
}
}
}
} catch (Exception e) {
s_logger.warn("Error while collecting alerts from router", e);
}
}
private final static int DEFAULT_PRIORITY = 100;
private final static int DEFAULT_DELTA = 2;

View File

@ -23,6 +23,8 @@ import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.log4j.Logger;
import com.cloud.configuration.ConfigurationManager;
@ -82,6 +84,8 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana
EntityManager _entityMgr;
@Inject
VpcService _vpcSvc;
@Inject
MessageBus _messageBus;
@Override
public NetworkACL createNetworkACL(String name, String description, long vpcId, Boolean forDisplay) {
@ -210,7 +214,13 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana
if (_networkDao.update(network.getId(), network)) {
s_logger.debug("Updated network: " + network.getId() + " with Network ACL Id: " + acl.getId() + ", Applying ACL items");
//Apply ACL to network
return applyACLToNetwork(network.getId());
Boolean result = applyACLToNetwork(network.getId());
if (result) {
// public message on message bus, so that network elements implementing distributed routing capability
// can act on the event
_messageBus.publish(_name, "Network_ACL_Replaced", PublishScope.LOCAL, network);
}
return result;
}
return false;
}

View File

@ -16,10 +16,14 @@
// under the License.
package com.cloud.network.vpc;
import com.cloud.network.element.NetworkElement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -202,7 +206,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker"));
private List<VpcProvider> vpcElements = null;
private final List<Service> nonSupportedServices = Arrays.asList(Service.SecurityGroup, Service.Firewall);
private final List<Provider> supportedProviders = Arrays.asList(Provider.VPCVirtualRouter, Provider.NiciraNvp, Provider.InternalLbVm, Provider.Netscaler, Provider.JuniperContrailVpcRouter);
private final List<Provider> supportedProviders = Arrays.asList(Provider.VPCVirtualRouter,
Provider.NiciraNvp, Provider.InternalLbVm, Provider.Netscaler, Provider.JuniperContrailVpcRouter,
Provider.Ovs);
int _cleanupInterval;
int _maxNetworks;
@ -215,44 +221,49 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) {
s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName);
Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
Set<Provider> defaultProviders = new HashSet<Provider>();
defaultProviders.add(Provider.VPCVirtualRouter);
for (Service svc : getSupportedServices()) {
if (svc == Service.Lb) {
Set<Provider> lbProviders = new HashSet<Provider>();
lbProviders.add(Provider.VPCVirtualRouter);
lbProviders.add(Provider.InternalLbVm);
svcProviderMap.put(svc, lbProviders);
} else {
svcProviderMap.put(svc, defaultProviders);
if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) {
s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName);
Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
Set<Provider> defaultProviders = new HashSet<Provider>();
defaultProviders.add(Provider.VPCVirtualRouter);
for (Service svc : getSupportedServices()) {
if (svc == Service.Lb) {
Set<Provider> lbProviders = new HashSet<Provider>();
lbProviders.add(Provider.VPCVirtualRouter);
lbProviders.add(Provider.InternalLbVm);
svcProviderMap.put(svc, lbProviders);
} else {
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName,
svcProviderMap, true, State.Enabled, null, false, false);
}
}
createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled, null);
}
//configure default vpc offering with Netscaler as LB Provider
//configure default vpc offering with Netscaler as LB Provider
if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCNSOfferingName) == null) {
s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName);
Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
Set<Provider> defaultProviders = new HashSet<Provider>();
defaultProviders.add(Provider.VPCVirtualRouter);
for (Service svc : getSupportedServices()) {
if (svc == Service.Lb) {
Set<Provider> lbProviders = new HashSet<Provider>();
lbProviders.add(Provider.Netscaler);
lbProviders.add(Provider.InternalLbVm);
svcProviderMap.put(svc, lbProviders);
} else {
svcProviderMap.put(svc, defaultProviders);
s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName);
Map<Service, Set<Provider>> svcProviderMap = new HashMap<Service, Set<Provider>>();
Set<Provider> defaultProviders = new HashSet<Provider>();
defaultProviders.add(Provider.VPCVirtualRouter);
for (Service svc : getSupportedServices()) {
if (svc == Service.Lb) {
Set<Provider> lbProviders = new HashSet<Provider>();
lbProviders.add(Provider.Netscaler);
lbProviders.add(Provider.InternalLbVm);
svcProviderMap.put(svc, lbProviders);
} else {
svcProviderMap.put(svc, defaultProviders);
}
}
createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName,
svcProviderMap, false, State.Enabled, null, false, false);
}
}
createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null);
}
}
});
Map<String, String> configs = _configDao.getConfiguration(params);
@ -299,8 +310,10 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
@Override
@ActionEvent(eventType = EventTypes.EVENT_VPC_OFFERING_CREATE, eventDescription = "creating vpc offering", create = true)
public VpcOffering createVpcOffering(String name, String displayText, List<String> supportedServices, Map<String, List<String>> serviceProviders,
Long serviceOfferingId) {
public VpcOffering createVpcOffering(String name, String displayText, List<String> supportedServices,
Map<String, List<String>> serviceProviders,
Map serviceCapabilitystList,
Long serviceOfferingId) {
Map<Network.Service, Set<Network.Provider>> svcProviderMap = new HashMap<Network.Service, Set<Network.Provider>>();
Set<Network.Provider> defaultProviders = new HashSet<Network.Provider>();
defaultProviders.add(Provider.VPCVirtualRouter);
@ -372,45 +385,201 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
}
VpcOffering offering = createVpcOffering(name, displayText, svcProviderMap, false, null, serviceOfferingId);
validateConnectivtyServiceCapablitlies(svcProviderMap.get(Service.Connectivity), serviceCapabilitystList);
boolean supportsDistributedRouter = isVpcOfferingSupportsDistributedRouter(serviceCapabilitystList);
boolean offersRegionLevelVPC = isVpcOfferingForRegionLevelVpc(serviceCapabilitystList);
VpcOffering offering = createVpcOffering(name, displayText, svcProviderMap, false, null,
serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC);
CallContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name);
return offering;
}
@DB
protected VpcOffering createVpcOffering(final String name, final String displayText, final Map<Network.Service, Set<Network.Provider>> svcProviderMap,
final boolean isDefault, final State state, final Long serviceOfferingId) {
protected VpcOffering createVpcOffering(final String name, final String displayText,
final Map<Network.Service, Set<Network.Provider>> svcProviderMap,
final boolean isDefault, final State state, final Long serviceOfferingId,
final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC) {
return Transaction.execute(new TransactionCallback<VpcOffering>() {
@Override
public VpcOffering doInTransaction(TransactionStatus status) {
// create vpc offering object
VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId);
// create vpc offering object
VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId,
supportsDistributedRouter, offersRegionLevelVPC);
if (state != null) {
offering.setState(state);
}
s_logger.debug("Adding vpc offering " + offering);
offering = _vpcOffDao.persist(offering);
// populate services and providers
if (svcProviderMap != null) {
for (Network.Service service : svcProviderMap.keySet()) {
Set<Provider> providers = svcProviderMap.get(service);
if (providers != null && !providers.isEmpty()) {
for (Network.Provider provider : providers) {
VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
_vpcOffSvcMapDao.persist(offService);
s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName());
if (state != null) {
offering.setState(state);
}
s_logger.debug("Adding vpc offering " + offering);
offering = _vpcOffDao.persist(offering);
// populate services and providers
if (svcProviderMap != null) {
for (Network.Service service : svcProviderMap.keySet()) {
Set<Provider> providers = svcProviderMap.get(service);
if (providers != null && !providers.isEmpty()) {
for (Network.Provider provider : providers) {
VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider);
_vpcOffSvcMapDao.persist(offService);
s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName());
}
} else {
throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName());
}
}
}
return offering;
}
});
}
private void validateConnectivtyServiceCapablitlies(Set<Provider> providers, Map serviceCapabilitystList) {
if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) {
Collection serviceCapabilityCollection = serviceCapabilitystList.values();
Iterator iter = serviceCapabilityCollection.iterator();
Map<Network.Capability, String> capabilityMap = null;
boolean distributedRouterCapabilitySpecified = false;
boolean regionLevelVpcCapabilitySpecified = false;
while (iter.hasNext()) {
HashMap<String, String> svcCapabilityMap = (HashMap<String, String>)iter.next();
Network.Capability capability = null;
String svc = svcCapabilityMap.get("service");
String capabilityName = svcCapabilityMap.get("capabilitytype");
String capabilityValue = svcCapabilityMap.get("capabilityvalue");
if (capabilityName != null) {
capability = Network.Capability.getCapability(capabilityName);
}
if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) {
throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue);
}
if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) {
throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only 'Connectivity'" +
" service capabilities can be specified");
}
if (!capabilityName.equalsIgnoreCase("DistributedRouter") && !capabilityName.equalsIgnoreCase("RegionLevelVpc")) {
throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified." +
" Only 'DistributedRouter'/'RegionLevelVpc' capability can be specified.");
}
if (capabilityName.equalsIgnoreCase("DistributedRouter")) {
distributedRouterCapabilitySpecified = true;
}
if (capabilityName.equalsIgnoreCase("RegionLevelVpc")) {
regionLevelVpcCapabilitySpecified = true;
}
if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) {
throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified.");
}
}
if (providers != null && !providers.isEmpty()) {
for (Provider provider: providers) {
NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName());
Map<Service, Map<Network.Capability, String>> capabilities = element.getCapabilities();
if (capabilities != null && !capabilities.isEmpty()) {
Map<Network.Capability, String> connectivityCapabilities = capabilities.get(Service.Connectivity);
if (regionLevelVpcCapabilitySpecified) {
if (connectivityCapabilities == null || (connectivityCapabilities != null &&
!connectivityCapabilities.keySet().contains(Network.Capability.RegionLevelVpc))) {
throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support "
+ Network.Capability.RegionLevelVpc.getName() + " capability.");
}
}
if (distributedRouterCapabilitySpecified) {
if (connectivityCapabilities == null || (connectivityCapabilities != null &&
!connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) {
throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support "
+ Network.Capability.DistributedRouter.getName() + " capability.");
}
}
}
} else {
throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName());
}
}
}
return offering;
}
});
private boolean isVpcOfferingForRegionLevelVpc(Map serviceCapabilitystList) {
boolean offersRegionLevelVPC = false;
if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) {
Collection serviceCapabilityCollection = serviceCapabilitystList.values();
Iterator iter = serviceCapabilityCollection.iterator();
Map<Network.Capability, String> capabilityMap = null;
while (iter.hasNext()) {
HashMap<String, String> svcCapabilityMap = (HashMap<String, String>)iter.next();
Network.Capability capability = null;
String svc = svcCapabilityMap.get("service");
String capabilityName = svcCapabilityMap.get("capabilitytype");
String capabilityValue = svcCapabilityMap.get("capabilityvalue");
if (capabilityName != null) {
capability = Network.Capability.getCapability(capabilityName);
}
if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) {
throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue);
}
if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) {
throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified");
}
if (!capabilityName.equalsIgnoreCase("RegionLevelVpc")) {
continue;
}
if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) {
throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified.");
}
offersRegionLevelVPC = capabilityValue.equalsIgnoreCase("true");
}
}
return offersRegionLevelVPC;
}
private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) {
boolean supportsDistributedRouter = false;
if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) {
Collection serviceCapabilityCollection = serviceCapabilitystList.values();
Iterator iter = serviceCapabilityCollection.iterator();
Map<Network.Capability, String> capabilityMap = null;
while (iter.hasNext()) {
HashMap<String, String> svcCapabilityMap = (HashMap<String, String>)iter.next();
Network.Capability capability = null;
String svc = svcCapabilityMap.get("service");
String capabilityName = svcCapabilityMap.get("capabilitytype");
String capabilityValue = svcCapabilityMap.get("capabilityvalue");
if (capabilityName != null) {
capability = Network.Capability.getCapability(capabilityName);
}
if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) {
throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue);
}
if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) {
throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified");
}
if (!capabilityName.equalsIgnoreCase("DistributedRouter")) {
continue;
}
if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) {
throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified.");
}
supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true");
}
}
return supportsDistributedRouter;
}
@Override
@ -607,6 +776,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
throw ex;
}
boolean isRegionLevelVpcOff = vpcOff.offersRegionLevelVPC();
if (isRegionLevelVpcOff && networkDomain == null) {
throw new InvalidParameterValueException("Network domain must be specified for region level VPC");
}
//Validate zone
DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
if (zone == null) {
@ -630,12 +804,14 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
}
return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc);
boolean useDistributedRouter = vpcOff.supportsDistributedRouter();
return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc,
useDistributedRouter, isRegionLevelVpcOff);
}
@DB
protected Vpc createVpc(final long zoneId, final long vpcOffId, final Account vpcOwner, final String vpcName, final String displayText, final String cidr,
final String networkDomain, final Boolean displayVpc) {
final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter, final boolean regionLevelVpc) {
//Validate CIDR
if (!NetUtils.isValidCIDR(cidr)) {
@ -657,7 +833,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
return Transaction.execute(new TransactionCallback<VpcVO>() {
@Override
public VpcVO doInTransaction(TransactionStatus status) {
VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId, cidr, networkDomain);
VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId,
cidr, networkDomain, useDistributedRouter, regionLevelVpc);
if (displayVpc != null) {
vpc.setDisplay(displayVpc);
}
@ -2108,7 +2286,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
networkDomain = vpc.getNetworkDomain();
}
if (vpc.getZoneId() != zoneId) {
if (!vpc.isRegionLevelVpc() && vpc.getZoneId() != zoneId) {
throw new InvalidParameterValueException("New network doesn't belong to vpc zone");
}
@ -2187,6 +2365,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
hTypes.add(HypervisorType.KVM);
hTypes.add(HypervisorType.Simulator);
hTypes.add(HypervisorType.LXC);
hTypes.add(HypervisorType.Hyperv);
return hTypes;
}

View File

@ -1153,9 +1153,9 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
// Offering #5
NetworkOfferingVO defaultNetscalerNetworkOffering =
new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering,
"Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true,
Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false);
new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering,
"Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true,
Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false, false);
defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled);
defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering);

View File

@ -343,7 +343,9 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
}
for (HostVO host : gpuEnabledHosts) {
HashMap<String, HashMap<String, Long>> groupDetails = _resourceMgr.getGPUStatistics(host);
_resourceMgr.updateGPUDetails(host.getId(), groupDetails);
if (groupDetails != null) {
_resourceMgr.updateGPUDetails(host.getId(), groupDetails);
}
}
hostIds = _hostGpuGroupsDao.listHostIds();
} catch (Throwable t) {

View File

@ -854,8 +854,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
}
@Override
public BigDecimal getStorageOverProvisioningFactor(Long dcId) {
return new BigDecimal(CapacityManager.StorageOverprovisioningFactor.valueIn(dcId));
public BigDecimal getStorageOverProvisioningFactor(Long poolId) {
return new BigDecimal(CapacityManager.StorageOverprovisioningFactor.valueIn(poolId));
}
@Override
@ -869,13 +869,18 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
long totalOverProvCapacity;
if (storagePool.getPoolType() == StoragePoolType.NetworkFilesystem || storagePool.getPoolType() == StoragePoolType.VMFS) {
BigDecimal overProvFactor = getStorageOverProvisioningFactor(storagePool.getDataCenterId());
totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(storagePool.getCapacityBytes())).longValue();
// All this is for the inaccuracy of floats for big number multiplication.
BigDecimal overProvFactor = getStorageOverProvisioningFactor(storagePool.getId());
totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(storagePool.getCapacityBytes())).longValue();
s_logger.debug("Found storage pool " + storagePool.getName() + " of type " + storagePool.getPoolType().toString() + " with overprovisioning factor "
+ overProvFactor.toString());
s_logger.debug("Total over provisioned capacity calculated is " + overProvFactor + " * " + storagePool.getCapacityBytes());
} else {
s_logger.debug("Found storage pool " + storagePool.getName() + " of type " + storagePool.getPoolType().toString());
totalOverProvCapacity = storagePool.getCapacityBytes();
}
s_logger.debug("Total over provisioned capacity of the pool " + storagePool.getName() + " id: " + storagePool.getId() + " is " + totalOverProvCapacity);
if (capacities.size() == 0) {
CapacityVO capacity =
new CapacityVO(storagePool.getId(), storagePool.getDataCenterId(), storagePool.getPodId(), storagePool.getClusterId(), allocated, totalOverProvCapacity,
@ -1552,16 +1557,22 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
long totalOverProvCapacity;
if (pool.getPoolType() == StoragePoolType.NetworkFilesystem || pool.getPoolType() == StoragePoolType.VMFS) {
totalOverProvCapacity = getStorageOverProvisioningFactor(pool.getDataCenterId()).multiply(new BigDecimal(pool.getCapacityBytes())).longValue();
BigDecimal overProvFactor = getStorageOverProvisioningFactor(pool.getId());
totalOverProvCapacity = overProvFactor.multiply(new BigDecimal(pool.getCapacityBytes())).longValue();
s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString() + " with overprovisioning factor "
+ overProvFactor.toString());
s_logger.debug("Total over provisioned capacity calculated is " + overProvFactor + " * " + pool.getCapacityBytes());
} else {
totalOverProvCapacity = pool.getCapacityBytes();
s_logger.debug("Found storage pool " + poolVO.getName() + " of type " + pool.getPoolType().toString());
}
s_logger.debug("Total capacity of the pool " + poolVO.getName() + " id: " + pool.getId() + " is " + totalOverProvCapacity);
double storageAllocatedThreshold = CapacityManager.StorageAllocatedCapacityDisableThreshold.valueIn(pool.getDataCenterId());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Checking pool: " + pool.getId() + " for volume allocation " + volumes.toString() + ", maxSize : " + totalOverProvCapacity +
", totalAllocatedSize : " + allocatedSizeWithtemplate + ", askingSize : " + totalAskingSize + ", allocated disable threshold: " +
storageAllocatedThreshold);
", totalAllocatedSize : " + allocatedSizeWithtemplate + ", askingSize : " + totalAskingSize + ", allocated disable threshold: " +
storageAllocatedThreshold);
}
double usedPercentage = (allocatedSizeWithtemplate + totalAskingSize) / (double)(totalOverProvCapacity);

View File

@ -2642,7 +2642,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
boolean securityGroupEnabled = false;
boolean vpcNetwork = false;
for (NetworkVO network : networkList) {
if (network.getDataCenterId() != zone.getId()) {
if ((network.getDataCenterId() != zone.getId()) && !network.isStrechedL2Network()) {
throw new InvalidParameterValueException("Network id=" + network.getId() + " doesn't belong to zone " + zone.getId());
}
@ -4016,7 +4016,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware) && !vm.getHypervisorType().equals(HypervisorType.KVM)
&& !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Simulator)) {
&& !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Hyperv)
&& !vm.getHypervisorType().equals(HypervisorType.Simulator)) {
throw new InvalidParameterValueException("Unsupported hypervisor type for vm migration, we support" + " XenServer/VMware/KVM only");
}

View File

@ -103,7 +103,7 @@ public class CreatePrivateNetworkTest {
NetworkOfferingVO ntwkOff =
new NetworkOfferingVO("offer", "fakeOffer", TrafficType.Guest, true, true, null, null, false, null, null, GuestType.Isolated, false, false, false, false,
false, false, false, false, false, false, false, false, false);
false, false, false, false, false, false, false, false, false, false);
when(networkService._networkOfferingDao.findById(anyLong())).thenReturn(ntwkOff);
List<NetworkOfferingVO> netofferlist = new ArrayList<NetworkOfferingVO>();
netofferlist.add(ntwkOff);

View File

@ -606,7 +606,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
@Override
public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain,
Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6,
String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException,
String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan ) throws ConcurrentOperationException, InsufficientCapacityException,
ResourceAllocationException {
// TODO Auto-generated method stub
return null;

View File

@ -26,6 +26,7 @@ import junit.framework.TestCase;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.test.utils.SpringUtils;
import org.junit.After;
import org.junit.Before;
@ -308,6 +309,11 @@ public class NetworkACLManagerTest extends TestCase {
return Mockito.mock(VpcService.class);
}
@Bean
public MessageBus messageBus() {
return Mockito.mock(MessageBus.class);
}
public static class Library implements TypeFilter {
@Override
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {

View File

@ -85,7 +85,7 @@ public class VpcApiUnitTest extends TestCase {
public void validateNtwkOffForVpc() {
//validate network offering
//1) correct network offering
VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain");
VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false);
boolean result = false;
try {
_vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", vo, "10.1.1.1", new AccountVO(), null);

View File

@ -98,9 +98,9 @@ public class MockVpcDaoImpl extends GenericDaoBase<VpcVO, Long> implements VpcDa
public VpcVO findById(Long id) {
VpcVO vo = null;
if (id.longValue() == 1) {
vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain");
vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false);
} else if (id.longValue() == 2) {
vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain");
vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false);
vo.setState(State.Inactive);
}

View File

@ -26,6 +26,7 @@ ALTER TABLE `cloud`.`disk_offering` ADD `cache_mode` VARCHAR( 16 ) DEFAULT 'none
UPDATE `cloud`.`hypervisor_capabilities` set max_guests_limit='150' WHERE hypervisor_version='6.1.0';
UPDATE `cloud`.`hypervisor_capabilities` set max_guests_limit='500' WHERE hypervisor_version='6.2.0';
UPDATE `cloud`.`hypervisor_capabilities` set storage_motion_supported='1' WHERE hypervisor_version='6.2' AND hypervisor_type="Hyperv";
DROP VIEW IF EXISTS `cloud`.`disk_offering_view`;
CREATE VIEW `cloud`.`disk_offering_view` AS
@ -657,6 +658,14 @@ ALTER TABLE `cloud`.`s2s_vpn_gateway` ADD COLUMN `display` tinyint(1) NOT NULL D
INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (225, UUID(), 9, 'FreeBSD 10 (32-bit)');
INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (226, UUID(), 9, 'FreeBSD 10 (64-bit)');
CREATE TABLE `cloud`.`op_router_monitoring_services` (
`vm_id` bigint unsigned UNIQUE NOT NULL COMMENT 'Primary Key',
`router_name` varchar(255) NOT NULL COMMENT 'Name of the Virtual Router',
`last_alert_timestamp` varchar(255) NOT NULL COMMENT 'Timestamp of the last alert received from Virtual Router',
PRIMARY KEY (`vm_id`),
CONSTRAINT `fk_virtual_router__id` FOREIGN KEY `fk_virtual_router__id` (`vm_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `cloud`.`event` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'True if the detail can be displayed to the end user';
DROP VIEW IF EXISTS `cloud`.`event_view`;
@ -730,5 +739,14 @@ UPDATE `cloud`.`guest_os_hypervisor` SET `created` = now();
ALTER TABLE `cloud`.`guest_os` ADD COLUMN `created` datetime COMMENT 'Time when Guest OS was created in system';
ALTER TABLE `cloud`.`guest_os` ADD COLUMN `removed` datetime COMMENT 'Time when Guest OS was removed if deleted, else NULL';
UPDATE `cloud`.`guest_os` SET `created` = now();
ALTER TABLE `cloud`.`vm_reservation` ADD COLUMN `deployment_planner` varchar(40) DEFAULT NULL COMMENT 'Preferred deployment planner for the vm';
ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_distributed_router boolean default false;
ALTER TABLE `cloud`.`vpc` ADD COLUMN uses_distributed_router boolean default false;
INSERT INTO `cloud`.`storage_pool_details` (pool_id,name,value,display) SELECT storage_pool.id,data_center_details.name,data_center_details.value,data_center_details.display FROM `cloud`.`storage_pool` JOIN `cloud`.`data_center_details` ON data_center_details.dc_id=storage_pool.data_center_id WHERE data_center_details.name = "storage.overprovisioning.factor";
DELETE FROM `cloud`.`data_center_details` WHERE name="storage.overprovisioning.factor";
ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_region_level_vpc boolean default false;
ALTER TABLE `cloud`.`network_offerings` ADD COLUMN supports_streched_l2 boolean default false;
ALTER TABLE `cloud`.`networks` ADD COLUMN streched_l2 boolean default false;
ALTER TABLE `cloud`.`vpc` ADD COLUMN region_level_vpc boolean default false;
ALTER TABLE `cloud`.`load_balancer_vm_map` ADD COLUMN instance_ip VARCHAR(40);
ALTER TABLE `cloud`.`load_balancer_vm_map` DROP KEY `load_balancer_id`, ADD UNIQUE KEY load_balancer_id (`load_balancer_id`, `instance_id`, `instance_ip`);

Some files were not shown because too many files have changed in this diff Show More