From 91de70d3d0d8079580a14a11023a65a4b0b11419 Mon Sep 17 00:00:00 2001 From: fuwei Date: Wed, 22 Feb 2023 10:15:57 +0800 Subject: [PATCH] [sugon_sdn]Add period task for sync port between tf and zstack --- conf/springConfigXml/sugonSdnController.xml | 7 ++ .../neutronClient/TfPortClient.java | 37 ++++-- .../network/TfPortService.java | 12 +- .../network/TfZstackPortSync.java | 105 ++++++++++++++++++ 4 files changed, 147 insertions(+), 14 deletions(-) create mode 100644 plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java diff --git a/conf/springConfigXml/sugonSdnController.xml b/conf/springConfigXml/sugonSdnController.xml index 2ce8f40202..66b4de5b33 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 aceb28b6b3..448639f20f 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 6173846866..6a314db0c5 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 0000000000..8c2fac65a3 --- /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)); + } + } + } +} -- Gitee