Skip to content

Commit

Permalink
Merge pull request futurewei-cloud#19 from kevin-zhonghao/feature/rou…
Browse files Browse the repository at this point in the history
…te_manager

subnet manager e2e update
  • Loading branch information
kevin-zhonghao committed Apr 20, 2020
2 parents 39f7d50 + ef723ba commit 090aa3a
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.futurewei.alcor.common.exception;

public class DatabaseAddException extends Exception {

public DatabaseAddException (String message) {
super(message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.futurewei.alcor.subnet.config;

public class ThreadPoolExecutorConfig {

public static int corePoolSize = 10;
public static int maximumPoolSize = 20;
public static int KeepAliveTime = 5000;
public static int capacity = 1024;

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public class UnitTestConfig {
public static String updateResource = "{\"subnet\":{\"project_id\":\"3dda2801-d675-4688-a63f-dcda8d327f50\",\"vpc_id\":\"9192a4d4-ffff-4ece-b3f0-8d36e3d88038\",\"id\":\"9192a4d4-ffff-4ece-b3f0-8d36e3d88000\",\"name\":\"update_subnet\",\"cidr\":\"10.0.0.0/16\"}}";
public static String exception = "Request processing failed; nested exception is java.lang.Exception: com.futurewei.alcor.common.exception.ResourceNotFoundException: Subnet not found : 9192a4d4-ffff-4ece-b3f0-8d36e3d88000";
public static String createException = "Request processing failed; nested exception is java.lang.Exception: java.util.concurrent.CompletionException: com.futurewei.alcor.common.exception.FallbackException: fallback request";
public static String createException2 = "Request processing failed; nested exception is java.lang.Exception: java.util.concurrent.CompletionException: java.util.concurrent.CompletionException: com.futurewei.alcor.common.exception.FallbackException: fallback request";
public static String macAddress = "00-AA-BB-CC-36-51";
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,30 @@ public SubnetStateJson createSubnetState(@PathVariable String projectid, @Reques

// TODO: Create a verification framework for all resources
SubnetState inSubnetState = resource.getSubnet();
RestPreconditionsUtil.verifyResourceFound(inSubnetState.getVpcId());
String subnetId = inSubnetState.getId();
String vpcId = inSubnetState.getVpcId();
RestPreconditionsUtil.verifyResourceFound(vpcId);
RestPreconditionsUtil.populateResourceProjectId(inSubnetState, projectid);

//Allocate Gateway Mac
CompletableFuture<MacStateJson> macFuture = CompletableFuture.supplyAsync(() -> {
try {
return this.subnetService.allocateMacGateway(projectid, inSubnetState.getVpcId(), portId);
return this.subnetService.allocateMacGateway(projectid, vpcId, portId);
} catch (Exception e) {
throw new CompletionException(e);
}
}, ThreadPoolExecutorUtils.SELECT_POOL_EXECUTOR).handle((s, e) -> {
macResponseAtomic.set(s);
if (e != null) {
throw new CompletionException(e);
}
return s;
});

// Verify VPC ID
CompletableFuture<VpcStateJson> vpcFuture = CompletableFuture.supplyAsync(() -> {
try {
return this.subnetService.verifyVpcId(projectid, inSubnetState.getVpcId());
return this.subnetService.verifyVpcId(projectid, vpcId);
} catch (Exception e) {
throw new CompletionException(e);
}
Expand All @@ -125,14 +130,17 @@ public SubnetStateJson createSubnetState(@PathVariable String projectid, @Reques
//Prepare Route Rule(IPv4/6) for Subnet
CompletableFuture<RouteWebJson> routeFuture = CompletableFuture.supplyAsync(() -> {
try {
return this.subnetService.createRouteRules(inSubnetState.getId(), inSubnetState);
return this.subnetService.createRouteRules(subnetId, inSubnetState);
} catch (Exception e) {
throw new CompletionException(e);
}
}, ThreadPoolExecutorUtils.SELECT_POOL_EXECUTOR).handle((s, e) -> {
routeResponseAtomic.set(s);
if (e != null) {
throw new CompletionException(e);
}
return s;
});;
});



Expand All @@ -151,51 +159,25 @@ public SubnetStateJson createSubnetState(@PathVariable String projectid, @Reques
logger.info("Total processing time:" + (System.currentTimeMillis() - start) + "ms");

// set up value of properties for subnetState
List<RouteWebObject> routes = inSubnetState.getRoutes();
if (routes == null) {
routes = new ArrayList<>();
}
List<RouteWebObject> routes = new ArrayList<>();
routes.add(routeResponse.getRoute());
inSubnetState.setRoutes(routes);
//subnetState.setGatewayIp(ipResponse.getIpState().getIp());

this.subnetDatabaseService.addSubnet(inSubnetState);

subnetState = this.subnetDatabaseService.getBySubnetId(inSubnetState.getId());
if (subnetState == null) {
throw new ResourcePersistenceException();
}
// subnetState = this.subnetDatabaseService.getBySubnetId(subnetId);
// if (SubnetState == null) {
// throw new ResourcePersistenceException();
// }

return new SubnetStateJson(subnetState);
return new SubnetStateJson(inSubnetState);

} catch (ResourcePersistenceException e) {
logger.error(e.getMessage());
throw new Exception(e);
} catch (CompletionException e) {
routeResponse = (RouteWebJson) routeResponseAtomic.get();
macResponse = (MacStateJson) macResponseAtomic.get();
logger.error(e.getMessage());

// Subnet fallback
logger.info("subnet fallback start");
this.subnetDatabaseService.deleteSubnet(resource.getSubnet().getId());
logger.info("subnet fallback end");

// Route fallback
logger.info("Route fallback start");
if (routeResponse != null) {
RouteWebObject route = routeResponse.getRoute();
this.subnetService.routeFallback(route.getId(), resource.getSubnet().getVpcId());
}
logger.info("Route fallback end");

// Mac fallback
logger.info("Mac fallback start");
if (macResponse != null) {
this.subnetService.macFallback(macResponse.getMacState().getMacAddress());
//this.subnetService.macFallback(UnitTestConfig.macAddress);
}
logger.info("Mac fallback end");
this.subnetService.fallbackOperation(routeResponseAtomic, macResponseAtomic, resource, e.getMessage());
throw new Exception(e);
} catch (DatabaseAddException e) {
this.subnetService.fallbackOperation(routeResponseAtomic, macResponseAtomic, resource, e.getMessage());
throw new Exception(e);
} catch (NullPointerException e) {
logger.error(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.futurewei.alcor.subnet.service;

import com.futurewei.alcor.common.exception.DatabaseAddException;
import com.futurewei.alcor.common.exception.ResourceNotFoundException;
import com.futurewei.alcor.common.exception.ResourcePersistenceException;
import com.futurewei.alcor.subnet.entity.SubnetState;
Expand All @@ -10,7 +11,7 @@ public interface SubnetDatabaseService {

public SubnetState getBySubnetId (String subnetId) throws ResourceNotFoundException, ResourcePersistenceException;
public Map getAllSubnets ();
public void addSubnet (SubnetState subnetState);
public void addSubnet (SubnetState subnetState) throws DatabaseAddException;
public void deleteSubnet (String id);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.futurewei.alcor.common.exception.ResourcePersistenceException;
import com.futurewei.alcor.subnet.entity.*;

import java.util.concurrent.atomic.AtomicReference;

public interface SubnetService {

// Subnet Route info Fallback
Expand All @@ -14,6 +16,12 @@ public interface SubnetService {
// Ip gateway Fallback
public void ipFallback (String ipGateway);

// Fallback operation
public void fallbackOperation (AtomicReference<RouteWebJson> routeResponseAtomic,
AtomicReference<MacStateJson> macResponseAtomic,
SubnetStateJson resource,
String message);

// Verify VPC ID
public VpcStateJson verifyVpcId (String projectId, String vpcId) throws Exception;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.futurewei.alcor.subnet.service.implement;

import com.futurewei.alcor.common.exception.DatabaseAddException;
import com.futurewei.alcor.subnet.dao.SubnetRedisRepository;
import com.futurewei.alcor.subnet.entity.SubnetState;
import com.futurewei.alcor.subnet.service.SubnetDatabaseService;
Expand Down Expand Up @@ -29,8 +30,12 @@ public Map getAllSubnets() {
}

@Override
public void addSubnet(SubnetState subnetState) {
this.subnetRedisRepository.addItem(subnetState);
public void addSubnet(SubnetState subnetState) throws DatabaseAddException {
try {
this.subnetRedisRepository.addItem(subnetState);
} catch (Exception e) {
throw new DatabaseAddException(e.getMessage());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,27 @@
import com.futurewei.alcor.common.exception.FallbackException;
import com.futurewei.alcor.common.exception.ResourcePersistenceException;
import com.futurewei.alcor.subnet.entity.*;
import com.futurewei.alcor.subnet.service.SubnetDatabaseService;
import com.futurewei.alcor.subnet.service.SubnetService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.atomic.AtomicReference;

@Service
public class SubnetServiceImp implements SubnetService {

private Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private SubnetDatabaseService subnetDatabaseService;

@Value("${microservices.vpc.service.url}")
private String vpcUrl;

Expand All @@ -29,28 +40,60 @@ public class SubnetServiceImp implements SubnetService {

private RestTemplate restTemplate = new RestTemplate();

@Async
@Override
public void routeFallback(String routeId, String vpcId) {
String routeManagerServiceUrl = routeUrl + "vpcs/" + vpcId + "/routes/" + routeId; // for kubernetes test
restTemplate.delete(routeManagerServiceUrl, ResponseId.class);
}

@Async
@Override
public void macFallback(String macAddress) {
String macManagerServiceUrl = macUrl + "/" + macAddress;
restTemplate.delete(macManagerServiceUrl, ResponseId.class);
}

@Async
@Override
public void ipFallback(String ipGateway) {
String ipManagerServiceUrl = ipUrl + ipGateway;
restTemplate.delete(ipManagerServiceUrl, ResponseId.class);
}

@Override
public void fallbackOperation(AtomicReference<RouteWebJson> routeResponseAtomic,
AtomicReference<MacStateJson> macResponseAtomic,
SubnetStateJson resource,
String message) {
RouteWebJson routeResponse = (RouteWebJson) routeResponseAtomic.get();
MacStateJson macResponse = (MacStateJson) macResponseAtomic.get();
logger.error(message);

// Subnet fallback
logger.info("subnet fallback start");
this.subnetDatabaseService.deleteSubnet(resource.getSubnet().getId());
logger.info("subnet fallback end");

// Route fallback
logger.info("Route fallback start");
if (routeResponse != null) {
RouteWebObject route = routeResponse.getRoute();
this.routeFallback(route.getId(), resource.getSubnet().getVpcId());
}
logger.info("Route fallback end");

// Mac fallback
logger.info("Mac fallback start");
if (macResponse != null) {
this.macFallback(macResponse.getMacState().getMacAddress());
}
logger.info("Mac fallback end");
}

@Override
public VpcStateJson verifyVpcId(String projectid, String vpcId) throws FallbackException {
String vpcManagerServiceUrl = vpcUrl + projectid + "/vpcs/" + vpcId; // for kubernetes test
//HttpEntity<SubnetStateJson> vpcRequest = new HttpEntity<>(new SubnetStateJson(subnetState));
String vpcManagerServiceUrl = vpcUrl + projectid + "/vpcs/" + vpcId;
VpcStateJson vpcResponse = restTemplate.getForObject(vpcManagerServiceUrl, VpcStateJson.class);
if (vpcResponse.getVpc() == null) {
throw new FallbackException("fallback request");
Expand All @@ -60,7 +103,7 @@ public VpcStateJson verifyVpcId(String projectid, String vpcId) throws FallbackE

@Override
public RouteWebJson createRouteRules(String subnetId, SubnetState subnetState) throws FallbackException {
String routeManagerServiceUrl = routeUrl + "subnets/" + subnetId + "/routes"; // for kubernetes test
String routeManagerServiceUrl = routeUrl + "subnets/" + subnetId + "/routes";
HttpEntity<SubnetStateJson> routeRequest = new HttpEntity<>(new SubnetStateJson(subnetState));
RouteWebJson routeResponse = restTemplate.postForObject(routeManagerServiceUrl, routeRequest, RouteWebJson.class);
// retry if routeResponse is null
Expand Down Expand Up @@ -100,7 +143,7 @@ public IPStateJson allocateIPGateway(String subnetId, String cidr, String portId
ipState.setPortId(portId);
ipState.setSubnetCidr(cidr);

String ipManagerServiceUrl = ipUrl; // for kubernetes test
String ipManagerServiceUrl = ipUrl;
HttpEntity<IPStateJson> ipRequest = new HttpEntity<>(new IPStateJson(ipState));
IPStateJson ipResponse = restTemplate.postForObject(ipManagerServiceUrl, ipRequest, IPStateJson.class);
// retry if ipResponse is null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package com.futurewei.alcor.subnet.utils;

import com.futurewei.alcor.subnet.config.ThreadPoolExecutorConfig;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorUtils {
public static final ThreadPoolExecutor SELECT_POOL_EXECUTOR = new ThreadPoolExecutor(10, 20, 5000,
public static final ThreadPoolExecutor SELECT_POOL_EXECUTOR = new ThreadPoolExecutor(
ThreadPoolExecutorConfig.corePoolSize,
ThreadPoolExecutorConfig.maximumPoolSize,
ThreadPoolExecutorConfig.KeepAliveTime,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1024),
new LinkedBlockingQueue<>(ThreadPoolExecutorConfig.capacity),
new ThreadFactoryBuilder().setNameFormat("selectThreadPoolExecutor-%d").build());
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ public void createSubnetState_canNotFindRoute_notPass () throws Exception {

VpcStateJson vpcStateJson = new VpcStateJson(vpcState);
MacStateJson macResponse = new MacStateJson();
MacState macState = new MacState();
macResponse.setMacState(macState);

Mockito.when(subnetDatabaseService.getBySubnetId(UnitTestConfig.subnetId))
.thenReturn(subnetState);
Expand All @@ -166,7 +168,7 @@ public void createSubnetState_canNotFindRoute_notPass () throws Exception {
.andExpect(MockMvcResultMatchers.jsonPath("$.subnet.id").value(UnitTestConfig.subnetId));
}catch (Exception ex) {
//System.out.println(ex.getMessage());
assertEquals(UnitTestConfig.createException, ex.getMessage());
assertEquals(UnitTestConfig.createException2, ex.getMessage());
}

}
Expand Down Expand Up @@ -200,7 +202,7 @@ public void createSubnetState_canNotFindMac_notPass () throws Exception {
.andExpect(MockMvcResultMatchers.jsonPath("$.subnet.id").value(UnitTestConfig.subnetId));
}catch (Exception ex) {
//System.out.println(ex.getMessage());
assertEquals(UnitTestConfig.createException, ex.getMessage());
assertEquals(UnitTestConfig.createException2, ex.getMessage());
}

}
Expand Down

0 comments on commit 090aa3a

Please sign in to comment.