Add support to add and delete and update static routes on Netris (#37)

* Add support to add static routes in Netris

* support to delete static routes on netris

* add defensive check for nextHop

* Add support to update static routes

* add state

* pass empty list for switched to avoid timeout

* Netris: search static route by name and next hop if exists

---------

Co-authored-by: Wei Zhou <weizhou@apache.org>
This commit is contained in:
Pearl Dsilva 2024-12-20 07:22:04 -05:00 committed by GitHub
parent bbb7acccbe
commit 5ac35a2d8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 335 additions and 2 deletions

View File

@ -22,14 +22,28 @@ import com.cloud.network.vpc.Vpc;
public interface NetrisService {
boolean createIPAMAllocationsForZoneLevelPublicRanges(long zoneId);
boolean createVpcResource(long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled, String cidr, boolean isVpcNetwork);
boolean deleteVpcResource(long zoneId, long accountId, long domainId, Vpc vpc);
boolean createVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr);
boolean deleteVnetResource(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr);
boolean createSnatRule(long zoneId, long accountId, long domainId, String vpcName, long vpcId, String networkName, long networkId, boolean isForVpc, String vpcCidr, String sourceNatIp);
boolean createPortForwardingRule(long zoneId, long accountId, long domainId, String vpcName, long vpcId, String networkName, Long networkId, boolean isForVpc, String vpcCidr, SDNProviderNetworkRule networkRule);
boolean deletePortForwardingRule(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, boolean isForVpc, String vpcCidr, SDNProviderNetworkRule networkRule);
boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
boolean createStaticNatRule(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String vpcCidr, String staticNatIp, String vmIp);
boolean deleteStaticNatRule(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String staticNatIp);
boolean addOrUpdateStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId, boolean updateRoute);
boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId);
}

View File

@ -25,6 +25,7 @@ public interface StaticRoute extends ControlledEntity, Identity, InternalIdentit
Staged, // route been created but has never got through network rule conflict detection. Routes in this state can not be sent to VPC virtual router.
Add, // Add means the route has been created and has gone through network rule conflict detection.
Active, // Route has been sent to the VPC router and reported to be active.
Update,
Revoke, // Revoke means this route has been revoked. If this route has been sent to the VPC router, the route will be deleted from database.
Deleting // rule has been revoked and is scheduled for deletion
}

View File

@ -0,0 +1,48 @@
// 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.agent.api;
public class AddOrUpdateNetrisStaticRouteCommand extends NetrisCommand {
private String prefix;
private String nextHop;
private Long routeId;
private boolean updateRoute;
public AddOrUpdateNetrisStaticRouteCommand(long zoneId, Long accountId, Long domainId, String name, Long id, boolean isVpc, String prefix, String nextHop, Long routeId, boolean updateRoute) {
super(zoneId, accountId, domainId, name, id, isVpc);
this.prefix = prefix;
this.nextHop = nextHop;
this.routeId = routeId;
this.updateRoute = updateRoute;
}
public String getPrefix() {
return prefix;
}
public String getNextHop() {
return nextHop;
}
public Long getRouteId() {
return routeId;
}
public boolean isUpdateRoute() {
return updateRoute;
}
}

View File

@ -0,0 +1,23 @@
// 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.agent.api;
public class DeleteNetrisStaticRouteCommand extends AddOrUpdateNetrisStaticRouteCommand {
public DeleteNetrisStaticRouteCommand(long zoneId, Long accountId, Long domainId, String name, Long id, boolean isVpc, String prefix, String nextHop, Long routeId) {
super(zoneId, accountId, domainId, name, id, isVpc, prefix, nextHop, routeId, false);
}
}

View File

@ -28,10 +28,12 @@ import com.cloud.agent.api.StartupCommand;
import com.cloud.host.Host;
import com.cloud.resource.ServerResource;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.NetrisAnswer;
@ -102,7 +104,11 @@ public class NetrisResource implements ServerResource {
} else if (cmd instanceof DeleteNetrisNatRuleCommand) {
return executeRequest((DeleteNetrisNatRuleCommand) cmd);
} else if (cmd instanceof CreateOrUpdateNetrisNatCommand) {
return executeRequest((CreateOrUpdateNetrisNatCommand) cmd);
return executeRequest((CreateOrUpdateNetrisNatCommand) cmd);
} else if (cmd instanceof DeleteNetrisStaticRouteCommand) {
return executeRequest((DeleteNetrisStaticRouteCommand) cmd);
} else if (cmd instanceof AddOrUpdateNetrisStaticRouteCommand) {
return executeRequest((AddOrUpdateNetrisStaticRouteCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -297,6 +303,22 @@ public class NetrisResource implements ServerResource {
return new NetrisAnswer(cmd, true, "OK");
}
private Answer executeRequest(AddOrUpdateNetrisStaticRouteCommand cmd) {
boolean result = netrisApiClient.addOrUpdateStaticRoute(cmd);
if (!result) {
return new NetrisAnswer(cmd, false, String.format("Failed to add static route for VPC: %s, prefix: %s, nextHop: %s ", cmd.getName(), cmd.getPrefix(), cmd.getNextHop()));
}
return new NetrisAnswer(cmd, true, "OK");
}
private Answer executeRequest(DeleteNetrisStaticRouteCommand cmd) {
boolean result = netrisApiClient.deleteStaticRoute(cmd);
if (!result) {
return new NetrisAnswer(cmd, false, String.format("Failed to add static route for VPC: %s, prefix: %s, nextHop: %s ", cmd.getName(), cmd.getPrefix(), cmd.getNextHop()));
}
return new NetrisAnswer(cmd, true, "OK");
}
@Override
public boolean start() {
return true;

View File

@ -22,7 +22,7 @@ import org.apache.commons.lang3.ArrayUtils;
public class NetrisResourceObjectUtils {
public enum NetrisObjectType {
VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET, SNAT, STATICNAT, DNAT
VPC, IPAM_ALLOCATION, IPAM_SUBNET, VNET, SNAT, STATICNAT, DNAT, STATICROUTE
}
public static String retrieveNetrisResourceObjectName(NetrisCommand cmd, NetrisObjectType netrisObjectType, String... suffixes) {
@ -72,6 +72,10 @@ public class NetrisResourceObjectUtils {
stringBuilder.append(String.format("%s%s-%s", prefix, suffixes[0], "DNAT"));
suffixes = ArrayUtils.subarray(suffixes, 1, suffixes.length);
break;
case STATICROUTE:
stringBuilder.append(String.format("%s%s-%s%s", prefix, suffixes[0], "ROUTE", suffixes[1]));
suffixes = new String[0];
break;
case VNET:
break;
default:

View File

@ -20,10 +20,12 @@ import io.netris.ApiException;
import io.netris.model.GetSiteBody;
import io.netris.model.VPCListing;
import io.netris.model.response.TenantResponse;
import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
@ -74,4 +76,6 @@ public interface NetrisApiClient {
boolean createOrUpdateDNATRule(CreateOrUpdateNetrisNatCommand cmd);
boolean createStaticNatRule(CreateOrUpdateNetrisNatCommand cmd);
boolean deleteNatRule(DeleteNetrisNatRuleCommand cmd);
boolean addOrUpdateStaticRoute(AddOrUpdateNetrisStaticRouteCommand cmd);
boolean deleteStaticRoute(DeleteNetrisStaticRouteCommand cmd);
}

View File

@ -22,6 +22,7 @@ import io.netris.ApiClient;
import io.netris.ApiException;
import io.netris.ApiResponse;
import io.netris.api.v1.AuthenticationApi;
import io.netris.api.v1.RoutesApi;
import io.netris.api.v1.SitesApi;
import io.netris.api.v1.TenantsApi;
import io.netris.api.v2.IpamApi;
@ -35,6 +36,7 @@ import io.netris.model.FilterByVpc;
import io.netris.model.GetSiteBody;
import io.netris.model.InlineResponse20015;
import io.netris.model.InlineResponse20016;
import io.netris.model.InlineResponse2003;
import io.netris.model.InlineResponse2004;
import io.netris.model.InlineResponse2004Data;
import io.netris.model.IpTree;
@ -48,6 +50,13 @@ import io.netris.model.NatGetBody;
import io.netris.model.NatPostBody;
import io.netris.model.NatPutBody;
import io.netris.model.NatResponseGetOk;
import io.netris.model.RoutesBody;
import io.netris.model.RoutesBodyId;
import io.netris.model.RoutesBodyVpcVpc;
import io.netris.model.RoutesGetBody;
import io.netris.model.RoutesPostBody;
import io.netris.model.RoutesPutBody;
import io.netris.model.RoutesResponseGetOk;
import io.netris.model.SitesResponseOK;
import io.netris.model.SubnetBody;
import io.netris.model.SubnetResBody;
@ -71,10 +80,12 @@ import io.netris.model.VnetsBody;
import io.netris.model.response.AuthResponse;
import io.netris.model.response.TenantResponse;
import io.netris.model.response.TenantsResponse;
import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.SetupNetrisPublicRangeCommand;
@ -283,6 +294,176 @@ public class NetrisApiClientImpl implements NetrisApiClient {
return true;
}
@Override
public boolean addOrUpdateStaticRoute(AddOrUpdateNetrisStaticRouteCommand cmd) {
String prefix = cmd.getPrefix();
String nextHop = cmd.getNextHop();
Long vpcId = cmd.getId();
String vpcName = cmd.getName();
boolean updateRoute = cmd.isUpdateRoute();
try {
String vpcSuffix = getNetrisVpcNameSuffix(vpcId, vpcName, null, null, true);
String netrisVpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC, vpcSuffix);
VPCListing vpcResource = getVpcByNameAndTenant(netrisVpcName);
if (vpcResource == null) {
logger.error("Could not find the Netris VPC resource with name {} and tenant ID {}", netrisVpcName, tenantId);
return false;
}
String[] suffixes = new String[2];
suffixes[0] = vpcId.toString();
suffixes[1] = cmd.getRouteId().toString();
String staticRouteId = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC, suffixes);
Pair<Boolean, RoutesGetBody> existingStaticRoute = staticRouteExists(vpcResource.getId(), prefix, null, staticRouteId);
if (updateRoute) {
if (!existingStaticRoute.first()) {
logger.error("The Netris static route {} does not exist for VPC {}", prefix, netrisVpcName);
return false;
}
return updateStaticRouteInternal(existingStaticRoute.second().getId(), netrisVpcName, prefix, nextHop, staticRouteId);
} else {
if (existingStaticRoute.first()) {
String existingNextHop = existingStaticRoute.second().getNextHop();
if (existingNextHop != null && existingNextHop.equals(nextHop)) {
logger.debug("The Netris static route {} already exists for VPC {}", prefix, netrisVpcName);
return true;
} else {
logger.debug("The Netris static route {} already exists but has different next hop {} for VPC {}", prefix, nextHop, netrisVpcName);
return false;
}
}
return addStaticRouteInternal(vpcResource, netrisVpcName, prefix, nextHop, staticRouteId);
}
} catch (Exception e) {
throw new CloudRuntimeException("Error adding Netris static route", e);
}
}
private boolean addStaticRouteInternal(VPCListing vpcResource, String netrisVpcName, String prefix, String nextHop, String staticRouteId) {
try {
RoutesApi routesApi = apiClient.getApiStubForMethod(RoutesApi.class);
RoutesPostBody routesPostBody = new RoutesPostBody();
routesPostBody.setPrefix(prefix);
routesPostBody.setNextHop(nextHop);
routesPostBody.setSiteId(new BigDecimal(siteId));
routesPostBody.setStateStatus(RoutesBody.StateStatusEnum.ACTIVE);
RoutesBodyVpcVpc vpcBody = new RoutesBodyVpcVpc();
vpcBody.setId(vpcResource.getId());
vpcBody.setName(vpcResource.getName());
vpcBody.setIsDefault(vpcResource.isIsDefault());
vpcBody.setIsSystem(vpcResource.isIsSystem());
routesPostBody.setVpc(vpcBody);
routesPostBody.setDescription(staticRouteId);
routesPostBody.setStateStatus(RoutesBody.StateStatusEnum.ACTIVE);
routesPostBody.setSwitches(Collections.emptyList());
InlineResponse2004 routeResponse = routesApi.apiRoutesPost(routesPostBody);
if (routeResponse == null || !routeResponse.isIsSuccess()) {
String reason = routeResponse == null ? "Empty response" : "Operation failed on Netris";
logger.debug("The Netris static route creation failed for netris VPC - {}: {}", netrisVpcName, reason);
throw new CloudRuntimeException(reason);
}
} catch (ApiException e) {
logAndThrowException("Error adding Netris static route", e);
return false;
}
return true;
}
private boolean updateStaticRouteInternal(Integer id, String netrisVpcName, String prefix, String nextHop, String staticRouteId) {
try {
RoutesApi routesApi = apiClient.getApiStubForMethod(RoutesApi.class);
RoutesPutBody routesPutBody = new RoutesPutBody();
routesPutBody.setId(id);
routesPutBody.setPrefix(prefix);
routesPutBody.setNextHop(nextHop);
routesPutBody.setSiteId(new BigDecimal(siteId));
routesPutBody.setDescription(staticRouteId);
routesPutBody.setSwitches(Collections.emptyList());
InlineResponse2003 routeResponse = routesApi.apiRoutesPut(routesPutBody);
if (routeResponse == null || !routeResponse.isIsSuccess()) {
String reason = routeResponse == null ? "Empty response" : "Operation failed on Netris";
logger.debug("Failed to update Netris static route for netris VPC - {}: {}", netrisVpcName, reason);
throw new CloudRuntimeException(reason);
}
} catch (ApiException e) {
logAndThrowException("Error updating Netris static route", e);
return false;
}
return true;
}
@Override
public boolean deleteStaticRoute(DeleteNetrisStaticRouteCommand cmd) {
Long vpcId = cmd.getId();
String vpcName = cmd.getName();
String prefix = cmd.getPrefix();
String nextHop = cmd.getNextHop();
try {
String vpcSuffix = getNetrisVpcNameSuffix(vpcId, vpcName, null, null, true);
String netrisVpcName = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC, vpcSuffix);
VPCListing vpcResource = getVpcByNameAndTenant(netrisVpcName);
if (vpcResource == null) {
logger.error("Could not find the Netris VPC resource with name {} and tenant ID {}", netrisVpcName, tenantId);
return false;
}
String[] suffixes = new String[2];
suffixes[0] = vpcId.toString();
suffixes[1] = cmd.getRouteId().toString();
String staticRouteId = NetrisResourceObjectUtils.retrieveNetrisResourceObjectName(cmd, NetrisResourceObjectUtils.NetrisObjectType.VPC, suffixes);
Pair<Boolean, RoutesGetBody> existingStaticRoute = staticRouteExists(vpcResource.getId(), prefix, nextHop, staticRouteId);
if (Boolean.FALSE.equals(existingStaticRoute.first())) {
logger.debug("The Netris static route {} does not exist for VPC {}", prefix, netrisVpcName);
return true;
}
RoutesGetBody existingRoute = existingStaticRoute.second();
RoutesApi routesApi = apiClient.getApiStubForMethod(RoutesApi.class);
RoutesBodyId id = new RoutesBodyId();
id.setId(existingRoute.getId());
InlineResponse2003 routeDeleteResponse = routesApi.apiRoutesDelete(id);
if (routeDeleteResponse == null || !routeDeleteResponse.isIsSuccess()) {
String reason = routeDeleteResponse == null ? "Empty response" : "Operation failed on Netris";
logger.debug("The Netris static route deletion failed for netris VPC - {}: {}", netrisVpcName, reason);
throw new CloudRuntimeException(reason);
}
return true;
} catch (ApiException e) {
logAndThrowException("Error deleting Netris static route", e);
}
return false;
}
private Pair<Boolean, RoutesGetBody> staticRouteExists(Integer netrisVpcId, String prefix, String nextHop, String description) {
try {
FilterByVpc vpcFilter = new FilterByVpc();
vpcFilter.add(netrisVpcId);
FilterBySites sitesFilter = new FilterBySites();
sitesFilter.add(siteId);
RoutesApi routesApi = apiClient.getApiStubForMethod(RoutesApi.class);
RoutesResponseGetOk routesResponseGetOk = routesApi.apiRoutesGet(sitesFilter, vpcFilter);
if (Objects.isNull(routesResponseGetOk) || Boolean.FALSE.equals(routesResponseGetOk.isIsSuccess())) {
logger.warn("Failed to retrieve static routes");
return new Pair<>(false, null);
}
List<RoutesGetBody> routesList = routesResponseGetOk.getData();
List<RoutesGetBody> filteredList = routesList.stream()
.filter(x -> x.getName().equals(prefix) &&
(Objects.isNull(nextHop) || x.getNextHop().equals(nextHop)))
.collect(Collectors.toList());
return new Pair<>(!filteredList.isEmpty(), filteredList.isEmpty() ? null : filteredList.get(0));
} catch (ApiException e) {
logAndThrowException("Error checking Netris static routes", e);
}
return new Pair<>(false, null);
}
private void deleteNatSubnet(Integer netrisVpcId, String natIp) {
FilterByVpc vpcFilter = new FilterByVpc();
vpcFilter.add(netrisVpcId);

View File

@ -61,6 +61,7 @@ import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNat;
import com.cloud.network.vpc.NetworkACLItem;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.StaticRoute;
import com.cloud.network.vpc.StaticRouteProfile;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcVO;
@ -410,6 +411,15 @@ public class NetrisElement extends AdapterBase implements DhcpServiceProvider, D
@Override
public boolean applyStaticRoutes(Vpc vpc, List<StaticRouteProfile> routes) throws ResourceUnavailableException {
for(StaticRouteProfile staticRoute : routes) {
if (StaticRoute.State.Add == staticRoute.getState()) {
netrisService.addOrUpdateStaticRoute(vpc.getZoneId(), vpc.getAccountId(), vpc.getDomainId(), vpc.getName(), vpc.getId(), true, staticRoute.getCidr(), staticRoute.getGateway(), staticRoute.getId(), false);
} else if (StaticRoute.State.Revoke == staticRoute.getState()) {
netrisService.deleteStaticRoute(vpc.getZoneId(), vpc.getAccountId(), vpc.getDomainId(), vpc.getName(), vpc.getId(), true, staticRoute.getCidr(), staticRoute.getGateway(), staticRoute.getId());
} else if (StaticRoute.State.Update == staticRoute.getState()) {
netrisService.addOrUpdateStaticRoute(vpc.getZoneId(), vpc.getAccountId(), vpc.getDomainId(), vpc.getName(), vpc.getId(), true, staticRoute.getCidr(), staticRoute.getGateway(), staticRoute.getId(), true);
}
}
return true;
}

View File

@ -42,10 +42,12 @@ import com.cloud.utils.net.NetUtils;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressString;
import io.netris.model.NatPostBody;
import org.apache.cloudstack.agent.api.AddOrUpdateNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVnetCommand;
import org.apache.cloudstack.agent.api.CreateNetrisVpcCommand;
import org.apache.cloudstack.agent.api.CreateOrUpdateNetrisNatCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisNatRuleCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisStaticRouteCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVnetCommand;
import org.apache.cloudstack.agent.api.DeleteNetrisVpcCommand;
import org.apache.cloudstack.agent.api.NetrisAnswer;
@ -338,6 +340,20 @@ public class NetrisServiceImpl implements NetrisService, Configurable {
return answer.getResult();
}
@Override
public boolean addOrUpdateStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId, boolean updateRoute) {
AddOrUpdateNetrisStaticRouteCommand cmd = new AddOrUpdateNetrisStaticRouteCommand(zoneId, accountId, domainId, networkResourceName, networkResourceId, isForVpc, prefix, nextHop, routeId, updateRoute);
NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
return answer.getResult();
}
@Override
public boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId) {
DeleteNetrisStaticRouteCommand cmd = new DeleteNetrisStaticRouteCommand(zoneId, accountId, domainId, networkResourceName, networkResourceId, isForVpc, prefix, nextHop, routeId);
NetrisAnswer answer = sendNetrisCommand(cmd, zoneId);
return answer.getResult();
}
private String getResourceSuffix(Long vpcId, Long networkId, boolean isForVpc) {
String suffix;
if (isForVpc) {

View File

@ -76,4 +76,14 @@ public class NetrisServiceMockTest implements NetrisService {
public boolean deleteStaticNatRule(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String staticNatIp) {
return true;
}
@Override
public boolean addOrUpdateStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId, boolean updateRoute) {
return true;
}
@Override
public boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId) {
return true;
}
}