CLOUDSTACK-9402 : Support for underlay features (Source & Static NAT to underlay) in Nuage VSP plugin
CLOUDSTACK-9402 : Marvin tests for Source NAT and Static NAT features verification with NuageVsp (both overlay and underlay infra). Co-Authored-By: Prashanth Manthena <[email protected]>, Frank Maximus <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8d4dc812 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8d4dc812 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8d4dc812 Branch: refs/heads/master Commit: 8d4dc81223032f104bd4c7d576aceed329c6a099 Parents: 027409d Author: Nick Livens <[email protected]> Authored: Wed Jun 15 11:04:21 2016 +0200 Committer: Prashanth Manthena <[email protected]> Committed: Thu Nov 24 21:33:02 2016 +0100 ---------------------------------------------------------------------- .../cloudstack/api/ResponseGenerator.java | 2 + core/src/com/cloud/agent/transport/Request.java | 2 +- .../spring-engine-schema-core-daos-context.xml | 1 + .../schema/src/com/cloud/dc/VlanDetailsVO.java | 83 + .../src/com/cloud/dc/dao/VlanDetailsDao.java | 25 + .../com/cloud/dc/dao/VlanDetailsDaoImpl.java | 32 + .../dao/NetworkOfferingServiceMapDao.java | 2 + .../dao/NetworkOfferingServiceMapDaoImpl.java | 9 + .../agent/api/manager/EntityExistsCommand.java | 77 + .../DisableNuageUnderlayVlanIpRangeCmd.java | 110 + .../EnableNuageUnderlayVlanIpRangeCmd.java | 110 + .../ListNuageUnderlayVlanIpRangesCmd.java | 80 + .../com/cloud/api/commands/VspConstants.java | 1 + .../api/response/NuageVlanIpRangeResponse.java | 38 + .../cloud/network/element/NuageVspElement.java | 73 +- .../network/guru/NuageVspGuestNetworkGuru.java | 42 +- .../cloud/network/manager/NuageVspManager.java | 11 + .../network/manager/NuageVspManagerImpl.java | 76 +- .../network/resource/NuageVspResource.java | 20 + .../com/cloud/util/NuageVspEntityBuilder.java | 6 +- .../src/com/cloud/util/NuageVspUtil.java | 8 + .../test/com/cloud/agent/api/CommandsTest.java | 122 +- .../network/element/NuageVspElementTest.java | 10 +- .../guru/NuageVspGuestNetworkGuruTest.java | 7 +- .../cloud/util/NuageVspEntityBuilderTest.java | 13 + server/src/com/cloud/api/ApiResponseHelper.java | 131 +- setup/db/db/schema-4910to41000.sql | 12 +- .../plugins/nuagevsp/nuageTestCase.py | 56 +- .../plugins/nuagevsp/test_nuage_source_nat.py | 1454 ++++++++++++ .../plugins/nuagevsp/test_nuage_static_nat.py | 2084 ++++++++++++++++++ tools/marvin/marvin/config/test_data.py | 8 + 31 files changed, 4538 insertions(+), 167 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/api/src/org/apache/cloudstack/api/ResponseGenerator.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index 1cc5bc8..8da1ded 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -237,6 +237,8 @@ public interface ResponseGenerator { VlanIpRangeResponse createVlanIpRangeResponse(Vlan vlan); + VlanIpRangeResponse createVlanIpRangeResponse(Class<? extends VlanIpRangeResponse> subClass, Vlan vlan); + IPAddressResponse createIPAddressResponse(ResponseView view, IpAddress ipAddress); GuestVlanRangeResponse createDedicatedGuestVlanRangeResponse(GuestVlan result); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/core/src/com/cloud/agent/transport/Request.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/transport/Request.java b/core/src/com/cloud/agent/transport/Request.java index 7b8dd0d..f78a96c 100644 --- a/core/src/com/cloud/agent/transport/Request.java +++ b/core/src/com/cloud/agent/transport/Request.java @@ -399,7 +399,7 @@ public class Request { try { _cmds = s_gson.fromJson(_content, this instanceof Response ? Answer[].class : Command[].class); } catch (RuntimeException e) { - s_logger.error("Unable to convert to json: " + _content); + s_logger.error("Unable to deserialize from json: " + _content); throw e; } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml ---------------------------------------------------------------------- diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 884bb30..c43e9ff 100644 --- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -325,6 +325,7 @@ <bean id="networkOfferingDetailsDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingDetailsDaoImpl" /> <bean id="serviceOfferingDetailsDaoImpl" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl"/> <bean id="networkDetailsDaoImpl" class="com.cloud.network.dao.NetworkDetailsDaoImpl" /> + <bean id="vlanDetailsDaoImpl" class="com.cloud.dc.dao.VlanDetailsDaoImpl" /> <bean id="hostGpuGroupsDaoImpl" class="com.cloud.gpu.dao.HostGpuGroupsDaoImpl" /> <bean id="vGPUTypesDaoImpl" class="com.cloud.gpu.dao.VGPUTypesDaoImpl" /> <bean id="AffinityGroupDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDaoImpl" /> http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/engine/schema/src/com/cloud/dc/VlanDetailsVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/dc/VlanDetailsVO.java b/engine/schema/src/com/cloud/dc/VlanDetailsVO.java new file mode 100644 index 0000000..1a1db3a --- /dev/null +++ b/engine/schema/src/com/cloud/dc/VlanDetailsVO.java @@ -0,0 +1,83 @@ +// 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.dc; + +import org.apache.cloudstack.api.ResourceDetail; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "vlan_details") +public class VlanDetailsVO implements ResourceDetail { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "vlan_id") + private long resourceId; + + @Column(name = "name") + private String name; + + @Column(name = "value", length = 1024) + private String value; + + @Column(name = "display") + private boolean display = true; + + public VlanDetailsVO() { + } + + public VlanDetailsVO(long networkId, String name, String value, boolean display) { + this.resourceId = networkId; + this.name = name; + this.value = value; + this.display = display; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getValue() { + return value; + } + + @Override + public long getResourceId() { + return resourceId; + } + + @Override + public boolean isDisplay() { + return display; + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/engine/schema/src/com/cloud/dc/dao/VlanDetailsDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/dc/dao/VlanDetailsDao.java b/engine/schema/src/com/cloud/dc/dao/VlanDetailsDao.java new file mode 100644 index 0000000..dfc72a0 --- /dev/null +++ b/engine/schema/src/com/cloud/dc/dao/VlanDetailsDao.java @@ -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 +// 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.dc.dao; + +import com.cloud.dc.VlanDetailsVO; +import com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDao; + +public interface VlanDetailsDao extends GenericDao<VlanDetailsVO, Long>, ResourceDetailsDao<VlanDetailsVO> { + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/engine/schema/src/com/cloud/dc/dao/VlanDetailsDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/dc/dao/VlanDetailsDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/VlanDetailsDaoImpl.java new file mode 100644 index 0000000..43f9087 --- /dev/null +++ b/engine/schema/src/com/cloud/dc/dao/VlanDetailsDaoImpl.java @@ -0,0 +1,32 @@ +// 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 +// 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.dc.dao; + + +import com.cloud.dc.VlanDetailsVO; +import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; +import org.springframework.stereotype.Component; + +@Component +public class VlanDetailsDaoImpl extends ResourceDetailsDaoBase<VlanDetailsVO> implements VlanDetailsDao { + + @Override + public void addDetail(long resourceId, String key, String value, boolean display) { + super.addDetail(new VlanDetailsVO(resourceId, key, value, display)); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDao.java b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDao.java index 8616449..8fb5d6d 100644 --- a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDao.java +++ b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDao.java @@ -31,6 +31,8 @@ import com.cloud.utils.db.GenericDao; public interface NetworkOfferingServiceMapDao extends GenericDao<NetworkOfferingServiceMapVO, Long> { boolean areServicesSupportedByNetworkOffering(long networkOfferingId, Service... services); + boolean canProviderSupportServiceInNetworkOffering(long networkOfferingId, Service service, Provider provider); + List<NetworkOfferingServiceMapVO> listByNetworkOfferingId(long networkOfferingId); void deleteByOfferingId(long networkOfferingId); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java index b667e58..7868be2 100644 --- a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java +++ b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java @@ -104,6 +104,15 @@ public class NetworkOfferingServiceMapDaoImpl extends GenericDaoBase<NetworkOffe } @Override + public boolean canProviderSupportServiceInNetworkOffering(long networkOfferingId, Service service, Provider provider) { + SearchCriteria<NetworkOfferingServiceMapVO> sc = AllFieldsSearch.create(); + sc.setParameters("networkOfferingId", networkOfferingId); + sc.setParameters("service", service.getName()); + sc.setParameters("provider", provider.getName()); + return findOneBy(sc) != null; + } + + @Override public List<NetworkOfferingServiceMapVO> listByNetworkOfferingId(long networkOfferingId) { SearchCriteria<NetworkOfferingServiceMapVO> sc = AllFieldsSearch.create(); sc.setParameters("networkOfferingId", networkOfferingId); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java new file mode 100644 index 0000000..64f3768 --- /dev/null +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/agent/api/manager/EntityExistsCommand.java @@ -0,0 +1,77 @@ +// +// 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.manager; + +import com.cloud.agent.api.Command; + +public class EntityExistsCommand<T> extends Command { + + private transient Class<T> _type; + private final String _className; + private final String _uuid; + + public EntityExistsCommand(Class<T> type, String uuid) { + super(); + this._type = type; + this._className = type.getName(); + this._uuid = uuid; + } + + public Class<T> getType() { + if (_type == null) { + try { + _type = (Class<T>)Class.forName(_className); + } catch (ClassNotFoundException e) { + } + } + return _type; + } + + public String getUuid() { + return _uuid; + } + + @Override + public boolean executeInSequence() { + return false; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof EntityExistsCommand)) return false; + if (!super.equals(o)) return false; + + EntityExistsCommand that = (EntityExistsCommand) o; + + if (getType() != null ? !getType().equals(that.getType()) : that.getType() != null) return false; + if (_uuid != null ? !_uuid.equals(that._uuid) : that._uuid != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (getType() != null ? getType().hashCode() : 0); + result = 31 * result + (_uuid != null ? _uuid.hashCode() : 0); + return result; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/DisableNuageUnderlayVlanIpRangeCmd.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/DisableNuageUnderlayVlanIpRangeCmd.java b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/DisableNuageUnderlayVlanIpRangeCmd.java new file mode 100644 index 0000000..bcc804c --- /dev/null +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/DisableNuageUnderlayVlanIpRangeCmd.java @@ -0,0 +1,110 @@ +// +// 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.api.commands; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.manager.NuageVspManager; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.VlanIpRangeResponse; +import org.apache.cloudstack.context.CallContext; + +import javax.inject.Inject; + +@APICommand(name = DisableNuageUnderlayVlanIpRangeCmd.APINAME, description = "disable Nuage underlay on vlan ip range", responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.10", + authorized = {RoleType.Admin}) +public class DisableNuageUnderlayVlanIpRangeCmd extends BaseAsyncCmd { + public static final String APINAME = "disableNuageUnderlayVlanIpRange"; + + @Inject + NuageVspManager _nuageVspManager; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VlanIpRangeResponse.class, required = true, description = "VLAN IP Range ID") + private long vlanIpRangeId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public long getVlanIpRangeId() { + return vlanIpRangeId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + boolean result = _nuageVspManager.updateNuageUnderlayVlanIpRange(vlanIpRangeId, false); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to disable underlay, VLAN IP range is already pushed to the Nuage VSP device."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } + + @Override + public String getEventType() { + return "VLAN.DISABLE.NUAGE.UNDERLAY"; + } + + @Override + public String getEventDescription() { + return "Disable VLAN IP range Nuage underlay"; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/EnableNuageUnderlayVlanIpRangeCmd.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/EnableNuageUnderlayVlanIpRangeCmd.java b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/EnableNuageUnderlayVlanIpRangeCmd.java new file mode 100644 index 0000000..b1eb9d7 --- /dev/null +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/EnableNuageUnderlayVlanIpRangeCmd.java @@ -0,0 +1,110 @@ +// +// 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.api.commands; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.manager.NuageVspManager; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.VlanIpRangeResponse; +import org.apache.cloudstack.context.CallContext; + +import javax.inject.Inject; + +@APICommand(name = EnableNuageUnderlayVlanIpRangeCmd.APINAME, description = "enable Nuage underlay on vlan ip range", responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.10", + authorized = {RoleType.Admin}) +public class EnableNuageUnderlayVlanIpRangeCmd extends BaseAsyncCmd { + public static final String APINAME = "enableNuageUnderlayVlanIpRange"; + + @Inject + NuageVspManager _nuageVspManager; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VlanIpRangeResponse.class, required = true, description = "VLAN IP Range ID") + private long vlanIpRangeId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public long getVlanIpRangeId() { + return vlanIpRangeId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + boolean result = _nuageVspManager.updateNuageUnderlayVlanIpRange(vlanIpRangeId, true); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to enable underlay, VLAN IP range is already pushed to the Nuage VSP device."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } + + @Override + public String getEventType() { + return "VLAN.ENABLE.NUAGE.UNDERLAY"; + } + + @Override + public String getEventDescription() { + return "Enable VLAN IP range Nuage underlay"; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/ListNuageUnderlayVlanIpRangesCmd.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/ListNuageUnderlayVlanIpRangesCmd.java b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/ListNuageUnderlayVlanIpRangesCmd.java new file mode 100644 index 0000000..38bc788 --- /dev/null +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/ListNuageUnderlayVlanIpRangesCmd.java @@ -0,0 +1,80 @@ +// +// 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.api.commands; + +import com.cloud.api.response.NuageVlanIpRangeResponse; +import com.cloud.dc.Vlan; +import com.cloud.network.manager.NuageVspManager; +import com.cloud.utils.Pair; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; +import org.apache.cloudstack.api.response.ListResponse; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = "listNuageUnderlayVlanIpRanges", description = "enable Nuage underlay on vlan ip range", responseObject = NuageVlanIpRangeResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.10", + authorized = {RoleType.Admin}) +public class ListNuageUnderlayVlanIpRangesCmd extends ListVlanIpRangesCmd { + public static final String APINAME = "listNuageUnderlayVlanIpRanges"; + + @Inject + NuageVspManager _nuageVspManager; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = VspConstants.NUAGE_VSP_API_UNDERLAY, type = CommandType.BOOLEAN, description = "true to list only underlay enabled, false if not, empty for all") + private Boolean underlay; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Boolean getUnderlay() { + return underlay; + } + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + Pair<List<? extends Vlan>, Integer> vlans = _mgr.searchForVlans(this); + ListResponse<NuageVlanIpRangeResponse> response = new ListResponse<NuageVlanIpRangeResponse>(); + List<NuageVlanIpRangeResponse> vlanIpRanges = _nuageVspManager.filterNuageVlanIpRanges(vlans.first(), underlay); + response.setResponses(vlanIpRanges); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/VspConstants.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/VspConstants.java b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/VspConstants.java index 7abcdfb..55e6b47 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/VspConstants.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/api/commands/VspConstants.java @@ -33,4 +33,5 @@ public class VspConstants { public static final String NUAGE_VSP_API_RESOURCE_FILTER = "resourcefilter"; public static final String NUAGE_VSP_API_RESOURCE_INFO = "resourceinfo"; public static final String NUAGE_VSP_CMS_ID = "cmsid"; + public static final String NUAGE_VSP_API_UNDERLAY = "underlay"; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/api/response/NuageVlanIpRangeResponse.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/api/response/NuageVlanIpRangeResponse.java b/plugins/network-elements/nuage-vsp/src/com/cloud/api/response/NuageVlanIpRangeResponse.java new file mode 100644 index 0000000..cc3204d --- /dev/null +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/api/response/NuageVlanIpRangeResponse.java @@ -0,0 +1,38 @@ +// +// 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.api.response; + +import com.cloud.api.commands.VspConstants; +import com.cloud.dc.Vlan; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.api.response.VlanIpRangeResponse; + +@EntityReference(value = Vlan.class) +public class NuageVlanIpRangeResponse extends VlanIpRangeResponse { + @SerializedName(VspConstants.NUAGE_VSP_API_UNDERLAY) + @Param(description = "true if Nuage underlay enabled, false if not") + private boolean underlay; + + public void setUnderlay(boolean underlay) { + this.underlay = underlay; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java index aae16b8..d0b9ed9 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/element/NuageVspElement.java @@ -53,9 +53,11 @@ import com.cloud.agent.api.element.ApplyStaticNatVspCommand; import com.cloud.agent.api.element.ImplementVspCommand; import com.cloud.agent.api.element.ShutDownVpcVspCommand; import com.cloud.agent.api.element.ShutDownVspCommand; +import com.cloud.dc.Vlan; import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.VlanDao; +import com.cloud.dc.dao.VlanDetailsDao; import com.cloud.deploy.DeployDestination; import com.cloud.domain.Domain; import com.cloud.domain.dao.DomainDao; @@ -71,7 +73,6 @@ import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkModel; import com.cloud.network.Networks; -import com.cloud.network.NuageVspDeviceVO; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PublicIpAddress; @@ -109,8 +110,9 @@ import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; import com.cloud.util.NuageVspEntityBuilder; +import com.cloud.util.NuageVspUtil; import com.cloud.utils.component.AdapterBase; -import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; @@ -149,6 +151,8 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider @Inject VlanDao _vlanDao; @Inject + VlanDetailsDao _vlanDetailsDao; + @Inject NicDao _nicDao; @Inject VpcDao _vpcDao; @@ -282,7 +286,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider floatingIpUuids.add(ip.getUuid()); } VspDhcpDomainOption vspDhcpOptions = _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering); - HostVO nuageVspHost = getNuageVspHost(network.getPhysicalNetworkId()); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); ImplementVspCommand cmd = new ImplementVspCommand(vspNetwork, ingressFirewallRules, egressFirewallRules, floatingIpUuids, vspDhcpOptions); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { @@ -353,7 +357,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider NetworkOfferingVO networkOfferingVO = _ntwkOfferingDao.findById(network.getNetworkOfferingId()); VspDhcpDomainOption vspDhcpOptions = _nuageVspEntityBuilder.buildNetworkDhcpOption(network, networkOfferingVO); VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false); - HostVO nuageVspHost = getNuageVspHost(network.getPhysicalNetworkId()); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); ShutDownVspCommand cmd = new ShutDownVspCommand(vspNetwork, vspDhcpOptions); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { @@ -399,8 +403,8 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider return false; } - if ((services.contains(Service.StaticNat)) && (!services.contains(Service.SourceNat))) { - s_logger.warn("Unable to provide StaticNat without the SourceNat service."); + if (!services.contains(Service.SourceNat)) { + s_logger.warn("Unable to support services combination without SourceNat service provided by Nuage VSP."); return false; } @@ -438,6 +442,20 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider } } + if (service != Service.Connectivity && !_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), Service.Connectivity, getProvider())) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as Connectivity provider"); + } + return false; + } + + if (service != Service.SourceNat && !_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(), Service.SourceNat, getProvider())) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as SourceNat provider"); + } + return false; + } + if (network.getVpcId() != null) { NetworkOffering networkOffering = _ntwkOfferingDao.findById(network.getNetworkOfferingId()); if (!networkOffering.getIsPersistent()) { @@ -481,13 +499,15 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider for (StaticNat staticNat : rules) { IPAddressVO sourceNatIp = _ipAddressDao.findById(staticNat.getSourceIpAddressId()); VlanVO sourceNatVlan = _vlanDao.findById(sourceNatIp.getVlanId()); + checkVlanUnderlayCompatibility(sourceNatVlan); + NicVO nicVO = _nicDao.findByIp4AddressAndNetworkId(staticNat.getDestIpAddress(), staticNat.getNetworkId()); VspStaticNat vspStaticNat = _nuageVspEntityBuilder.buildVspStaticNat(staticNat.isForRevoke(), sourceNatIp, sourceNatVlan, nicVO); vspStaticNatDetails.add(vspStaticNat); } VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(config, false); - HostVO nuageVspHost = getNuageVspHost(config.getPhysicalNetworkId()); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(config.getPhysicalNetworkId()); ApplyStaticNatVspCommand cmd = new ApplyStaticNatVspCommand(vspNetwork, vspStaticNatDetails); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { @@ -500,6 +520,28 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider return true; } + private void checkVlanUnderlayCompatibility(VlanVO newVlan) throws ResourceUnavailableException { + List<VlanVO> vlans = _vlanDao.listByZone(newVlan.getDataCenterId()); + if (CollectionUtils.isNotEmpty(vlans)) { + boolean newVlanUnderlay = NuageVspUtil.isUnderlayEnabledForVlan(_vlanDetailsDao, newVlan); + for (VlanVO vlan : vlans) { + if (vlan.getId() == newVlan.getId()) continue; + + final String newCidr = NetUtils.getCidrFromGatewayAndNetmask(newVlan.getVlanGateway(), newVlan.getVlanNetmask()); + final String existingCidr = NetUtils.getCidrFromGatewayAndNetmask(vlan.getVlanGateway(), vlan.getVlanNetmask()); + + NetUtils.SupersetOrSubset supersetOrSubset = NetUtils.isNetowrkASubsetOrSupersetOfNetworkB(newCidr, existingCidr); + if (supersetOrSubset == NetUtils.SupersetOrSubset.sameSubnet) { + boolean vlanUnderlay = NuageVspUtil.isUnderlayEnabledForVlan(_vlanDetailsDao, vlan); + if (newVlanUnderlay != vlanUnderlay) { + throw new ResourceUnavailableException("Mixed values for the underlay flag for IP ranges in the same subnet is not supported", Vlan.class, newVlan.getId()); + } + break; + } + } + } + } + @Override public IpDeployer getIpDeployer(Network network) { return this; @@ -536,7 +578,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider } }); - HostVO nuageVspHost = getNuageVspHost(network.getPhysicalNetworkId()); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); VspAclRule.ACLType vspAclType = isNetworkAcl ? VspAclRule.ACLType.NetworkACL : VspAclRule.ACLType.Firewall; ApplyAclRuleVspCommand cmd = new ApplyAclRuleVspCommand(vspAclType, vspNetwork, vspAclRules, networkReset); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); @@ -605,7 +647,7 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider }); Domain vpcDomain = _domainDao.findById(vpc.getDomainId()); - HostVO nuageVspHost = getNuageVspHost(getPhysicalNetworkId(vpc.getZoneId())); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(getPhysicalNetworkId(vpc.getZoneId())); String preConfiguredDomainTemplateName; VpcDetailVO domainTemplateNameDetail = _vpcDetailsDao.findDetail(vpc.getId(), NuageVspManager.nuageDomainTemplateDetailName); @@ -680,17 +722,4 @@ public class NuageVspElement extends AdapterBase implements ConnectivityProvider } return new DeleteHostAnswer(true); } - - private HostVO getNuageVspHost(Long physicalNetworkId) { - HostVO nuageVspHost; - List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listByPhysicalNetwork(physicalNetworkId); - if (nuageVspDevices != null && (!nuageVspDevices.isEmpty())) { - NuageVspDeviceVO config = nuageVspDevices.iterator().next(); - nuageVspHost = _hostDao.findById(config.getHostId()); - _hostDao.loadDetails(nuageVspHost); - } else { - throw new CloudRuntimeException("There is no Nuage VSP device configured on physical network " + physicalNetworkId); - } - return nuageVspHost; - } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java index aedf646..6bdd9e4 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java @@ -63,7 +63,6 @@ import com.cloud.network.Network.GuestType; import com.cloud.network.Network.State; import com.cloud.network.NetworkProfile; import com.cloud.network.Networks; -import com.cloud.network.NuageVspDeviceVO; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetwork.IsolationMethod; import com.cloud.network.dao.IPAddressVO; @@ -83,7 +82,6 @@ import com.cloud.user.dao.AccountDao; import com.cloud.util.NuageVspEntityBuilder; import com.cloud.utils.StringUtils; import com.cloud.utils.db.DB; -import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; @@ -198,7 +196,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { implemented.setBroadcastUri(Networks.BroadcastDomainType.Vsp.toUri(broadcastUriStr)); implemented.setBroadcastDomainType(Networks.BroadcastDomainType.Vsp); - HostVO nuageVspHost = getNuageVspHost(physicalNetworkId); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(physicalNetworkId); ImplementNetworkVspCommand cmd = new ImplementNetworkVspCommand(vspNetwork, _nuageVspEntityBuilder.buildNetworkDhcpOption(network, offering)); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); @@ -256,7 +254,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { throw new IllegalStateException("The broadcast URI path " + network.getBroadcastUri() + " is empty or in an incorrect format."); } - HostVO nuageVspHost = getNuageVspHost(network.getPhysicalNetworkId()); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false); // Set flags for dhcp options @@ -344,7 +342,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { @Override protected boolean canHandle(NetworkOffering offering, final NetworkType networkType, final PhysicalNetwork physicalNetwork) { if (networkType == NetworkType.Advanced && isMyTrafficType(offering.getTrafficType()) && (offering.getGuestType() == Network.GuestType.Isolated || offering.getGuestType() == Network.GuestType.Shared) - && isMyIsolationMethod(physicalNetwork)) { + && isMyIsolationMethod(physicalNetwork) && hasRequiredServices(offering)) { if (_configMgr.isOfferingForVpc(offering) && !offering.getIsPersistent()) { if (s_logger.isDebugEnabled()) { s_logger.debug("NuageVsp can't handle VPC tiers which use a network offering which are not persistent"); @@ -360,6 +358,23 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { } } + private boolean hasRequiredServices(NetworkOffering networkOffering) { + if (!_ntwkOfferingSrvcDao.canProviderSupportServiceInNetworkOffering(networkOffering.getId(), Network.Service.Connectivity, Network.Provider.NuageVsp)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as Connectivity provider"); + } + return false; + } + + if (!_ntwkOfferingSrvcDao.canProviderSupportServiceInNetworkOffering(networkOffering.getId(), Network.Service.SourceNat, Network.Provider.NuageVsp)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("NuageVsp can't handle networks which use a network offering without NuageVsp as SourceNat provider"); + } + return false; + } + return true; + } + @Override @DB public void deallocate(Network network, NicProfile nic, VirtualMachineProfile vm) { @@ -379,7 +394,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false); VspVm vspVm = _nuageVspEntityBuilder.buildVspVm(vm.getVirtualMachine(), network); VspNic vspNic = _nuageVspEntityBuilder.buildVspNic(nicFromDb.getUuid(), nic); - HostVO nuageVspHost = getNuageVspHost(network.getPhysicalNetworkId()); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); DeallocateVmVspCommand cmd = new DeallocateVmVspCommand(vspNetwork, vspVm, vspNic); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); @@ -431,7 +446,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { s_logger.debug("Handling trash() call back to delete the network " + network.getName() + " with uuid " + network.getUuid() + " from VSP"); } VspNetwork vspNetwork = _nuageVspEntityBuilder.buildVspNetwork(network, false); - HostVO nuageVspHost = getNuageVspHost(network.getPhysicalNetworkId()); + HostVO nuageVspHost = _nuageVspManager.getNuageVspHost(network.getPhysicalNetworkId()); TrashNetworkVspCommand cmd = new TrashNetworkVspCommand(vspNetwork); Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); if (answer == null || !answer.getResult()) { @@ -447,19 +462,6 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { return super.trash(network, offering); } - private HostVO getNuageVspHost(long physicalNetworkId) { - HostVO nuageVspHost; - List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listByPhysicalNetwork(physicalNetworkId); - if (nuageVspDevices != null && (!nuageVspDevices.isEmpty())) { - NuageVspDeviceVO config = nuageVspDevices.iterator().next(); - nuageVspHost = _hostDao.findById(config.getHostId()); - _hostDao.loadDetails(nuageVspHost); - } else { - throw new CloudRuntimeException("There is no Nuage VSP device configured on physical network " + physicalNetworkId); - } - return nuageVspHost; - } - private boolean networkHasDns(Network network) { if (network != null) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java index 4861fb2..e5c9871 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManager.java @@ -23,7 +23,10 @@ import com.cloud.api.commands.AddNuageVspDeviceCmd; import com.cloud.api.commands.DeleteNuageVspDeviceCmd; import com.cloud.api.commands.ListNuageVspDevicesCmd; import com.cloud.api.commands.UpdateNuageVspDeviceCmd; +import com.cloud.api.response.NuageVlanIpRangeResponse; import com.cloud.api.response.NuageVspDeviceResponse; +import com.cloud.dc.Vlan; +import com.cloud.host.HostVO; import com.cloud.network.Network; import com.cloud.network.NuageVspDeviceVO; import com.cloud.utils.component.PluggableService; @@ -42,6 +45,8 @@ public interface NuageVspManager extends PluggableService { static final String nuageDomainTemplateDetailName = "domainTemplateName"; + static final String nuageUnderlayVlanIpRangeDetailKey = "nuage.underlay"; + static final ConfigKey<Boolean> NuageVspConfigDns = new ConfigKey<Boolean>(Boolean.class, "nuagevsp.configure.dns", "Advanced", "true", "Defines if NuageVsp plugin needs to configure DNS setting for a VM or not. True will configure the DNS and false will not configure the DNS settings", true, Scope.Global, null); @@ -83,4 +88,10 @@ public interface NuageVspManager extends PluggableService { List<String> getGatewaySystemIds(); + HostVO getNuageVspHost(long physicalNetworkId); + + boolean updateNuageUnderlayVlanIpRange(long vlanIpRangeId, boolean enabled); + + List<NuageVlanIpRangeResponse> filterNuageVlanIpRanges(List<? extends Vlan> vlanIpRanges, Boolean underlay); + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java index b82b194..7bc36e2 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/manager/NuageVspManagerImpl.java @@ -27,6 +27,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.PingNuageVspCommand; import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.manager.EntityExistsCommand; import com.cloud.agent.api.manager.GetApiDefaultsAnswer; import com.cloud.agent.api.manager.GetApiDefaultsCommand; import com.cloud.agent.api.manager.SupportedApiVersionCommand; @@ -37,11 +38,20 @@ import com.cloud.agent.api.sync.SyncNuageVspCmsIdCommand; import com.cloud.api.ApiDBUtils; import com.cloud.api.commands.AddNuageVspDeviceCmd; import com.cloud.api.commands.DeleteNuageVspDeviceCmd; +import com.cloud.api.commands.DisableNuageUnderlayVlanIpRangeCmd; +import com.cloud.api.commands.EnableNuageUnderlayVlanIpRangeCmd; +import com.cloud.api.commands.ListNuageUnderlayVlanIpRangesCmd; import com.cloud.api.commands.ListNuageVspDevicesCmd; import com.cloud.api.commands.UpdateNuageVspDeviceCmd; +import com.cloud.api.response.NuageVlanIpRangeResponse; import com.cloud.api.response.NuageVspDeviceResponse; import com.cloud.dc.DataCenterVO; +import com.cloud.dc.Vlan; +import com.cloud.dc.VlanDetailsVO; +import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.dc.dao.VlanDetailsDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -108,6 +118,7 @@ import com.cloud.util.NuageVspEntityBuilder; import net.nuage.vsp.acs.NuageVspPluginClientLoader; import net.nuage.vsp.acs.client.api.model.VspApiDefaults; import net.nuage.vsp.acs.client.api.model.VspDomain; +import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; @@ -185,6 +196,12 @@ public class NuageVspManagerImpl extends ManagerBase implements NuageVspManager, NetworkOfferingServiceMapDao _networkOfferingServiceMapDao; @Inject NuageVspEntityBuilder _nuageVspEntityBuilder; + @Inject + VlanDao _vlanDao; + @Inject + VlanDetailsDao _vlanDetailsDao; + @Inject + ResponseGenerator _responseGenerator; @Inject MessageBus _messageBus; @@ -209,7 +226,7 @@ public class NuageVspManagerImpl extends ManagerBase implements NuageVspManager, @Override public List<Class<?>> getCommands() { return Lists.<Class<?>>newArrayList(AddNuageVspDeviceCmd.class, DeleteNuageVspDeviceCmd.class, ListNuageVspDevicesCmd.class, - UpdateNuageVspDeviceCmd.class); + UpdateNuageVspDeviceCmd.class, EnableNuageUnderlayVlanIpRangeCmd.class, DisableNuageUnderlayVlanIpRangeCmd.class, ListNuageUnderlayVlanIpRangesCmd.class); } @Override @@ -678,6 +695,63 @@ public class NuageVspManagerImpl extends ManagerBase implements NuageVspManager, } @Override + public HostVO getNuageVspHost(long physicalNetworkId) { + HostVO nuageVspHost; + List<NuageVspDeviceVO> nuageVspDevices = _nuageVspDao.listByPhysicalNetwork(physicalNetworkId); + if (CollectionUtils.isEmpty(nuageVspDevices)) { + // Perhaps another physical network is passed from within the same zone, find the VSP physical network in that case + PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); + List<PhysicalNetworkVO> physicalNetworksInZone = _physicalNetworkDao.listByZone(physicalNetwork.getDataCenterId()); + for (PhysicalNetworkVO physicalNetworkInZone : physicalNetworksInZone) { + if (physicalNetworkInZone.getIsolationMethods().contains(PhysicalNetwork.IsolationMethod.VSP.name())) { + nuageVspDevices = _nuageVspDao.listByPhysicalNetwork(physicalNetworkInZone.getId()); + break; + } + } + } + + if (CollectionUtils.isNotEmpty(nuageVspDevices)) { + NuageVspDeviceVO config = nuageVspDevices.iterator().next(); + nuageVspHost = _hostDao.findById(config.getHostId()); + _hostDao.loadDetails(nuageVspHost); + } else { + throw new CloudRuntimeException("There is no Nuage VSP device configured on physical network " + physicalNetworkId); + } + return nuageVspHost; + } + + @Override + public boolean updateNuageUnderlayVlanIpRange(long vlanIpRangeId, boolean enabled) { + VlanVO staticNatVlan = _vlanDao.findById(vlanIpRangeId); + HostVO nuageVspHost = getNuageVspHost(staticNatVlan.getPhysicalNetworkId()); + EntityExistsCommand<Vlan> cmd = new EntityExistsCommand<Vlan>(Vlan.class, staticNatVlan.getUuid()); + Answer answer = _agentMgr.easySend(nuageVspHost.getId(), cmd); + if (answer != null && !answer.getResult()) { + _vlanDetailsDao.addDetail(staticNatVlan.getId(), NuageVspManager.nuageUnderlayVlanIpRangeDetailKey, String.valueOf(enabled), false); + return true; + } + + return false; + } + + @Override + public List<NuageVlanIpRangeResponse> filterNuageVlanIpRanges(List<? extends Vlan> vlanIpRanges, Boolean underlay) { + List<NuageVlanIpRangeResponse> nuageVlanIpRanges = Lists.newArrayList(); + for (Vlan vlanIpRange : vlanIpRanges) { + NuageVlanIpRangeResponse nuageVlanIpRange = (NuageVlanIpRangeResponse) _responseGenerator.createVlanIpRangeResponse(NuageVlanIpRangeResponse.class, vlanIpRange); + + VlanDetailsVO nuageUnderlayDetail = _vlanDetailsDao.findDetail(vlanIpRange.getId(), NuageVspManager.nuageUnderlayVlanIpRangeDetailKey); + boolean underlayEnabled = nuageUnderlayDetail != null && nuageUnderlayDetail.getValue().equalsIgnoreCase(String.valueOf(true)); + nuageVlanIpRange.setUnderlay(underlayEnabled); + if (underlay == null || underlayEnabled == underlay) { + nuageVlanIpRanges.add(nuageVlanIpRange); + } + nuageVlanIpRange.setObjectName("nuagevlaniprange"); + } + return nuageVlanIpRanges; + } + + @Override public boolean preStateTransitionEvent(Status oldState, Status.Event event, Status newState, Host host, boolean status, Object opaque) { return true; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java index 5cb6683..9d04ab0 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/resource/NuageVspResource.java @@ -58,6 +58,7 @@ import com.cloud.agent.api.guru.ImplementNetworkVspCommand; import com.cloud.agent.api.guru.ReserveVmInterfaceVspCommand; import com.cloud.agent.api.guru.TrashNetworkVspCommand; import com.cloud.agent.api.guru.UpdateDhcpOptionVspCommand; +import com.cloud.agent.api.manager.EntityExistsCommand; import com.cloud.agent.api.manager.GetApiDefaultsAnswer; import com.cloud.agent.api.manager.GetApiDefaultsCommand; import com.cloud.agent.api.manager.SupportedApiVersionCommand; @@ -65,12 +66,14 @@ import com.cloud.agent.api.sync.SyncDomainAnswer; import com.cloud.agent.api.sync.SyncDomainCommand; import com.cloud.agent.api.sync.SyncNuageVspCmsIdAnswer; import com.cloud.agent.api.sync.SyncNuageVspCmsIdCommand; +import com.cloud.dc.Vlan; import com.cloud.host.Host; import com.cloud.resource.ServerResource; import com.cloud.util.NuageVspUtil; import com.cloud.utils.StringUtils; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; +import net.nuage.vsp.acs.client.common.model.NuageVspEntity; import static com.cloud.agent.api.sync.SyncNuageVspCmsIdCommand.SyncType; @@ -323,6 +326,8 @@ public class NuageVspResource extends ManagerBase implements ServerResource { return executeRequest((GetApiDefaultsCommand)cmd); } else if (cmd instanceof SupportedApiVersionCommand) { return executeRequest((SupportedApiVersionCommand)cmd); + } else if (cmd instanceof EntityExistsCommand) { + return executeRequest((EntityExistsCommand)cmd); } if (s_logger.isDebugEnabled()) { s_logger.debug("Received unsupported command " + cmd.toString()); @@ -514,6 +519,21 @@ public class NuageVspResource extends ManagerBase implements ServerResource { } } + private Answer executeRequest(EntityExistsCommand cmd) { + try { + isNuageVspApiLoaded(); + NuageVspEntity entityType = null; + if (Vlan.class.isAssignableFrom(cmd.getType())) { + entityType = NuageVspEntity.SHARED_NETWORK; + } + boolean exists = _nuageVspApiClient.entityExists(entityType, cmd.getUuid()); + return new Answer(cmd, exists, "Check if entity with UUID " + cmd.getUuid() + " of type " + entityType + " exists"); + } catch (ExecutionException | ConfigurationException e) { + s_logger.error("Failure during " + cmd + " on Nuage VSD " + _hostName, e); + return new Answer(cmd, e); + } + } + protected void isNuageVspApiLoaded() throws ConfigurationException { if (!_isNuageVspClientLoaded || _nuageVspApiClient == null) { throw new ConfigurationException(NUAGE_VSP_PLUGIN_ERROR_MESSAGE); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java index 6b0e26e..b1db4fb 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspEntityBuilder.java @@ -21,6 +21,7 @@ package com.cloud.util; import com.cloud.dc.VlanVO; import com.cloud.dc.dao.VlanDao; +import com.cloud.dc.dao.VlanDetailsDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -88,6 +89,8 @@ public class NuageVspEntityBuilder { @Inject VlanDao _vlanDao; @Inject + VlanDetailsDao _vlanDetailsDao; + @Inject ConfigurationDao _configurationDao; @Inject IPAddressDao _ipAddressDao; @@ -291,7 +294,8 @@ public class NuageVspEntityBuilder { .oneToOneNat(staticNatIp.isOneToOneNat()) .vlanUuid(staticNatVlan.getUuid()) .vlanGateway(staticNatVlan.getVlanGateway()) - .vlanNetmask(staticNatVlan.getVlanNetmask()); + .vlanNetmask(staticNatVlan.getVlanNetmask()) + .vlanUnderlay(NuageVspUtil.isUnderlayEnabledForVlan(_vlanDetailsDao, staticNatVlan)); if (nic != null) { VspNic vspNic = buildVspNic(nic); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java index fedf048..7eff324 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/util/NuageVspUtil.java @@ -19,6 +19,9 @@ package com.cloud.util; +import com.cloud.dc.Vlan; +import com.cloud.dc.VlanDetailsVO; +import com.cloud.dc.dao.VlanDetailsDao; import com.cloud.network.Network; import com.cloud.network.dao.NetworkDetailVO; import com.cloud.network.dao.NetworkDetailsDao; @@ -58,4 +61,9 @@ public class NuageVspUtil { byte[] passwordBytes = Base64.decodeBase64(encodedPasswordBytes); return new String(passwordBytes, StringUtils.getPreferredCharset()); } + + public static boolean isUnderlayEnabledForVlan(VlanDetailsDao vlanDetailsDao, Vlan vlan) { + VlanDetailsVO nuageUnderlayDetail = vlanDetailsDao.findDetail(vlan.getId(), NuageVspManager.nuageUnderlayVlanIpRangeDetailKey); + return nuageUnderlayDetail != null && nuageUnderlayDetail.getValue().equalsIgnoreCase(String.valueOf(true)); + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/test/com/cloud/agent/api/CommandsTest.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/agent/api/CommandsTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/agent/api/CommandsTest.java index 2a0b07a..03fe5eb 100644 --- a/plugins/network-elements/nuage-vsp/test/com/cloud/agent/api/CommandsTest.java +++ b/plugins/network-elements/nuage-vsp/test/com/cloud/agent/api/CommandsTest.java @@ -19,6 +19,17 @@ package com.cloud.agent.api; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +import com.google.common.collect.Maps; +import com.google.common.testing.EqualsTester; +import com.google.gson.Gson; + import com.cloud.agent.api.element.ApplyAclRuleVspCommand; import com.cloud.agent.api.element.ApplyStaticNatVspCommand; import com.cloud.agent.api.element.ImplementVspCommand; @@ -27,71 +38,76 @@ import com.cloud.agent.api.guru.DeallocateVmVspCommand; import com.cloud.agent.api.guru.ImplementNetworkVspCommand; import com.cloud.agent.api.guru.ReserveVmInterfaceVspCommand; import com.cloud.agent.api.guru.TrashNetworkVspCommand; +import com.cloud.agent.api.manager.EntityExistsCommand; import com.cloud.agent.api.manager.SupportedApiVersionCommand; import com.cloud.agent.api.sync.SyncDomainCommand; import com.cloud.agent.api.sync.SyncNuageVspCmsIdCommand; -import com.google.common.collect.Maps; -import com.google.common.testing.EqualsTester; -import org.junit.Test; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; +import com.cloud.serializer.GsonHelper; public class CommandsTest { + private static final Gson s_gson = GsonHelper.getGson(); + + private EqualsTester tester = new EqualsTester(); @Test public void testCommandEquals() throws IllegalAccessException, InvocationTargetException, InstantiationException { - ApplyAclRuleVspCommand applyAclRuleVspCommand = fillObject(ApplyAclRuleVspCommand.class); - ApplyAclRuleVspCommand otherApplyAclRuleVspCommand = fillObject(ApplyAclRuleVspCommand.class); - - ApplyStaticNatVspCommand applyStaticNatVspCommand = fillObject(ApplyStaticNatVspCommand.class); - ApplyStaticNatVspCommand otherApplyStaticNatVspCommand = fillObject(ApplyStaticNatVspCommand.class); - - ImplementVspCommand implementVspCommand = fillObject(ImplementVspCommand.class); - ImplementVspCommand otherImplementVspCommand = fillObject(ImplementVspCommand.class); - - ShutDownVpcVspCommand shutDownVpcVspCommand = fillObject(ShutDownVpcVspCommand.class); - ShutDownVpcVspCommand otherShutDownVpcVspCommand = fillObject(ShutDownVpcVspCommand.class); - - DeallocateVmVspCommand deallocateVmVspCommand = fillObject(DeallocateVmVspCommand.class); - DeallocateVmVspCommand otherDeallocateVmVspCommand = fillObject(DeallocateVmVspCommand.class); - - ImplementNetworkVspCommand implementNetworkVspCommand = fillObject(ImplementNetworkVspCommand.class); - ImplementNetworkVspCommand otherImplementNetworkVspCommand = fillObject(ImplementNetworkVspCommand.class); - - ReserveVmInterfaceVspCommand reserveVmInterfaceVspCommand = fillObject(ReserveVmInterfaceVspCommand.class); - ReserveVmInterfaceVspCommand otherReserveVmInterfaceVspCommand = fillObject(ReserveVmInterfaceVspCommand.class); - - TrashNetworkVspCommand trashNetworkVspCommand = fillObject(TrashNetworkVspCommand.class); - TrashNetworkVspCommand otherTrashNetworkVspCommand = fillObject(TrashNetworkVspCommand.class); - - SupportedApiVersionCommand supportedApiVersionCommand = new SupportedApiVersionCommand("3.2"); - SupportedApiVersionCommand otherSupportedApiVersionCommand = new SupportedApiVersionCommand("3.2"); + addCommandEqualityGroup(ApplyAclRuleVspCommand.class); + addCommandEqualityGroup(ImplementVspCommand.class); + addCommandEqualityGroup(ApplyStaticNatVspCommand.class); + addCommandEqualityGroup(ShutDownVpcVspCommand.class); + addCommandEqualityGroup(DeallocateVmVspCommand.class); + addCommandEqualityGroup(ImplementNetworkVspCommand.class); + addCommandEqualityGroup(ReserveVmInterfaceVspCommand.class); + addCommandEqualityGroup(TrashNetworkVspCommand.class); + addCommandEqualityGroup(SyncDomainCommand.class); + addCommandEqualityGroup(SyncNuageVspCmsIdCommand.class); + addCommandEqualityGroup(PingNuageVspCommand.class); + + SupportedApiVersionCommand supportedApiVersionCommandA = new SupportedApiVersionCommand("3.2"); + SupportedApiVersionCommand supportedApiVersionCommandB = new SupportedApiVersionCommand("3.2"); + + EntityExistsCommand entityExistsCommandA = new EntityExistsCommand(Command.class, "uuid"); + EntityExistsCommand entityExistsCommandB = new EntityExistsCommand(Command.class, "uuid"); + + tester + .addEqualityGroup(supportedApiVersionCommandA, supportedApiVersionCommandB) + .addEqualityGroup(entityExistsCommandA, entityExistsCommandB) + .testEquals(); + } - SyncDomainCommand syncDomainCommand = fillObject(SyncDomainCommand.class); - SyncDomainCommand otherSyncDomainCommand = fillObject(SyncDomainCommand.class); + @Test + public void testCommandGsonEquals() throws IllegalAccessException, InvocationTargetException, InstantiationException { + addCommandGsonEqualityGroup(ApplyAclRuleVspCommand.class); + addCommandGsonEqualityGroup(ImplementVspCommand.class); + addCommandGsonEqualityGroup(ApplyStaticNatVspCommand.class); + addCommandGsonEqualityGroup(ShutDownVpcVspCommand.class); + addCommandGsonEqualityGroup(DeallocateVmVspCommand.class); + addCommandGsonEqualityGroup(ImplementNetworkVspCommand.class); + addCommandGsonEqualityGroup(ReserveVmInterfaceVspCommand.class); + addCommandGsonEqualityGroup(TrashNetworkVspCommand.class); + addCommandGsonEqualityGroup(new SupportedApiVersionCommand("3.2")); + addCommandGsonEqualityGroup(SyncDomainCommand.class); + addCommandGsonEqualityGroup(SyncNuageVspCmsIdCommand.class); + addCommandGsonEqualityGroup(PingNuageVspCommand.class); + addCommandGsonEqualityGroup(new EntityExistsCommand(Command.class, "uuid")); + + tester.testEquals(); + } - SyncNuageVspCmsIdCommand syncNuageVspCmsIdCommand = fillObject(SyncNuageVspCmsIdCommand.class); - SyncNuageVspCmsIdCommand otherSyncNuageVspCmsIdCommand = fillObject(SyncNuageVspCmsIdCommand.class); + private <T extends Command> void addCommandGsonEqualityGroup(Class<T> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException{ + addCommandGsonEqualityGroup(fillObject(clazz)); + } - PingNuageVspCommand pingNuageVspCommand = fillObject(PingNuageVspCommand.class); - PingNuageVspCommand otherPingNuageVspCommand = fillObject(PingNuageVspCommand.class); + private <T extends Command> void addCommandGsonEqualityGroup(Command command) throws IllegalAccessException, InvocationTargetException, InstantiationException{ + Command[] forwardedCommands = s_gson.fromJson(s_gson.toJson(new Command[] { command }), Command[].class); + Assert.assertEquals(command, forwardedCommands[0]); + tester.addEqualityGroup(command, forwardedCommands[0]); + } - new EqualsTester() - .addEqualityGroup(applyAclRuleVspCommand, otherApplyAclRuleVspCommand) - .addEqualityGroup(applyStaticNatVspCommand, otherApplyStaticNatVspCommand) - .addEqualityGroup(implementVspCommand, otherImplementVspCommand) - .addEqualityGroup(shutDownVpcVspCommand, otherShutDownVpcVspCommand) - .addEqualityGroup(deallocateVmVspCommand, otherDeallocateVmVspCommand) - .addEqualityGroup(implementNetworkVspCommand, otherImplementNetworkVspCommand) - .addEqualityGroup(reserveVmInterfaceVspCommand, otherReserveVmInterfaceVspCommand) - .addEqualityGroup(trashNetworkVspCommand, otherTrashNetworkVspCommand) - .addEqualityGroup(supportedApiVersionCommand, otherSupportedApiVersionCommand) - .addEqualityGroup(syncDomainCommand, otherSyncDomainCommand) - .addEqualityGroup(syncNuageVspCmsIdCommand, otherSyncNuageVspCmsIdCommand) - .addEqualityGroup(pingNuageVspCommand, otherPingNuageVspCommand) - .testEquals(); + private <T extends Command> void addCommandEqualityGroup(Class<T> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException { + Command a = fillObject(clazz); + Command b = fillObject(clazz); + tester.addEqualityGroup(a, b); } private <T> T fillObject(Class<T> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java index 929aba7..aad6398 100644 --- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java +++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/element/NuageVspElementTest.java @@ -113,6 +113,9 @@ public class NuageVspElementTest extends NuageTest { public void setUp() throws Exception { super.setUp(); _nuageVspElement._nuageVspEntityBuilder = _nuageVspEntityBuilder; + when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.Connectivity, Provider.NuageVsp)).thenReturn(true); + when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.SourceNat, Provider.NuageVsp)).thenReturn(true); + _nuageVspElement.configure("NuageVspTestElement", Collections.<String, Object>emptyMap()); } @@ -128,7 +131,6 @@ public class NuageVspElementTest extends NuageTest { when(ntwkoffer.getIsPersistent()).thenReturn(true); when(_networkOfferingDao.findById(NETWORK_ID)).thenReturn(ntwkoffer); - when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.Connectivity, Provider.NuageVsp)).thenReturn(true); // Golden path assertTrue(_nuageVspElement.canHandle(net, Service.Connectivity)); @@ -162,7 +164,6 @@ public class NuageVspElementTest extends NuageTest { when(network.getPhysicalNetworkId()).thenReturn(NETWORK_ID); when(network.getDomainId()).thenReturn(NETWORK_ID); when(_networkModel.isProviderForNetwork(Provider.NuageVsp, NETWORK_ID)).thenReturn(true); - when(_networkServiceMapDao.canProviderSupportServiceInNetwork(NETWORK_ID, Service.Connectivity, Provider.NuageVsp)).thenReturn(true); final NetworkOffering offering = mock(NetworkOffering.class); when(offering.getId()).thenReturn(NETWORK_ID); @@ -186,6 +187,7 @@ public class NuageVspElementTest extends NuageTest { when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); when(_firewallRulesDao.listByNetworkPurposeTrafficType(NETWORK_ID, FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Ingress)).thenReturn(new ArrayList<FirewallRuleVO>()); when(_firewallRulesDao.listByNetworkPurposeTrafficType(NETWORK_ID, FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Egress)).thenReturn(new ArrayList<FirewallRuleVO>()); @@ -235,6 +237,7 @@ public class NuageVspElementTest extends NuageTest { when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); when(_domainDao.findById(NETWORK_ID)).thenReturn(mock(DomainVO.class)); final Answer answer = mock(Answer.class); @@ -263,6 +266,7 @@ public class NuageVspElementTest extends NuageTest { when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); when(_domainDao.findById(NETWORK_ID)).thenReturn(mock(DomainVO.class)); @@ -292,6 +296,7 @@ public class NuageVspElementTest extends NuageTest { when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(new NuageVspDeviceVO[]{nuageVspDevice})); when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); when(_domainDao.findById(NETWORK_ID)).thenReturn(mock(DomainVO.class)); final Answer answer = mock(Answer.class); @@ -329,6 +334,7 @@ public class NuageVspElementTest extends NuageTest { when(nuageVspDevice.getHostId()).thenReturn(NETWORK_ID); when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Lists.newArrayList(nuageVspDevice)); when(_hostDao.findById(NETWORK_ID)).thenReturn(host); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); DomainRouterVO domainRouter = mock(DomainRouterVO.class); when(domainRouter.getUuid()).thenReturn("aaaaaa"); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8d4dc812/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java b/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java index d0de447..fdfc4d5 100644 --- a/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java +++ b/plugins/network-elements/nuage-vsp/test/com/cloud/network/guru/NuageVspGuestNetworkGuruTest.java @@ -144,6 +144,7 @@ public class NuageVspGuestNetworkGuruTest extends NuageTest { when(_hostDao.findById(NETWORK_ID)).thenReturn(host); when(host.getId()).thenReturn(NETWORK_ID); when(_agentManager.easySend(eq(NETWORK_ID), any(Command.class))).thenReturn(new Answer(null)); + when(_nuageVspManager.getNuageVspHost(NETWORK_ID)).thenReturn(host); final NuageVspDeviceVO device = mock(NuageVspDeviceVO.class); when(_nuageVspDao.listByPhysicalNetwork(NETWORK_ID)).thenReturn(Arrays.asList(device)); @@ -158,7 +159,8 @@ public class NuageVspGuestNetworkGuruTest extends NuageTest { when(offering.getIsPersistent()).thenReturn(false); when(_configurationManager.isOfferingForVpc(any(NetworkOffering.class))).thenReturn(false); - when(_networkOfferingServiceMapDao.areServicesSupportedByNetworkOffering(NETWORK_ID, Service.Connectivity)).thenReturn(true); + when(_networkOfferingServiceMapDao.canProviderSupportServiceInNetworkOffering(NETWORK_ID, Service.Connectivity, Network.Provider.NuageVsp)).thenReturn(true); + when(_networkOfferingServiceMapDao.canProviderSupportServiceInNetworkOffering(NETWORK_ID, Service.SourceNat, Network.Provider.NuageVsp)).thenReturn(true); when(offering.getTrafficType()).thenReturn(TrafficType.Guest); when(offering.getGuestType()).thenReturn(GuestType.Isolated); @@ -199,7 +201,8 @@ public class NuageVspGuestNetworkGuruTest extends NuageTest { when(offering.getIsPersistent()).thenReturn(false); when(_configurationManager.isOfferingForVpc(any(NetworkOffering.class))).thenReturn(false); - when(_networkOfferingServiceMapDao.areServicesSupportedByNetworkOffering(NETWORK_ID, Service.Connectivity)).thenReturn(true); + when(_networkOfferingServiceMapDao.canProviderSupportServiceInNetworkOffering(NETWORK_ID, Service.Connectivity, Network.Provider.NuageVsp)).thenReturn(true); + when(_networkOfferingServiceMapDao.canProviderSupportServiceInNetworkOffering(NETWORK_ID, Service.SourceNat, Network.Provider.NuageVsp)).thenReturn(true); final DeploymentPlan plan = mock(DeploymentPlan.class); final Network network = mock(Network.class);
