mirror of https://github.com/apache/cloudstack.git
Merge branch '4.4' into resize-root
This commit is contained in:
commit
c02c634945
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -129,4 +129,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
|
|||
Integer getConcurrentConnections();
|
||||
|
||||
boolean isKeepAliveEnabled();
|
||||
|
||||
boolean getSupportsStrechedL2();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<>();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,5 +21,6 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
|
|||
public enum StorageAction {
|
||||
TAKESNAPSHOT,
|
||||
BACKUPSNAPSHOT,
|
||||
DELETESNAPSHOT
|
||||
DELETESNAPSHOT,
|
||||
MIGRATEVOLUME
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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?";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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" % \
|
||||
|
|
|
|||
|
|
@ -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"})
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue