diff --git a/conf/springConfigXml/sugonSdnController.xml b/conf/springConfigXml/sugonSdnController.xml
index dd763b641ecf6087cf0542e1e7a50e675e4d5867..6188abb0a962b52218ab0dcd7fb88568f7573a61 100644
--- a/conf/springConfigXml/sugonSdnController.xml
+++ b/conf/springConfigXml/sugonSdnController.xml
@@ -71,4 +71,11 @@
+
+
diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
index 9c1efd21e9a83b8f1919bb4308c3ec0b3cf6a9a6..37ac9763e670b7ef18a189aa6d71dade6b0b03cb 100755
--- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
+++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
@@ -2952,7 +2952,7 @@ public class KVMHost extends HostBase implements Host {
to.setIps(getCleanTrafficIp(nic));
}
- if (!nic.getType().equals(VmInstanceConstant.VIRTUAL_NIC_TYPE)) {
+ if (!nic.getType().equals(VmInstanceConstant.VIRTUAL_NIC_TYPE) && !nic.getType().equals(VmInstanceConstant.TF_VIRTUAL_NIC_TYPE)) {
return to;
}
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java
index 8cb1602ebaf3b97b7614687c70e4056b17b51d63..f8c66d4cd41cd357f585d6a261eb2c3fa7f58440 100644
--- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java
@@ -16,9 +16,7 @@ import org.zstack.network.l2.vxlan.vxlanNetwork.L2VxlanNetworkInventory;
import org.zstack.network.l3.L3NetworkSystemTags;
import org.zstack.sdnController.SdnController;
import org.zstack.sdnController.header.*;
-import org.zstack.sugonSdnController.controller.api.ApiConnector;
-import org.zstack.sugonSdnController.controller.api.ApiConnectorFactory;
-import org.zstack.sugonSdnController.controller.api.Status;
+import org.zstack.sugonSdnController.controller.api.*;
import org.zstack.sugonSdnController.controller.api.types.*;
import org.zstack.sugonSdnController.header.APICreateL2TfNetworkMsg;
import org.zstack.utils.StringDSL;
@@ -26,7 +24,6 @@ import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;
import org.zstack.utils.network.NetworkUtils;
-import java.io.IOException;
import java.util.*;
import static org.zstack.core.Platform.operr;
@@ -38,8 +35,11 @@ public class SugonSdnController implements TfSdnController, SdnController {
private SdnControllerVO sdnControllerVO;
+ private TfHttpClient client;
+
public SugonSdnController(SdnControllerVO vo) {
sdnControllerVO = vo;
+ client = new TfHttpClient(vo.getIp());
}
@Override
@@ -56,21 +56,20 @@ public class SugonSdnController implements TfSdnController, SdnController {
return;
}
String accountUuid = StringDSL.transToTfUuid(accountVO.getUuid());
- ApiConnector apiConnector = ApiConnectorFactory.build(msg.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
- assert apiConnector != null;
- Domain domain = (Domain) apiConnector.findByFQN(Domain.class, SugonSdnControllerConstant.TF_DEFAULT_DOMAIN);
+ client = new TfHttpClient(msg.getIp());
+ Domain domain = (Domain) client.getDomain();
if(domain == null){
completion.fail(operr("get default domain on tf controller failed"));
return;
}
- Project defaultProject = (Project) apiConnector.findById(Project.class, accountUuid);
+ Project defaultProject = (Project) client.findById(Project.class, accountUuid);
if(defaultProject == null){
Project project = new Project();
project.setParent(domain);
project.setDisplayName(SugonSdnControllerConstant.ZSTACK_DEFAULT_ACCOUNT);
project.setName(accountUuid);
project.setUuid(accountUuid);
- Status status = apiConnector.create(project);
+ Status status = client.create(project);
if(status.isSuccess()){
logger.info("create tf project for zstack admin success");
completion.success();
@@ -81,7 +80,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
logger.warn("tf project for zstack admin already exists: " + accountUuid);
completion.success();
}
- } catch (IOException e) {
+ } catch (Exception e) {
String message = String.format("create tf project for zstack admin on tf controller failed due to: %s", e.getMessage());
logger.error(message, e);
completion.fail(operr(message));
@@ -135,8 +134,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
String name = l2NetworkVO.getName();
try {
APICreateL2TfNetworkMsg l2TfNetworkMsg = (APICreateL2TfNetworkMsg) msg;
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
- Project project = (Project) apiConnector.findById(Project.class, accountUuid);
+ Project project = (Project) client.findById(Project.class, accountUuid);
if(project == null) {
completion.fail(operr("get project[uuid:%s] on tf controller failed ", accountUuid));
}else{
@@ -149,7 +147,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
IPSegmentType ipSegmentType = new IPSegmentType(l2TfNetworkMsg.getIpPrefix(), l2TfNetworkMsg.getIpPrefixLength());
virtualNetwork.setIpSegment(ipSegmentType);
}
- Status status = apiConnector.create(virtualNetwork);
+ Status status = client.create(virtualNetwork);
if(status.isSuccess()){
logger.info("create tf l2 network success, name:" + name);
completion.success();
@@ -157,7 +155,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
completion.fail(operr("create tf l2 network[name:%s] on tf controller failed ", name));
}
}
- } catch (IOException e) {
+ } catch (Exception e) {
String message = String.format("create tf l2 network[name:%s] on tf controller failed due to: %s", name, e.getMessage());
logger.error(message, e);
completion.fail(operr(message));
@@ -169,13 +167,12 @@ public class SugonSdnController implements TfSdnController, SdnController {
String uuid = StringDSL.transToTfUuid(l2NetworkVO.getUuid());
String name = l2NetworkVO.getName();
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
- VirtualNetwork virtualNetwork = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, uuid);
+ VirtualNetwork virtualNetwork = (VirtualNetwork) client.findById(VirtualNetwork.class, uuid);
if(virtualNetwork == null){
completion.fail(operr("get virtual network[uuid:%s] on tf controller failed ", uuid));
}else{
virtualNetwork.setDisplayName(name);
- Status status = apiConnector.update(virtualNetwork);
+ Status status = client.update(virtualNetwork);
if(status.isSuccess()){
logger.info("update tf l2 network success, name:" + name);
completion.success();
@@ -183,7 +180,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
completion.fail(operr("update tf l2 network[name:%s] on tf controller failed ", name));
}
}
- } catch (IOException e) {
+ } catch (Exception e) {
String message = String.format("update tf l2 network[name:%s] on tf controller failed due to: %s ", name, e.getMessage());
logger.error(message, e);
completion.fail(operr(message));
@@ -194,15 +191,14 @@ public class SugonSdnController implements TfSdnController, SdnController {
public void deleteL2Network(L2NetworkVO l2NetworkVO, List systemTags, Completion completion) {
String uuid = StringDSL.transToTfUuid(l2NetworkVO.getUuid());
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
- Status status = apiConnector.delete(VirtualNetwork.class, uuid);
+ Status status = client.delete(VirtualNetwork.class, uuid);
if(status.isSuccess()){
logger.info("delete tf l2 network success, uuid:" + uuid);
completion.success();
}else{
completion.fail(operr("delete tf l2 network[uuid:%s] on tf controller failed ", uuid));
}
- } catch (IOException e) {
+ } catch (Exception e) {
String message = String.format("delete tf l2 network[uuid:%s] on tf controller failed due to: %s", uuid, e.getMessage());
logger.error(message, e);
completion.fail(operr(message));
@@ -296,9 +292,8 @@ public class SugonSdnController implements TfSdnController, SdnController {
@Override
public void deleteL3Network(L3NetworkVO l3NetworkVO, Completion completion) {
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
// 获取 tf 网络信息
- VirtualNetwork vn = (VirtualNetwork)apiConnector.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
+ VirtualNetwork vn = (VirtualNetwork)client.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
if(vn!=null){
// 判断tf网络是否存在
if(vn.getNetworkIpam()!=null) {
@@ -313,7 +308,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
}
}
// 更新 tf 网络信息
- Status status = apiConnector.update(vn);
+ Status status = client.update(vn);
if(!status.isSuccess()){
completion.fail(operr("delete tf l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),status.getMsg()));
// completion.fail(operr("delete tf l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),"tf api call failed"));
@@ -341,9 +336,8 @@ public class SugonSdnController implements TfSdnController, SdnController {
@Override
public void updateL3Network(L3NetworkVO l3NetworkVO, APIUpdateL3NetworkMsg msg, Completion completion) {
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
// 获取 tf 网络信息
- VirtualNetwork vn = (VirtualNetwork)apiConnector.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
+ VirtualNetwork vn = (VirtualNetwork)client.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
// 判断tf网络是否存在
if(vn!=null){
if(vn.getNetworkIpam()!=null) {
@@ -362,10 +356,9 @@ public class SugonSdnController implements TfSdnController, SdnController {
checkOp.get().addDnsNameservers(msg.getDnsDomain());
}
// 更新 tf 网络信息
- Status status = apiConnector.update(vn);
+ Status status = client.update(vn);
if(!status.isSuccess()){
completion.fail(operr("update tf l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),status.getMsg()));
-// completion.fail(operr("update tf l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),"tf api call failed"));
} else{
completion.success();
}
@@ -392,9 +385,8 @@ public class SugonSdnController implements TfSdnController, SdnController {
@Override
public void addL3IpRangeByCidr(L3NetworkVO l3NetworkVO, APIAddIpRangeByNetworkCidrMsg msg, Completion completion) {
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
// 获取 tf 网络信息
- VirtualNetwork vn = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
+ VirtualNetwork vn = (VirtualNetwork) client.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
if(vn!=null){
IpamSubnetType ipamSubnetType = new IpamSubnetType();
// subnet_uuid
@@ -438,9 +430,6 @@ public class SugonSdnController implements TfSdnController, SdnController {
ipamSubnetType.addAllocationPools(allocationPoolType);
// 设置分配IP从小到大
ipamSubnetType.setAddrFromStart(true);
- // 封装实体 -> ObjectReference
- IpamSubnets ipamSubnets = new IpamSubnets();
- ipamSubnets.addSubnets(ipamSubnetType);
VnSubnetsType vnSubnetsType = new VnSubnetsType();
vnSubnetsType.addIpamSubnets(ipamSubnetType);
if(vn.getNetworkIpam()!=null){
@@ -451,7 +440,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
vn.setNetworkIpam(networkIpam,vnSubnetsType);
}
// 更新 tf 网络信息
- Status status = apiConnector.update(vn);
+ Status status = client.update(vn);
if(!status.isSuccess()){
completion.fail(operr("add tf l3 subnet[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),status.getMsg()));
// completion.fail(operr("add tf l3 subnet[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),"tf api call failed"));
@@ -473,9 +462,8 @@ public class SugonSdnController implements TfSdnController, SdnController {
@Override
public void addL3HostRoute(L3NetworkVO l3NetworkVO, APIAddHostRouteToL3NetworkMsg msg, Completion completion) {
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
// 获取 tf 网络信息
- VirtualNetwork vn = (VirtualNetwork)apiConnector.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
+ VirtualNetwork vn = (VirtualNetwork)client.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
if(vn!=null){
// 判断tf网络是否存在
if(vn.getNetworkIpam()!=null) {
@@ -496,7 +484,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
// 替换host route
checkOp.get().setHostRoutes(routeTableType);
// 更新 tf 网络信息
- Status status = apiConnector.update(vn);
+ Status status = client.update(vn);
if(!status.isSuccess()){
completion.fail(operr("add host router to l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),status.getMsg()));
// completion.fail(operr("add host router to l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),"tf api call failed"));
@@ -526,9 +514,8 @@ public class SugonSdnController implements TfSdnController, SdnController {
@Override
public void deleteL3HostRoute(L3NetworkVO l3NetworkVO, APIRemoveHostRouteFromL3NetworkMsg msg, Completion completion) {
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
// 获取 tf 网络信息
- VirtualNetwork vn = (VirtualNetwork)apiConnector.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
+ VirtualNetwork vn = (VirtualNetwork)client.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
if(vn!=null){
// 判断tf网络是否存在
if(vn.getNetworkIpam()!=null) {
@@ -550,7 +537,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
// 替换host route
checkOp.get().setHostRoutes(routeTableType);
// 更新 tf 网络信息
- Status status = apiConnector.update(vn);
+ Status status = client.update(vn);
if(!status.isSuccess()){
completion.fail(operr("delete host route from l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),status.getMsg()));
// completion.fail(operr("delete host route from l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),"tf api call failed"));
@@ -580,9 +567,8 @@ public class SugonSdnController implements TfSdnController, SdnController {
@Override
public void addL3Dns(L3NetworkVO l3NetworkVO, APIAddDnsToL3NetworkMsg msg, Completion completion) {
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
// 获取 tf 网络信息
- VirtualNetwork vn = (VirtualNetwork)apiConnector.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
+ VirtualNetwork vn = (VirtualNetwork)client.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
// 判断tf网络是否存在
if(vn!=null){
if(vn.getNetworkIpam()!=null) {
@@ -608,7 +594,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
checkOp.get().setDhcpOptionList(dhcpOptionsListType);
}
// 更新 tf 网络信息
- Status status = apiConnector.update(vn);
+ Status status = client.update(vn);
if(!status.isSuccess()){
completion.fail(operr("add dns to l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),status.getMsg()));
// completion.fail(operr("add dns to l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),"tf api call failed"));
@@ -638,9 +624,8 @@ public class SugonSdnController implements TfSdnController, SdnController {
@Override
public void deleteL3Dns(L3NetworkVO l3NetworkVO, APIRemoveDnsFromL3NetworkMsg msg, Completion completion) {
try {
- ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
// 获取 tf 网络信息
- VirtualNetwork vn = (VirtualNetwork)apiConnector.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
+ VirtualNetwork vn = (VirtualNetwork)client.findById(VirtualNetwork.class, StringDSL.transToTfUuid(l3NetworkVO.getL2NetworkUuid()));
if(vn!=null){
// 判断tf网络是否存在
if(vn.getNetworkIpam()!=null) {
@@ -654,7 +639,7 @@ public class SugonSdnController implements TfSdnController, SdnController {
dnsValues.remove(msg.getDns());
checkOp.get().getDhcpOptionList().getDhcpOption().get(0).setDhcpOptionValue(StringUtils.join(dnsValues, " "));
// 更新 tf 网络信息
- Status status = apiConnector.update(vn);
+ Status status = client.update(vn);
if (!status.isSuccess()) {
completion.fail(operr("delete dns from to l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),status.getMsg()));
// completion.fail(operr("delete dns from to l3 network[name:%s] on tf controller failed due to:%s", l3NetworkVO.getName(),"tf api call failed"));
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java
index d8971f0dd0d1865335ed2d93f774467a11bfbdfb..ef88f3c9109fddf43d34425d3fb200b40ae3eadb 100644
--- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java
@@ -225,6 +225,7 @@ class ApiConnectorImpl implements ApiConnector {
request.setHeader("X-AUTH-TOKEN", _authtoken);
}
try {
+ _connection.setSocketTimeout(6000);
_httpexecutor.preProcess(request, _httpproc, _httpcontext);
response = _httpexecutor.execute(request, _connection, _httpcontext);
response.setParams(_params);
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/TfCommands.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/TfCommands.java
new file mode 100644
index 0000000000000000000000000000000000000000..849c26f405965249c1807668145c85a147f1b682
--- /dev/null
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/TfCommands.java
@@ -0,0 +1,48 @@
+package org.zstack.sugonSdnController.controller.api;
+
+import org.zstack.utils.gson.JSONObjectUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TfCommands {
+ public static final String TF_GET_DAEMON = "/fqname-to-id";
+ public static final String TF_GET_DAEMON_DETAIL = "/domain/.*";
+ public static final String TF_GET_PROJECT = "/project/.*";
+ public static final String TF_CREATE_PROJECT = "/projects";
+ public static final String TF_GET_NETWORK = "/virtual-network/.*";
+ public static final String TF_CREATE_NETWORK = "/virtual-networks";
+ public static final String TF_GET_VM = "/virtual-machine/.*";
+ public static final String TF_CREATE_VM = "/virtual-machines";
+ public static final String TF_GET_VMI = "/virtual-machine-interface/.*";
+ public static final String TF_CREATE_VMI = "/virtual-machine-interfaces";
+ public static final String TEST_DOMAIN_UUID = "cf8107ad-eee6-4a54-be5e-c05c96a9d552";
+ public static final String TEST_PROJECT_UUID = "36c27e8f-f05c-4780-bf6d-2fa65700f22e";
+ public static final String TEST_L2_UUID = "1eca756e-b935-45ed-a2bc-a3ebba535f7f";
+ public static final String TEST_VM_UUID = "35c27fde-7f67-4c78-b80a-56ae1eefcb5b";
+ public static final String TEST_VMI_UUID = "a581ee83-f5a5-4755-bedf-8d51f235da52";
+
+ public static class TfCmd {
+ public String toString() {
+ return JSONObjectUtil.toJsonString(this);
+ }
+ }
+
+ public static class TfRsp {
+ }
+
+ public static class GetDomainCmd extends TfCmd {
+ public String type;
+ public List fq_name = new ArrayList<>();
+ }
+
+ public static class GetDomainRsp extends TfRsp {
+ public String uuid;
+ }
+
+ public static class GetProjectCmd extends TfCmd {
+ public String uuid;
+ }
+
+}
+
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/TfHttpClient.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/TfHttpClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..00ae9db442968e81cc124e2f7352748976aa11fe
--- /dev/null
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/TfHttpClient.java
@@ -0,0 +1,403 @@
+package org.zstack.sugonSdnController.controller.api;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gson.*;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.http.*;
+import org.springframework.beans.factory.annotation.Autowire;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.web.util.UriComponentsBuilder;
+import org.zstack.core.CoreGlobalProperty;
+import org.zstack.core.MessageCommandRecorder;
+import org.zstack.header.rest.RESTFacade;
+import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant;
+import org.zstack.sugonSdnController.controller.SugonSdnControllerGlobalProperty;
+import org.zstack.sugonSdnController.controller.api.types.Domain;
+import org.zstack.utils.Utils;
+import org.zstack.utils.gson.JSONObjectUtil;
+import org.zstack.utils.logging.CLogger;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE)
+public class TfHttpClient {
+ private static final CLogger logger = Utils.getLogger(TfHttpClient.class);
+ @Autowired
+ private RESTFacade restf;
+ private TimeUnit unit;
+ private Long timeout;
+ private String tf_ip;
+ private Map headers = new HashMap() {
+ {
+ put("Content-Type", "application/json; charset=UTF-8");
+ }
+ };
+
+ public TfHttpClient(String ip) {
+ this.tf_ip = ip;
+ this.unit = TimeUnit.MILLISECONDS;
+ this.timeout = 30000l;
+ }
+
+ public String getTypename(Class> cls) {
+ String clsname = cls.getName();
+ int loc = clsname.lastIndexOf('.');
+ if (loc > 0) {
+ clsname = clsname.substring(loc + 1);
+ }
+ String typename = new String();
+ for (int i = 0; i < clsname.length(); i++) {
+ char ch = clsname.charAt(i);
+ if (Character.isUpperCase(ch)) {
+ if (i > 0) {
+ typename += "-";
+ }
+ ch = Character.toLowerCase(ch);
+ }
+ typename += ch;
+ }
+ return typename;
+ }
+
+ public ApiObjectBase jsonToApiObject(String data, Class extends ApiObjectBase> cls) {
+ if (data == null) {
+ return null;
+ }
+ final String typename = getTypename(cls);
+ final JsonParser parser = new JsonParser();
+ final JsonObject js_obj = parser.parse(data).getAsJsonObject();
+ if (js_obj == null) {
+ logger.warn("Unable to parse response");
+ return null;
+ }
+ JsonElement element = null;
+ if (cls.getGenericSuperclass() == VRouterApiObjectBase.class) {
+ element = js_obj;
+ } else {
+ element = js_obj.get(typename);
+ }
+ if (element == null) {
+ logger.warn("Element " + typename + ": not found");
+ return null;
+ }
+ ApiObjectBase resp = ApiSerializer.deserialize(element.toString(), cls);
+ return resp;
+ }
+
+ public List extends ApiObjectBase> jsonToApiObjects(String data, Class extends ApiObjectBase> cls, boolean withDetail) {
+ if (data == null) {
+ return null;
+ }
+ final String typename = getTypename(cls);
+ List list = new ArrayList();
+ final JsonParser parser = new JsonParser();
+ final JsonObject js_obj= parser.parse(data).getAsJsonObject();
+ if (js_obj == null) {
+ logger.warn("Unable to parse response");
+ return null;
+ }
+ final JsonArray array = js_obj.getAsJsonArray(typename + "s");
+ if (array == null) {
+ logger.warn("Element " + typename + ": not found");
+ return null;
+ }
+ Gson json = ApiSerializer.getDeserializer();
+ for (JsonElement element : array) {
+ ApiObjectBase obj;
+ if (withDetail) {
+ obj = jsonToApiObject(element.toString(), cls);
+ } else {
+ obj = json.fromJson(element.toString(), cls);
+ }
+
+ if (obj == null) {
+ logger.warn("Unable to decode list element");
+ continue;
+ }
+ list.add(obj);
+ }
+ return list;
+ }
+
+ private String buildUrl(String ip, String path) {
+ UriComponentsBuilder ub = UriComponentsBuilder.newInstance();
+ ub.scheme("http");
+ if (CoreGlobalProperty.UNIT_TEST_ON) {
+ ub.host("localhost");
+ ub.port(8989);
+ } else {
+ ub.host(ip);
+ ub.port(SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
+ }
+
+ ub.path(path);
+ return ub.build().toUriString();
+ }
+
+ public String buildFqnJsonString(Class extends ApiObjectBase> cls, List name_list) {
+ Gson json = new Gson();
+ JsonObject js_dict = new JsonObject();
+ js_dict.add("type", json.toJsonTree(getTypename(cls)));
+ js_dict.add("fq_name", json.toJsonTree(name_list));
+ return js_dict.toString();
+ }
+
+ public String getUuid(String data) {
+ if (data == null) {
+ return null;
+ }
+ final JsonParser parser = new JsonParser();
+ final JsonObject js_obj= parser.parse(data).getAsJsonObject();
+ if (js_obj == null) {
+ logger.warn("Unable to parse response");
+ return null;
+ }
+ final JsonElement element = js_obj.get("uuid");
+ if (element == null) {
+ logger.warn("Element \"uuid\": not found");
+ return null;
+ }
+ return element.getAsString();
+ }
+
+ private ResponseEntity execute(String url, HttpMethod method, String body) {
+ HttpHeaders requestHeaders = new HttpHeaders();
+ if (headers != null) {
+ requestHeaders.setAll(headers);
+ }
+ requestHeaders.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity req = new HttpEntity(body, requestHeaders);
+ ResponseEntity response;
+ try {
+ response = restf.syncRawJson(buildUrl(tf_ip, url), req, method, unit, timeout);
+ } catch (Exception e){
+ logger.warn(String.format("Execute http requests:%s failed, reason:%s", url, e.getMessage()));
+ return null;
+ }
+
+ return response;
+ }
+
+ public ApiObjectBase getDomain() {
+ TfCommands.GetDomainCmd getDomainCmd = new TfCommands.GetDomainCmd();
+ getDomainCmd.type = getTypename(Domain.class);
+ List fqName = new ArrayList<>();
+ fqName.add(SugonSdnControllerConstant.TF_DEFAULT_DOMAIN);
+ getDomainCmd.fq_name = fqName;
+ MessageCommandRecorder.record(getDomainCmd.getClass());
+ String httpBody = JSONObjectUtil.toJsonString(getDomainCmd);
+ TfCommands.GetDomainRsp rsp = restf.syncJsonPost(buildUrl(tf_ip, TfCommands.TF_GET_DAEMON), httpBody, headers, TfCommands.GetDomainRsp.class, unit, timeout);
+ return findById(Domain.class, rsp.uuid);
+ }
+
+ public synchronized ApiObjectBase findById(Class extends ApiObjectBase> cls, String uuid) {
+ final String typename = getTypename(cls);
+ String url = String.format("/%s/%s", typename, uuid);
+ ResponseEntity response = execute(url, HttpMethod.GET, "");
+
+ if (response == null) {
+ return null;
+ }
+
+ if (response.getStatusCode() != HttpStatus.OK) {
+ return null;
+ }
+ ApiObjectBase object = jsonToApiObject(response.getBody(), cls);
+ if (object == null) {
+ logger.warn("Unable to decode find response");
+ }
+
+ return object;
+ }
+
+ public synchronized List extends ApiObjectBase> listWithDetail(Class extends ApiObjectBase> cls,
+ String fields,
+ String filters) {
+ final String typename = getTypename(cls);
+ String url = String.format("/%ss?detail=true", typename);
+ if (fields != null) {
+ url = url + "&fields=" + fields;
+ }
+ if (filters != null) {
+ url = url + "&filters=" + filters;
+ }
+ ResponseEntity response = execute(url, HttpMethod.GET, "");
+ if (response == null) {
+ return null;
+ }
+
+ if (response.getStatusCode() != HttpStatus.OK) {
+ logger.warn("list failed with :" + response.getBody());
+ return null;
+ }
+
+ String data = response.getBody();
+ if (data == null) {
+ return null;
+ }
+ List extends ApiObjectBase> list = jsonToApiObjects(data, cls, true);
+ if (list == null) {
+ logger.warn("Unable to parse/deserialize response: " + data);
+ }
+ return list;
+ }
+
+ public List extends ApiObjectBase>
+ getObjects(Class extends ApiObjectBase> cls, List> refList) {
+
+ List list = new ArrayList();
+ for (ObjectReference ref : refList) {
+ ApiObjectBase obj = findById(cls, ref.getUuid());
+ if (obj == null) {
+ logger.warn("Unable to find element with uuid: " + ref.getUuid());
+ continue;
+ }
+ list.add(obj);
+ }
+ return list;
+ }
+
+ public ApiObjectBase findByFQN(Class extends ApiObjectBase> cls, String fullName) {
+ List fqn = ImmutableList.copyOf(StringUtils.split(fullName, ':'));
+ String uuid = findByName(cls, fqn);
+ if (uuid == null) {
+ return null;
+ }
+ return findById(cls, uuid);
+ }
+
+ public synchronized String findByName(Class extends ApiObjectBase> cls, List name_list) {
+ String jsonStr = buildFqnJsonString(cls, name_list);
+ ResponseEntity response = execute("/fqname-to-id", HttpMethod.POST, jsonStr);
+
+ if (response == null) {
+ return null;
+ }
+
+ if (response.getStatusCode() != HttpStatus.OK) {
+ return null;
+ }
+
+ String data = response.getBody();
+ if (data == null) {
+ return null;
+ }
+ logger.debug("<< Response Data: " + data);
+
+ String uuid = getUuid(data);
+ if (uuid == null) {
+ logger.warn("Unable to parse response");
+ return null;
+ }
+ return uuid;
+ }
+
+ public synchronized Status create(ApiObjectBase obj) {
+ final String typename = getTypename(obj.getClass());
+ final String jsdata = ApiSerializer.serializeObject(typename, obj);
+ String url;
+
+ ResponseEntity response;
+ if (obj instanceof VRouterApiObjectBase) {
+ url = String.format("/%s", typename);
+ } else {
+ obj.updateQualifiedName();
+ url = String.format("/%ss", typename);
+ }
+ response = execute(url, HttpMethod.POST, jsdata);
+
+ if (response == null) {
+ return Status.failure("No response from API server.");
+ }
+ HttpStatus status = response.getStatusCode();
+ if (status != HttpStatus.OK
+ && status != HttpStatus.CREATED
+ && status != HttpStatus.ACCEPTED ) {
+
+ String reason = response.getBody();
+ logger.error("create api request failed: " + reason);
+ if (status != HttpStatus.NOT_FOUND) {
+ logger.error("Failure message: " + reason);
+ }
+ return Status.failure(reason);
+ }
+
+ ApiObjectBase resp = jsonToApiObject(response.getBody(), obj.getClass());
+ if (resp == null) {
+ String reason = "Unable to decode Create response";
+ logger.error(reason);
+ return Status.failure(reason);
+ }
+
+ String uuid = obj.getUuid();
+ if (uuid == null) {
+ obj.setUuid(resp.getUuid());
+ } else if (!uuid.equals(resp.getUuid())
+ && !(obj instanceof VRouterApiObjectBase)) {
+ logger.warn("Response contains unexpected uuid: " + resp.getUuid());
+ return Status.success();
+ }
+ logger.debug("Create " + typename + " uuid: " + obj.getUuid());
+ return Status.success();
+ }
+
+ public synchronized Status update(ApiObjectBase obj) {
+ final String typename = getTypename(obj.getClass());
+ final String jsdata = ApiSerializer.serializeObject(typename, obj);
+ String url = String.format("/%s/%s", typename, obj.getUuid());
+
+ ResponseEntity response = execute(url, HttpMethod.PUT, jsdata);
+
+ if (response == null) {
+ return Status.failure("No response from API server.");
+ }
+
+ HttpStatus status = response.getStatusCode();
+ if (status != HttpStatus.OK
+ && status != HttpStatus.ACCEPTED ) {
+ String reason = response.getBody();
+ logger.warn("<< Response:" + reason);
+ return Status.failure(reason);
+ }
+
+ return Status.success();
+ }
+
+ public synchronized Status delete(Class extends ApiObjectBase> cls, String uuid) {
+ if (findById(cls, uuid) == null) {
+ // object does not exist so we are ok
+ return Status.success();
+ }
+
+ final String typename = getTypename(cls);
+ String url = String.format("/%s/%s", typename, uuid);
+ ResponseEntity response = execute(url, HttpMethod.DELETE, "");
+
+ if (response == null) {
+ return Status.failure("No response from API server.");
+ }
+
+ HttpStatus status = response.getStatusCode();
+ if (status != HttpStatus.OK
+ && status != HttpStatus.NO_CONTENT
+ && status != HttpStatus.ACCEPTED ) {
+ String reason = response.getBody();
+ logger.warn("Delete failed: " + reason);
+ if (status != HttpStatus.NOT_FOUND) {
+ logger.error("Failure message: " + response);
+ }
+ return Status.failure(reason);
+ }
+ return Status.success();
+ }
+
+ public Status delete(ApiObjectBase obj) throws IOException {
+ return delete(obj.getClass(), obj.getUuid());
+ }
+}
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java
index 4b923786a5fa6fe1abaa9ee9bd7681785631a620..dd10d8edec7bcac0dc04b51011ab505a5b098dae 100644
--- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java
@@ -22,7 +22,7 @@ import java.util.*;
public class TfPortClient {
private static final CLogger logger = Utils.getLogger(TfPortClient.class);
- private ApiConnector apiConnector;
+ private TfHttpClient client;
private String tenantId;
@@ -33,10 +33,7 @@ public class TfPortClient {
if (sdn == null){
throw new RuntimeException("Can not find a tf sdn controller.");
}
- apiConnector = ApiConnectorFactory.build(sdn.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT);
- if (apiConnector == null) {
- throw new RuntimeException(String.format("Can not connect to tf sdn controller: %s.", sdn.getIp()));
- }
+ client = new TfHttpClient(sdn.getIp());
tenantId = StringDSL.transToTfUuid(sdn.getAccountUuid());
}
@@ -56,14 +53,14 @@ public class TfPortClient {
ipEntities.add(ipEntity);
requestPortResourceEntity.setFixdIps(ipEntities);
try {
- VirtualNetwork netObj = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, l2Id);
+ VirtualNetwork netObj = (VirtualNetwork) client.findById(VirtualNetwork.class, l2Id);
if (netObj == null) {
throw new RuntimeException(String.format("Can not find tf virtualnetwork: %s.", l2Id));
}
//if mac-address is specified, check against the exisitng ports
//to see if there exists a port with the same mac-address
if (!Objects.isNull(mac)) {
- List ports = (List) apiConnector.listWithDetail(
+ List ports = (List) client.listWithDetail(
VirtualMachineInterface.class, null, null);
for (VirtualMachineInterface port : ports) {
@@ -92,13 +89,13 @@ public class TfPortClient {
port.setDisplayName(vmName);
// always request for v4 and v6 ip object and handle the failure
// create the object
- Status result = apiConnector.create(port);
+ Status result = client.create(port);
if (!result.isSuccess()) {
throw new RuntimeException(String.format("Failed to create tf VirtualMachineInterface: %s, reason: %s",
port.getUuid(), result.getMsg()));
}
// add support, nova boot --nic subnet-id=subnet_uuid
- VirtualMachineInterface realPort = (VirtualMachineInterface) apiConnector.findById(
+ VirtualMachineInterface realPort = (VirtualMachineInterface) client.findById(
VirtualMachineInterface.class, port.getUuid());
if (ip != null) {
@@ -106,7 +103,7 @@ public class TfPortClient {
portCreateInstanceIp(netObj, realPort, l3Id, ip);
} catch (Exception e) {
try {
- apiConnector.delete(realPort);
+ client.delete(realPort);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
@@ -125,7 +122,7 @@ public class TfPortClient {
ipv4PortDelete = true;
// failure in creating the instance ip. Roll back.
try {
- apiConnector.delete(realPort);
+ client.delete(realPort);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
@@ -133,13 +130,13 @@ public class TfPortClient {
}
if (ipv4PortDelete) {
try {
- apiConnector.delete(realPort);
+ client.delete(realPort);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
- VirtualMachineInterface newestPort = (VirtualMachineInterface) apiConnector.findById(
+ VirtualMachineInterface newestPort = (VirtualMachineInterface) client.findById(
VirtualMachineInterface.class, realPort.getUuid());
return getPortResponse(newestPort);
} catch (Exception e) {
@@ -147,7 +144,7 @@ public class TfPortClient {
}
}
- private TfPortResponse getPortResponse(VirtualMachineInterface portObj) throws IOException {
+ private TfPortResponse getPortResponse(VirtualMachineInterface portObj) {
TfPortResponse tfPortResponse = new TfPortResponse();
tfPortResponse.setPortId(portObj.getUuid());
tfPortResponse.setCode(200);
@@ -156,7 +153,7 @@ public class TfPortClient {
List> ipBackRefs = portObj.getInstanceIpBackRefs();
if (ipBackRefs != null && ipBackRefs.size() > 0) {
for (ObjectReference ipBackRef : ipBackRefs) {
- InstanceIp ipObj = (InstanceIp) apiConnector.findById(InstanceIp.class, ipBackRef.getUuid());
+ InstanceIp ipObj = (InstanceIp) client.findById(InstanceIp.class, ipBackRef.getUuid());
String ipAddr = ipObj != null ? ipObj.getAddress() : null;
String subnetId = Objects.requireNonNull(ipObj).getSubnetUuid();
ipEntity.setIpAddress(ipAddr);
@@ -169,7 +166,7 @@ public class TfPortClient {
}
private Status portCreateInstanceIp(VirtualNetwork virtualNetwork, VirtualMachineInterface port,
- String subnetId, String ip) throws IOException {
+ String subnetId, String ip) {
InstanceIp ipObj = new InstanceIp();
String ipFamily = "v4";
if (ip != null) {
@@ -192,12 +189,12 @@ public class TfPortClient {
PermType2 permType2 = new PermType2();
permType2.setOwner(tenantId);
ipObj.setPerms2(permType2);
- return apiConnector.create(ipObj);
+ return client.create(ipObj);
}
private VirtualMachineInterface getTfPortObject(TfPortRequestResource requestPortResourceEntity, VirtualNetwork virtualNetwork, String tfPortUUid) throws IOException {
String projectId = requestPortResourceEntity.getTenantId();
- Project projectObj = (Project) apiConnector.findById(Project.class, projectId);
+ Project projectObj = (Project) client.findById(Project.class, projectId);
IdPermsType idPermsType = new IdPermsType();
idPermsType.setEnable(true);
String portUuid = String.valueOf(UUID.randomUUID());
@@ -231,11 +228,11 @@ public class TfPortClient {
}
public boolean ipInUseCheck(String ipAddr, String netId) throws IOException {
- VirtualNetwork virtualNetwork = (VirtualNetwork) apiConnector.findById(VirtualNetwork.class, netId);
+ VirtualNetwork virtualNetwork = (VirtualNetwork) client.findById(VirtualNetwork.class, netId);
if (virtualNetwork != null) {
List> instanceIpBackRefs = virtualNetwork.getInstanceIpBackRefs();
if (instanceIpBackRefs != null) {
- List ipObjects = (List) apiConnector.getObjects(InstanceIp.class, instanceIpBackRefs);
+ List ipObjects = (List) client.getObjects(InstanceIp.class, instanceIpBackRefs);
if (ipObjects != null) {
for (InstanceIp ipObj : ipObjects) {
if (ipObj.getAddress().equals(ipAddr)) {
@@ -252,7 +249,7 @@ public class TfPortClient {
private VirtualMachine ensureInstanceExists(String deviceId, String projectId, boolean baremeetal) throws IOException {
VirtualMachine instanceObj = null;
try {
- instanceObj = (VirtualMachine) apiConnector.findById(VirtualMachine.class, deviceId);
+ instanceObj = (VirtualMachine) client.findById(VirtualMachine.class, deviceId);
if (instanceObj != null) {
return instanceObj;
}
@@ -267,18 +264,18 @@ public class TfPortClient {
} else {
instanceObj.setServerType("virtual-server");
}
- apiConnector.create(instanceObj);
+ client.create(instanceObj);
} catch (Exception e) { // Exception......
VirtualMachine dbInstanceObj = null;
if (instanceObj.getUuid() != null) {
- dbInstanceObj = (VirtualMachine) apiConnector.findById(VirtualMachine.class, instanceObj.getUuid());
+ dbInstanceObj = (VirtualMachine) client.findById(VirtualMachine.class, instanceObj.getUuid());
} else {
- dbInstanceObj = (VirtualMachine) apiConnector.findByFQN(VirtualMachine.class, instanceObj.getName());
+ dbInstanceObj = (VirtualMachine) client.findByFQN(VirtualMachine.class, instanceObj.getName());
}
if (dbInstanceObj != null) {
if (baremeetal && !Objects.equals(dbInstanceObj.getServerType(), "baremetal-server")) {
- apiConnector.update(instanceObj);
+ client.update(instanceObj);
} else {
instanceObj = dbInstanceObj;
}
@@ -289,24 +286,24 @@ public class TfPortClient {
public TfPortResponse getVirtualMachineInterface(String portId) {
try {
- VirtualMachineInterface port = (VirtualMachineInterface) apiConnector.findById(
+ VirtualMachineInterface port = (VirtualMachineInterface) client.findById(
VirtualMachineInterface.class, portId);
if (port != null){
return getPortResponse(port);
}else {
return null;
}
- } catch (IOException e) {
+ } catch (Exception e) {
throw new RuntimeException(e);
}
}
public List getVirtualMachineInterfaceDetail() {
try {
- List ports = (List) apiConnector.listWithDetail(
+ List ports = (List) client.listWithDetail(
VirtualMachineInterface.class, null, null);
return ports;
- } catch (IOException e) {
+ } catch (Exception e) {
throw new RuntimeException(e);
}
}
@@ -314,7 +311,7 @@ public class TfPortClient {
public TfPortResponse deletePort(String portId) {
TfPortResponse response = new TfPortResponse();
try {
- VirtualMachineInterface portObj = (VirtualMachineInterface) apiConnector.findById(VirtualMachineInterface.class, portId);
+ VirtualMachineInterface portObj = (VirtualMachineInterface) client.findById(VirtualMachineInterface.class, portId);
if (portObj == null) {
response.setCode(200);
return response;
@@ -323,18 +320,18 @@ public class TfPortClient {
List> iipBackRefs = portObj.getInstanceIpBackRefs();
if (iipBackRefs != null && iipBackRefs.size() > 0) {
for (ObjectReference iipBackRef : iipBackRefs) {
- InstanceIp iipObj = (InstanceIp) apiConnector.findById(InstanceIp.class, iipBackRef.getUuid());
+ InstanceIp iipObj = (InstanceIp) client.findById(InstanceIp.class, iipBackRef.getUuid());
// in case of shared ip only delete the link to the VMI
if (iipObj != null) {
iipObj.removeVirtualMachineInterface(portObj);
List> virtualMachineInterface = iipObj.getVirtualMachineInterface();
if (virtualMachineInterface == null || virtualMachineInterface.size() == 0) {
- Status delResult = apiConnector.delete(InstanceIp.class, iipBackRef.getUuid());
+ Status delResult = client.delete(InstanceIp.class, iipBackRef.getUuid());
if (!delResult.isSuccess()) {
throw new RuntimeException("Tf instance ip delete failed: " + iipBackRef.getUuid());
}
} else {
- apiConnector.update(iipObj);
+ client.update(iipObj);
}
}
}
@@ -345,12 +342,12 @@ public class TfPortClient {
for (ObjectReference fipBackRef : fipBackRefs) {
FloatingIp fipObj = getTfFloatingipObject(fipBackRef.getUuid());
if (fipObj != null) {
- apiConnector.update(fipObj);
+ client.update(fipObj);
}
}
}
- apiConnector.delete(VirtualMachineInterface.class, portId);
+ client.delete(VirtualMachineInterface.class, portId);
// delete VirtualMachine if this was the last port
String instanceId;
if (Objects.equals(portObj.getParentType(), "virtual-machine")) {
@@ -364,9 +361,9 @@ public class TfPortClient {
}
}
if (instanceId != null) {
- VirtualMachine vm = (VirtualMachine) apiConnector.findById(VirtualMachine.class, instanceId);
+ VirtualMachine vm = (VirtualMachine) client.findById(VirtualMachine.class, instanceId);
if (CollectionUtils.isEmpty(vm.getVirtualMachineInterfaceBackRefs())) {
- apiConnector.delete(VirtualMachine.class, instanceId);
+ client.delete(VirtualMachine.class, instanceId);
}
}
response.setCode(200);
@@ -380,8 +377,8 @@ public class TfPortClient {
}
}
- private FloatingIp getTfFloatingipObject(String uuid) throws IOException {
- FloatingIp fipObj = (FloatingIp) apiConnector.findById(FloatingIp.class, uuid);
+ private FloatingIp getTfFloatingipObject(String uuid) {
+ FloatingIp fipObj = (FloatingIp) client.findById(FloatingIp.class, uuid);
if (fipObj == null) {
return null;
}
@@ -399,7 +396,7 @@ public class TfPortClient {
*/
public boolean checkTfIpAvailability(String ipAddr, String subnetId) throws IOException {
L3NetworkVO l3Network = Q.New(L3NetworkVO.class).eq(L3NetworkVO_.uuid, subnetId).find();
- VirtualNetwork virtualNetwork = (VirtualNetwork) apiConnector.findById(
+ VirtualNetwork virtualNetwork = (VirtualNetwork) client.findById(
VirtualNetwork.class, StringDSL.transToTfUuid(l3Network.getL2NetworkUuid()));
if (Objects.isNull(virtualNetwork)) {
@@ -413,11 +410,11 @@ public class TfPortClient {
List> floatingIpPools = virtualNetwork.getFloatingIpPools();
if (CollectionUtils.isNotEmpty(floatingIpPools)) {
for (ObjectReference floatingIpPool : floatingIpPools) {
- FloatingIpPool floatingIpPoolObj = (FloatingIpPool) apiConnector.findById(FloatingIpPool.class, floatingIpPool.getUuid());
+ FloatingIpPool floatingIpPoolObj = (FloatingIpPool) client.findById(FloatingIpPool.class, floatingIpPool.getUuid());
List> floatingIps = floatingIpPoolObj.getFloatingIps();
if (CollectionUtils.isNotEmpty(floatingIps)) {
for (ObjectReference fip : floatingIps) {
- FloatingIp fipObj = (FloatingIp) apiConnector.findById(FloatingIp.class, fip.getUuid());
+ FloatingIp fipObj = (FloatingIp) client.findById(FloatingIp.class, fip.getUuid());
if (fipObj.getAddress().equals(ipAddr)) {
return true;
}
@@ -427,7 +424,7 @@ public class TfPortClient {
}
} else { // else instance ips.
if (CollectionUtils.isNotEmpty(instanceIpBackRefs)) {
- List ipObjects = (List) apiConnector.getObjects(InstanceIp.class, instanceIpBackRefs);
+ List ipObjects = (List) client.getObjects(InstanceIp.class, instanceIpBackRefs);
// check all instance ips.
if (CollectionUtils.isNotEmpty(ipObjects)) {
for (InstanceIp ipObj : ipObjects) {
@@ -480,11 +477,11 @@ public class TfPortClient {
public void updateTfPort(String tfPortUUid, String accountId, String deviceId) {
try {
- VirtualMachineInterface port = (VirtualMachineInterface) apiConnector.findById(
+ VirtualMachineInterface port = (VirtualMachineInterface) client.findById(
VirtualMachineInterface.class, tfPortUUid);
VirtualMachine vm = ensureInstanceExists(deviceId, accountId, false);
port.setVirtualMachine(vm);
- apiConnector.update(port);
+ client.update(port);
} catch (IOException e) {
throw new RuntimeException(e);
}
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/header/SugonApiInterceptor.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/header/SugonApiInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..18294d7463a8705e517bec26da11355a10341dfb
--- /dev/null
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/header/SugonApiInterceptor.java
@@ -0,0 +1,89 @@
+package org.zstack.sugonSdnController.header;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.zstack.core.cloudbus.CloudBus;
+import org.zstack.core.db.Q;
+import org.zstack.header.apimediator.ApiMessageInterceptionException;
+import org.zstack.header.apimediator.ApiMessageInterceptor;
+import org.zstack.header.apimediator.GlobalApiMessageInterceptor;
+import org.zstack.header.apimediator.StopRoutingException;
+import org.zstack.header.message.APIMessage;
+import org.zstack.header.network.l2.*;
+import org.zstack.header.network.l3.*;
+import org.zstack.header.vm.VmInstanceConstant;
+import org.zstack.header.vm.VmNicVO;
+import org.zstack.header.vm.VmNicVO_;
+import org.zstack.sdnController.header.APIRemoveSdnControllerEvent;
+import org.zstack.sdnController.header.APIRemoveSdnControllerMsg;
+import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.zstack.core.Platform.operr;
+
+
+public class SugonApiInterceptor implements ApiMessageInterceptor, GlobalApiMessageInterceptor {
+ @Autowired
+ private CloudBus bus;
+
+ @Override
+ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException {
+ if (msg instanceof APIDeleteL2NetworkMsg) {
+ validate((APIDeleteL2NetworkMsg) msg);
+ } else if (msg instanceof APIDeleteL3NetworkMsg) {
+ validate((APIDeleteL3NetworkMsg) msg);
+ } else if (msg instanceof APIRemoveSdnControllerMsg) {
+ validate((APIRemoveSdnControllerMsg) msg);
+ }
+
+ return msg;
+ }
+
+ private void validate(APIDeleteL2NetworkMsg msg) {
+ APIDeleteL2NetworkEvent evt = new APIDeleteL2NetworkEvent(msg.getId());
+ if(Q.New(L3NetworkVO.class).eq(L3NetworkVO_.l2NetworkUuid, msg.getL2NetworkUuid())
+ .eq(L3NetworkVO_.type, SugonSdnControllerConstant.L3_TF_NETWORK_TYPE).count() > 0){
+ String error = String.format("L2Network[%s] still has some L3Networks, please delete L3Networks first.",
+ msg.getL2NetworkUuid());
+ evt.setError(operr(error));
+ bus.publish(evt);
+ throw new StopRoutingException();
+ }
+ }
+
+ private void validate(APIDeleteL3NetworkMsg msg) {
+ APIDeleteL3NetworkEvent evt = new APIDeleteL3NetworkEvent(msg.getId());
+ if(Q.New(VmNicVO.class).eq(VmNicVO_.l3NetworkUuid, msg.getL3NetworkUuid())
+ .eq(VmNicVO_.type, VmInstanceConstant.TF_VIRTUAL_NIC_TYPE).count() > 0){
+ String error = String.format("L3Network[%s] still has some Nics, please delete all Nics first.",
+ msg.getId());
+ evt.setError(operr(error));
+ bus.publish(evt);
+ throw new StopRoutingException();
+ }
+ }
+
+ private void validate(APIRemoveSdnControllerMsg msg) {
+ APIRemoveSdnControllerEvent evt = new APIRemoveSdnControllerEvent(msg.getId());
+ if(Q.New(L2NetworkVO.class).eq(L2NetworkVO_.type, SugonSdnControllerConstant.L2_TF_NETWORK_TYPE).count() > 0){
+ String error = String.format("There are some TfL2Networks exists, please delete all TfL2Networks first.",
+ msg.getId());
+ evt.setError(operr(error));
+ bus.publish(evt);
+ throw new StopRoutingException();
+ }
+ }
+
+ public List getMessageClassToIntercept() {
+ List ret = new ArrayList<>();
+ ret.add(APIDeleteL2NetworkMsg.class);
+ ret.add(APIDeleteL3NetworkMsg.class);
+ ret.add(APIRemoveSdnControllerMsg.class);
+ return ret;
+ }
+
+ public InterceptorPosition getPosition() {
+ return InterceptorPosition.END;
+ }
+}
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfL2Network.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfL2Network.java
index c6ee8351ed7d59f49e2ee99b938a1af2008b26a0..06520d030a738b1871bde710e7c91f1af1e383aa 100644
--- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfL2Network.java
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfL2Network.java
@@ -193,13 +193,6 @@ public class TfL2Network extends L2NoVlanNetwork implements TfL2NetworkExtension
private void handle(APIDeleteL2NetworkMsg msg) {
APIDeleteL2NetworkEvent evt = new APIDeleteL2NetworkEvent(msg.getId());
- if(Q.New(L3NetworkVO.class).eq(L3NetworkVO_.l2NetworkUuid, msg.getL2NetworkUuid()).count() > 0){
- String error = String.format("L2Network[%s] still has some L3Networks, please delete L3Networks first.",
- msg.getL2NetworkUuid());
- evt.setError(operr(error));
- bus.publish(evt);
- return;
- }
deleteTfL2NetworkOnSdnController(self, new Completion(msg) {
@Override
public void success() {
diff --git a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerTest.groovy b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerTest.groovy
index 9895cb45b1c888a3eac90bd1a7f3b0e1ec26d922..6d2c5bbf310c70faea5b49b1fbd98bebd85bbd54 100644
--- a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerTest.groovy
+++ b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerTest.groovy
@@ -19,6 +19,8 @@ class SdnControllerTest extends Test {
include("vip.xml")
include("vxlan.xml")
include("sdnController.xml")
+ include("sugonSdnController.xml")
+ include("TfPortAllocator.xml")
eip()
lb()
portForwarding()
diff --git a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerCase.groovy
new file mode 100644
index 0000000000000000000000000000000000000000..141813024d13f1f2dae8a7cbc5a62cf8753016b8
--- /dev/null
+++ b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerCase.groovy
@@ -0,0 +1,232 @@
+package org.zstack.test.integration.network.sdnController
+
+import org.zstack.core.db.DatabaseFacade
+import org.zstack.sdk.*
+import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant
+import org.zstack.sugonSdnController.controller.api.types.MacAddressesType
+import org.zstack.sugonSdnController.controller.api.types.Project
+import org.zstack.sugonSdnController.controller.api.types.VirtualMachineInterface
+import org.zstack.sugonSdnController.controller.api.ApiSerializer
+import org.zstack.sugonSdnController.controller.api.TfCommands
+import org.zstack.sdnController.header.SdnControllerVO
+import org.zstack.header.network.l3.L3NetworkVO;
+import org.zstack.testlib.EnvSpec
+import org.zstack.testlib.SubCase
+import javax.persistence.TypedQuery;
+import org.springframework.http.ResponseEntity
+import org.springframework.http.HttpStatus
+
+
+class SugonSdnControllerCase extends SubCase {
+ EnvSpec env
+ DatabaseFacade dbf
+
+ @Override
+ void setup() {
+ spring {
+ useSpring(SdnControllerTest.springSpec)
+ }
+ }
+
+ @Override
+ void environment() {
+ env = SugonSdnControllerEnv.SdnControllerBasicEnv()
+ }
+
+ @Override
+ void test() {
+ env.create {
+ dbf = bean(DatabaseFacade.class)
+ testTfApi()
+ }
+ }
+
+ @Override
+ void clean() {
+ env.delete()
+ }
+
+ void testTfApi() {
+ def zone = env.inventoryByName("zone") as ZoneInventory
+ def cluster1 = env.inventoryByName("cluster1") as ClusterInventory
+ def cluster2 = env.inventoryByName("cluster2") as ClusterInventory
+ def instanceOffering = env.inventoryByName("instanceOffering") as InstanceOfferingInventory
+ def image = env.inventoryByName("image1") as ImageInventory
+
+ String sql = "select sdn" +
+ " from SdnControllerVO sdn" +
+ " where sdn.vendorType = :vendorType";
+ TypedQuery q = dbf.getEntityManager().createQuery(sql, SdnControllerVO.class);
+ q.setParameter("vendorType", SugonSdnControllerConstant.TF_CONTROLLER);
+ List sdns = q.getResultList();
+ SdnControllerVO sdn = sdns.get(0);
+ updateSdnController {
+ uuid = sdn.uuid
+ name = "sugon_sdn"
+ description = "sugon sdn:tf"
+ }
+ SdnControllerVO vo = dbf.findByUuid(sdn.uuid, SdnControllerVO.class)
+ assert vo.name == "sugon_sdn"
+ assert vo.description == "sugon sdn:tf"
+
+ L2NetworkInventory l2TfNetwork = createL2TfNetwork {
+ name = "tfL2Network"
+ type = SugonSdnControllerConstant.L2_TF_NETWORK_TYPE
+ physicalInterface = sdn.uuid
+ zoneUuid = zone.uuid
+ }
+
+ updateL2Network {
+ uuid = l2TfNetwork.uuid
+ name = "test_tf_l2"
+ description = "test tf l2 network"
+ }
+
+ attachL2NetworkToCluster {
+ l2NetworkUuid = l2TfNetwork.uuid
+ clusterUuid = cluster1.uuid
+ }
+
+ attachL2NetworkToCluster {
+ l2NetworkUuid = l2TfNetwork.uuid
+ clusterUuid = cluster2.uuid
+ }
+
+ detachL2NetworkFromCluster {
+ l2NetworkUuid = l2TfNetwork.uuid
+ clusterUuid = cluster1.uuid
+ }
+
+ List l2TfNetworks = queryL2Network {
+ conditions=["type=" + SugonSdnControllerConstant.L2_TF_NETWORK_TYPE]}
+ assert l2TfNetworks.size() == 1
+
+ L3NetworkInventory test_l3_1 = createL3Network {
+ l2NetworkUuid = l2TfNetwork.uuid
+ name = "test-l3"
+ type = SugonSdnControllerConstant.L3_TF_NETWORK_TYPE
+ }
+
+ List l3TfNetworks = queryL3Network {
+ conditions=["type=" + SugonSdnControllerConstant.L3_TF_NETWORK_TYPE]}
+ assert l3TfNetworks.size() == 1
+
+ updateL3Network {
+ uuid = test_l3_1.uuid
+ name = "test_l3_1"
+ description = "test_l3_1"
+ }
+ L3NetworkVO l3Network = dbf.findByUuid(test_l3_1.uuid, L3NetworkVO.class)
+ assert l3Network.name == "test_l3_1"
+ assert l3Network.description == "test_l3_1"
+
+ addIpRangeByNetworkCidr {
+ name = "Test-IPRange"
+ networkCidr = "192.168.10.0/24"
+ l3NetworkUuid = test_l3_1.uuid
+ }
+
+ L3NetworkInventory l3Inv = addDnsToL3Network {
+ l3NetworkUuid = test_l3_1.uuid
+ dns = "1.1.1.1"
+ }
+ assert l3Inv.dns.get(0) == '1.1.1.1'
+
+ l3Inv = removeDnsFromL3Network {
+ l3NetworkUuid = test_l3_1.uuid
+ dns = "1.1.1.1"
+ }
+ assert l3Inv.dns == null
+
+ VmInstanceInventory vm = createVmInstance {
+ name = "test-vm1"
+ instanceOfferingUuid = instanceOffering.uuid
+ imageUuid = image.uuid
+ l3NetworkUuids = [test_l3_1.uuid]
+ }
+
+ L3NetworkInventory test_l3_2 = createL3Network {
+ l2NetworkUuid = l2TfNetwork.uuid
+ name = "test-l3-2"
+ type = SugonSdnControllerConstant.L3_TF_NETWORK_TYPE
+ }
+
+ addIpRangeByNetworkCidr {
+ name = "Test-IPRange2"
+ networkCidr = "192.168.20.0/24"
+ l3NetworkUuid = test_l3_2.uuid
+ }
+
+ env.simulator(TfCommands.TF_GET_VMI) {
+ VirtualMachineInterface rsp = new VirtualMachineInterface();
+ rsp.name = "5255167d-46c8-4d9e-b4b1-e20c38ce25d9"
+ rsp.uuid = "5255167d-46c8-4d9e-b4b1-e20c38ce25d9"
+ List macList = new ArrayList();
+ macList.add("08:00:27:b4:e1:98");
+ MacAddressesType macAddress = new MacAddressesType(macList);
+ rsp.setMacAddresses(macAddress);
+ Project project = new Project();
+ project.name = TfCommands.TEST_PROJECT_UUID
+ project.uuid = TfCommands.TEST_PROJECT_UUID
+ project.displayName = "admin";
+ rsp.parent = project
+ rsp.instance_ip_back_refs = null
+ String json = ApiSerializer.serializeObject("virtual-machine-interface", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ attachL3NetworkToVm {
+ l3NetworkUuid = test_l3_2.uuid
+ vmInstanceUuid = vm.uuid
+ }
+ VmInstanceInventory result = queryVmInstance {
+ conditions = ["uuid=${vm.uuid}"]
+ }[0]
+ assert result.vmNics.size() == 2
+
+ detachL3NetworkFromVm {
+ vmNicUuid = vm.getVmNics().get(0).uuid
+ }
+ result = queryVmInstance {
+ conditions = ["uuid=${vm.uuid}"]
+ }[0]
+ assert result.vmNics.size() == 1
+
+ destroyVmInstance {
+ uuid = vm.uuid
+ }
+
+ expungeVmInstance{
+ uuid = vm.uuid
+ }
+
+ deleteL3Network {
+ delegate.uuid = test_l3_1.uuid
+ }
+
+ deleteL3Network {
+ delegate.uuid = test_l3_2.uuid
+ }
+
+ l3TfNetworks = queryL3Network {conditions=["type=" + SugonSdnControllerConstant.L3_TF_NETWORK_TYPE]}
+ assert l3TfNetworks.size() == 0
+
+ expectError {
+ removeSdnController {
+ uuid = sdn.uuid
+ }
+ }
+
+ deleteL2Network {
+ delegate.uuid = l2TfNetwork.uuid
+ }
+
+ l2TfNetworks = queryL2Network {conditions=["type=" + SugonSdnControllerConstant.L2_TF_NETWORK_TYPE]}
+ assert l2TfNetworks.size() == 0
+
+ removeSdnController {
+ uuid = sdn.uuid
+ }
+ }
+}
diff --git a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerEnv.groovy b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerEnv.groovy
new file mode 100644
index 0000000000000000000000000000000000000000..00623ff866b77f51472218ae20e6d71a57dc86b0
--- /dev/null
+++ b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerEnv.groovy
@@ -0,0 +1,94 @@
+package org.zstack.test.integration.network.sdnController
+
+import org.zstack.testlib.EnvSpec
+import org.zstack.testlib.Test
+import org.zstack.utils.data.SizeUnit
+
+class SugonSdnControllerEnv {
+ static EnvSpec SdnControllerBasicEnv() {
+ return Test.makeEnv {
+ instanceOffering {
+ name = "instanceOffering"
+ memory = SizeUnit.GIGABYTE.toByte(1)
+ cpu = 1
+ }
+
+ sftpBackupStorage {
+ name = "sftp"
+ url = "/sftp"
+ username = "root"
+ password = "password"
+ hostname = "localhost"
+
+ image {
+ name = "image1"
+ url = "http://zstack.org/download/test.qcow2"
+ }
+
+ image {
+ name = "vr"
+ url = "http://zstack.org/download/vr.qcow2"
+ }
+ }
+
+ zone {
+ name = "zone"
+ description = "test"
+
+ cluster {
+ name = "cluster1"
+ hypervisorType = "KVM"
+
+ kvm {
+ name = "kvm1"
+ managementIp = "127.0.0.1"
+ username = "root"
+ password = "password"
+ }
+
+ kvm {
+ name = "kvm2"
+ managementIp = "127.0.0.2"
+ username = "root"
+ password = "password"
+ }
+
+ kvm {
+ name = "kvm3"
+ managementIp = "127.0.0.3"
+ username = "root"
+ password = "password"
+ }
+ attachPrimaryStorage("local")
+ }
+
+ cluster {
+ name = "cluster2"
+ hypervisorType = "KVM"
+
+ kvm {
+ name = "kvm4"
+ managementIp = "127.0.0.4"
+ username = "root"
+ password = "password"
+ }
+ attachPrimaryStorage("local")
+ }
+ attachBackupStorage("sftp")
+
+ localPrimaryStorage {
+ name = "local"
+ url = "/local_ps"
+ }
+
+ sdnController {
+ vendorType = "TF"
+ name = "tf"
+ ip = "127.0.0.1"
+ userName = "user"
+ password = "password"
+ }
+ }
+ }
+ }
+}
diff --git a/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy b/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy
index a00b3d455888a54151a1c20492d4848fc8d631ed..a8e3d148c64bf732a0368642e4c5a9c5f40d30bc 100644
--- a/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy
+++ b/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy
@@ -1,6 +1,7 @@
package org.zstack.testlib
-
+import org.springframework.http.HttpStatus
+import org.springframework.http.ResponseEntity
import org.zstack.sdk.SdnControllerInventory
import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands
import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.LoginReply
@@ -13,7 +14,15 @@ import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.VniRangeStruct
import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.GetH3cTenantsRsp
import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.H3cTenantStruct
import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.GetH3cTeamLederIpReply
-import org.zstack.testlib.*
+import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant
+import org.zstack.sugonSdnController.controller.api.ApiSerializer
+import org.zstack.sugonSdnController.controller.api.TfCommands
+import org.zstack.sugonSdnController.controller.api.types.Domain
+import org.zstack.sugonSdnController.controller.api.types.MacAddressesType
+import org.zstack.sugonSdnController.controller.api.types.Project
+import org.zstack.sugonSdnController.controller.api.types.VirtualMachine
+import org.zstack.sugonSdnController.controller.api.types.VirtualMachineInterface
+import org.zstack.sugonSdnController.controller.api.types.VirtualNetwork
/**
* Created by shixin.ruan on 2019/09/26.
@@ -127,6 +136,111 @@ class SdnControllerSpec extends Spec implements HasSession {
rsp.ip = "127.1.1.1"
return rsp
}
+
+ simulator(TfCommands.TF_GET_DAEMON) {
+ TfCommands.GetDomainRsp rsp = new TfCommands.GetDomainRsp()
+ rsp.uuid = TfCommands.TEST_DOMAIN_UUID
+ return rsp
+ }
+
+ simulator(TfCommands.TF_GET_DAEMON_DETAIL) {
+ Domain rsp = new Domain()
+ rsp.uuid = TfCommands.TEST_DOMAIN_UUID
+ rsp.name = SugonSdnControllerConstant.TF_DEFAULT_DOMAIN
+ String json = ApiSerializer.serializeObject("domain", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_GET_PROJECT) {
+ Project rsp = new Project();
+ rsp.name = TfCommands.TEST_PROJECT_UUID
+ rsp.uuid = TfCommands.TEST_PROJECT_UUID
+ rsp.displayName = "admin";
+ String json = ApiSerializer.serializeObject("project", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_CREATE_PROJECT) {
+ Project rsp = new Project();
+ rsp.name = TfCommands.TEST_PROJECT_UUID
+ rsp.uuid = TfCommands.TEST_PROJECT_UUID
+ rsp.displayName = "admin";
+ String json = ApiSerializer.serializeObject("project", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_CREATE_NETWORK) {
+ VirtualNetwork rsp = new VirtualNetwork();
+ rsp.name = TfCommands.TEST_L2_UUID
+ rsp.uuid = TfCommands.TEST_L2_UUID
+ String json = ApiSerializer.serializeObject("virtual-network", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_GET_NETWORK) {
+ VirtualNetwork rsp = new VirtualNetwork();
+ rsp.name = TfCommands.TEST_L2_UUID
+ rsp.uuid = TfCommands.TEST_L2_UUID
+ String json = ApiSerializer.serializeObject("virtual-network", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_CREATE_VM) {
+ VirtualMachine rsp = new VirtualMachine();
+ rsp.name = TfCommands.TEST_VM_UUID
+ rsp.uuid = TfCommands.TEST_VM_UUID
+ String json = ApiSerializer.serializeObject("virtual-machine", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_GET_VM) {
+ VirtualMachine rsp = new VirtualMachine();
+ rsp.name = TfCommands.TEST_VM_UUID
+ rsp.uuid = TfCommands.TEST_VM_UUID
+ String json = ApiSerializer.serializeObject("virtual-machine", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_CREATE_VMI) {
+ VirtualMachineInterface rsp = new VirtualMachineInterface();
+ rsp.name = TfCommands.TEST_VMI_UUID
+ rsp.uuid = TfCommands.TEST_VMI_UUID
+ Project project = new Project();
+ project.name = TfCommands.TEST_PROJECT_UUID
+ project.uuid = TfCommands.TEST_PROJECT_UUID
+ project.displayName = "admin";
+ rsp.setParent(project)
+ String json = ApiSerializer.serializeObject("virtual-machine-interface", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
+
+ simulator(TfCommands.TF_GET_VMI) {
+ VirtualMachineInterface rsp = new VirtualMachineInterface();
+ rsp.name = TfCommands.TEST_VMI_UUID
+ rsp.uuid = TfCommands.TEST_VMI_UUID
+ List macList = new ArrayList();
+ macList.add("08:00:27:b4:e1:99");
+ MacAddressesType macAddress = new MacAddressesType(macList);
+ rsp.setMacAddresses(macAddress);
+ Project project = new Project();
+ project.name = TfCommands.TEST_PROJECT_UUID
+ project.uuid = TfCommands.TEST_PROJECT_UUID
+ project.displayName = "admin";
+ rsp.parent = project
+ rsp.instance_ip_back_refs = null
+ String json = ApiSerializer.serializeObject("virtual-machine-interface", rsp);
+ ResponseEntity response = new ResponseEntity(json, HttpStatus.OK);
+ return response.getBody()
+ }
}
}
diff --git a/testlib/src/main/java/org/zstack/testlib/Test.groovy b/testlib/src/main/java/org/zstack/testlib/Test.groovy
index 96194c356165bc9a0a885bcbe84296b4e275361c..47803b40ca008617ac429873fc15e2252841766e 100755
--- a/testlib/src/main/java/org/zstack/testlib/Test.groovy
+++ b/testlib/src/main/java/org/zstack/testlib/Test.groovy
@@ -149,6 +149,8 @@ abstract class Test extends ApiHelper implements Retry {
include("log.xml")
include("HostAllocateExtension.xml")
include("sdnController.xml")
+ include("sugonSdnController.xml")
+ include("TfPortAllocator.xml")
}
}