diff --git a/conf/springConfigXml/sugonSdnController.xml b/conf/springConfigXml/sugonSdnController.xml
index 2ce8f4020283a77fa32170bb4cd9e6ca3ea16a55..66b4de5b33eb577861ac9d577ad1731e1ea3b934 100644
--- a/conf/springConfigXml/sugonSdnController.xml
+++ b/conf/springConfigXml/sugonSdnController.xml
@@ -65,4 +65,11 @@
+
+
+
+
+
+
+
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 aceb28b6b38ac10364b6a3219d46174748132916..448639f20f9e733723982bb7e722719a831b310a 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
@@ -24,11 +24,9 @@ public class TfPortClient {
private ApiConnector apiConnector;
- public TfPortClient(){
- apiConnector = getApiConnector();
- }
+ private String tenantId;
- public ApiConnector getApiConnector() {
+ public TfPortClient(){
SdnControllerVO sdn = Q.New(SdnControllerVO.class).eq(
SdnControllerVO_.vendorType,
SdnControllerConstant.TF_CONTROLLER).find();
@@ -39,10 +37,10 @@ public class TfPortClient {
if (apiConnector == null) {
throw new RuntimeException(String.format("Can not connect to tf sdn controller: %s.", sdn.getIp()));
}
- return apiConnector;
+ tenantId = StringDSL.transToTfUuid(sdn.getAccountUuid());
}
- public TfPortResponse createPort(String l2Id, String l3Id, String mac, String ip, String tenantId,
+ public TfPortResponse createPort(String l2Id, String l3Id, String mac, String ip,
String vmInventeryId, String tfPortUuid, String vmName) {
TfPortRequestResource requestPortResourceEntity = new TfPortRequestResource();
requestPortResourceEntity.setNetworkId(l2Id);
@@ -107,7 +105,7 @@ public class TfPortClient {
if (ip != null) {
try {
- portCreateInstanceIp(netObj, realPort, l3Id, ip, tenantId);
+ portCreateInstanceIp(netObj, realPort, l3Id, ip);
} catch (Exception e) {
try {
apiConnector.delete(realPort);
@@ -120,7 +118,7 @@ public class TfPortClient {
String errmsg = "Bad request trying to create IP instance.";
boolean ipv4PortDelete = false;
try {
- Status ip_result = portCreateInstanceIp(netObj, realPort, l3Id, ip, tenantId);
+ Status ip_result = portCreateInstanceIp(netObj, realPort, l3Id, ip);
if (!ip_result.isSuccess()) {
ipv4PortDelete = true;
logger.error("Tf instance ip create failed.");
@@ -173,7 +171,7 @@ public class TfPortClient {
}
private Status portCreateInstanceIp(VirtualNetwork virtualNetwork, VirtualMachineInterface port,
- String subnetId, String ip, String tenantId) throws IOException {
+ String subnetId, String ip) throws IOException {
InstanceIp ipObj = new InstanceIp();
String ipFamily = "v4";
if (ip != null) {
@@ -293,7 +291,7 @@ public class TfPortClient {
public TfPortResponse getVirtualMachineInterface(String portId) {
try {
- VirtualMachineInterface port = (VirtualMachineInterface) getApiConnector().findById(
+ VirtualMachineInterface port = (VirtualMachineInterface) apiConnector.findById(
VirtualMachineInterface.class, portId);
if (port != null){
return getPortResponse(port);
@@ -305,6 +303,25 @@ public class TfPortClient {
}
}
+ public List getVirtualMachineInterfaceDetail() {
+ try {
+ List result = new ArrayList<>();
+ List ports = (List) apiConnector.list(
+ VirtualMachineInterface.class, Arrays.asList("default-domain", tenantId));
+
+ for (VirtualMachineInterface port : ports) {
+ VirtualMachineInterface detail = (VirtualMachineInterface) apiConnector.findById(
+ VirtualMachineInterface.class, port.getUuid());
+ if (detail == null) {
+ continue;
+ }
+ result.add(detail);
+ }
+ return result;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
public TfPortResponse deletePort(String portId) {
TfPortResponse response = new TfPortResponse();
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java
index 6173846866b7eb70c635e37b5d3884674c69fcab..6a314db0c5f5b1b0cbb88fe68da058c46bfe8961 100644
--- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java
@@ -7,6 +7,7 @@ import org.zstack.compute.vm.StaticIpOperator;
import org.zstack.header.network.l3.L3NetworkInventory;
import org.zstack.header.vm.VmInstanceInventory;
import org.zstack.identity.AccountManager;
+import org.zstack.sugonSdnController.controller.api.types.VirtualMachineInterface;
import org.zstack.sugonSdnController.controller.neutronClient.TfPortClient;
import org.zstack.sugonSdnController.controller.neutronClient.TfPortResponse;
import org.zstack.utils.StringDSL;
@@ -23,13 +24,17 @@ public class TfPortService {
return tfPortClient.getVirtualMachineInterface(tfPortUUid);
}
+ public List getTfPortsDetail() {
+ TfPortClient tfPortClient = new TfPortClient();
+ return tfPortClient.getVirtualMachineInterfaceDetail();
+ }
+
public TfPortResponse createTfPort(String tfPortUUid, String l2NetworkUuid, String l3NetworkUuid, String mac, String ip) {
//invoke tf rest interface to retrieve real ip and mac and portId
TfPortClient tfPortClient = new TfPortClient();
String tfL2NetworkId = StringDSL.transToTfUuid(l2NetworkUuid);
String tfL3NetworkId = StringDSL.transToTfUuid(l3NetworkUuid);
- String accountId = StringDSL.transToTfUuid(acntMgr.getOwnerAccountUuidOfResource(l3NetworkUuid));
- TfPortResponse port = tfPortClient.createPort(tfL2NetworkId, tfL3NetworkId, mac, ip, accountId, null, tfPortUUid, null);
+ TfPortResponse port = tfPortClient.createPort(tfL2NetworkId, tfL3NetworkId, mac, ip, null, tfPortUUid, null);
if (port.getCode() != HttpStatus.OK.value()) {
// fail to rollback the flowchain
throw new RuntimeException("failed to invoke creating tf port: " + port);
@@ -50,10 +55,9 @@ public class TfPortService {
TfPortClient tfPortClient = new TfPortClient();
String tfL2NetworkId = StringDSL.transToTfUuid(l3.getL2NetworkUuid());
String tfL3NetworkId = StringDSL.transToTfUuid(l3.getUuid());
- String accountId = StringDSL.transToTfUuid(acntMgr.getOwnerAccountUuidOfResource(vm.getUuid()));
String vmiUuid = StringDSL.transToTfUuid(vm.getUuid());
String vmName = vm.getName();
- TfPortResponse port = tfPortClient.createPort(tfL2NetworkId, tfL3NetworkId, customMac, customIp, accountId, vmiUuid, tfPortUUid, vmName);
+ TfPortResponse port = tfPortClient.createPort(tfL2NetworkId, tfL3NetworkId, customMac, customIp, vmiUuid, tfPortUUid, vmName);
if (port.getCode() != HttpStatus.OK.value()) {
// fail to rollback the flowchain
throw new RuntimeException("failed to invoke creating tf port: " + port);
diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c2fac65a39f502bdc79cf777d0e780fb7ac5a72
--- /dev/null
+++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java
@@ -0,0 +1,105 @@
+package org.zstack.sugonSdnController.network;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.zstack.core.db.Q;
+import org.zstack.core.thread.PeriodicTask;
+import org.zstack.core.thread.ThreadFacade;
+import org.zstack.header.managementnode.ManagementNodeReadyExtensionPoint;
+import org.zstack.header.vm.VmNicVO;
+import org.zstack.header.vm.VmNicVO_;
+import org.zstack.sdnController.header.SdnControllerVO;
+import org.zstack.sdnController.header.SdnControllerVO_;
+import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant;
+import org.zstack.sugonSdnController.controller.SugonSdnControllerGlobalProperty;
+import org.zstack.sugonSdnController.controller.api.ApiConnector;
+import org.zstack.sugonSdnController.controller.api.ApiConnectorFactory;
+import org.zstack.sugonSdnController.controller.api.types.VirtualMachineInterface;
+import org.zstack.sugonSdnController.controller.neutronClient.TfPortClient;
+import org.zstack.sugonSdnController.controller.neutronClient.TfPortResponse;
+import org.zstack.utils.StringDSL;
+import org.zstack.utils.Utils;
+import org.zstack.utils.logging.CLogger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+public class TfZstackPortSync implements ManagementNodeReadyExtensionPoint {
+
+ @Autowired
+ protected ThreadFacade thdf;
+ private Future trackerThread = null;
+ @Autowired
+ private TfPortService tfPortService;
+ private final static CLogger logger = Utils.getLogger(TfZstackPortSync.class);
+
+ @Override
+ public void managementNodeReady() {
+ if (trackerThread != null) {
+ trackerThread.cancel(true);
+ }
+ trackerThread = thdf.submitPeriodicTask(new SyncPort());
+ }
+
+ private class SyncPort implements PeriodicTask {
+
+ @Override
+ public TimeUnit getTimeUnit() {
+ return TimeUnit.DAYS;
+ }
+
+ @Override
+ public long getInterval() {
+ return 1;
+ }
+
+ @Override
+ public String getName() {
+ return "Period-Task-for-sync-port-between-tf-and-zstack";
+ }
+
+ private HashSet getPortToDelete() {
+ List zstackPortsUuid = Q.New(VmNicVO.class).select(VmNicVO_.uuid).listValues();
+ List tfPortsUuid = new ArrayList<>();
+ try{
+ List tfPorts = tfPortService.getTfPortsDetail();
+ for (VirtualMachineInterface vmi : tfPorts) {
+ if ("neutron:LOADBALANCER".equals(vmi.getDeviceOwner())) {
+ continue;
+ }
+ tfPortsUuid.add(StringDSL.transToZstackUuid(vmi.getUuid()));
+ }
+ } catch (Exception e) {
+ logger.error(String.format("Port_Sync_Task: Fetch tf VirtualMachineInterface failed: %s.", e));
+ return null;
+ }
+ HashSet result = new HashSet<>(tfPortsUuid);
+ result.removeAll(zstackPortsUuid);
+ logger.debug(String.format("Port_Sync_Task: Fetch tf VirtualMachineInterface (%s) to delete.", result));
+ return result;
+ }
+
+ @Override
+ public void run() {
+ logger.info("Port_Sync_Task: begin.");
+ try {
+ HashSet portsToDelete = getPortToDelete();
+ for (String portUuid: portsToDelete) {
+ TfPortResponse response = tfPortService.deleteTfPort(portUuid);
+ if (response.getCode() == 200) {
+ logger.info(String.format("Port_Sync_Task: VirtualMachineInterface: %s delete success.",
+ portUuid));
+ } else {
+ logger.warn(String.format("Port_Sync_Task: VirtualMachineInterface: %s delete failed," +
+ " reason: %s.", portUuid, response.getMsg()));
+ }
+ }
+ } catch (Exception e) {
+ logger.error(String.format("Port_Sync_Task failed: %s.", e));
+ }
+ }
+ }
+}