From e913f32ed63a0ab34fc4b073048a254ae4810f47 Mon Sep 17 00:00:00 2001 From: fuwei Date: Mon, 14 Nov 2022 10:41:32 +0800 Subject: [PATCH 1/2] [sugon_sdn]fix zstack iso build miss sugonSdnController.jar Resolves: Change-Id:f69cf981-0915-4b82-bd09-2d0cd52b7319 --- build/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/pom.xml b/build/pom.xml index 0ad16da49c..b4fac6c222 100755 --- a/build/pom.xml +++ b/build/pom.xml @@ -502,6 +502,11 @@ sdnController ${project.version} + + org.zstack + sugonSdnController + ${project.version} + org.zstack iam2-script-plugin -- Gitee From d50be1b1c8877e3f7b320eebd3f9763c5fb73cc7 Mon Sep 17 00:00:00 2001 From: fuwei Date: Wed, 16 Nov 2022 10:06:05 +0800 Subject: [PATCH 2/2] [sugon_sdn]Add rollback for account api Add rollback for the scenario that zstack success bug tf failed Resolves: Change-Id:d2d9f5c3d7b1453e9c3a72943b2a2846 --- .../BeforeDeleteAccountExtensionPoint.java | 2 +- .../BeforeUpdateAccountExtensionPoint.java | 2 +- .../java/org/zstack/identity/AccountBase.java | 10 +- .../account/AccountSync.java | 17 ++-- .../controller/SugonSdnController.java | 99 ++++++++++++++----- .../controller/TfSdnController.java | 5 +- 6 files changed, 95 insertions(+), 40 deletions(-) diff --git a/header/src/main/java/org/zstack/header/identity/BeforeDeleteAccountExtensionPoint.java b/header/src/main/java/org/zstack/header/identity/BeforeDeleteAccountExtensionPoint.java index 50b68eb89a..c349978495 100644 --- a/header/src/main/java/org/zstack/header/identity/BeforeDeleteAccountExtensionPoint.java +++ b/header/src/main/java/org/zstack/header/identity/BeforeDeleteAccountExtensionPoint.java @@ -6,5 +6,5 @@ package org.zstack.header.identity; * @time: 2022/10/9 */ public interface BeforeDeleteAccountExtensionPoint { - void beforeDeleteAccount(AccountInventory account); + void beforeDeleteAccount(AccountInventory account, AccountVO accountBase); } diff --git a/header/src/main/java/org/zstack/header/identity/BeforeUpdateAccountExtensionPoint.java b/header/src/main/java/org/zstack/header/identity/BeforeUpdateAccountExtensionPoint.java index 285eb860a4..bcf3e93110 100644 --- a/header/src/main/java/org/zstack/header/identity/BeforeUpdateAccountExtensionPoint.java +++ b/header/src/main/java/org/zstack/header/identity/BeforeUpdateAccountExtensionPoint.java @@ -6,5 +6,5 @@ package org.zstack.header.identity; * @time: 2022/10/9 */ public interface BeforeUpdateAccountExtensionPoint { - void beforeUpdateAccount(AccountInventory account); + void beforeUpdateAccount(AccountInventory account, AccountVO accountBase); } diff --git a/identity/src/main/java/org/zstack/identity/AccountBase.java b/identity/src/main/java/org/zstack/identity/AccountBase.java index 8411958ae9..6efd37bc91 100755 --- a/identity/src/main/java/org/zstack/identity/AccountBase.java +++ b/identity/src/main/java/org/zstack/identity/AccountBase.java @@ -1,6 +1,7 @@ package org.zstack.identity; import org.hibernate.exception.ConstraintViolationException; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; @@ -82,7 +83,8 @@ public class AccountBase extends AbstractAccount { private void handle(APIUpdateAccountMsg msg) { AccountVO account = dbf.findByUuid(msg.getUuid(), AccountVO.class); - + final AccountVO accountBase = new AccountVO(); + BeanUtils.copyProperties(account,accountBase); if (msg.getPassword() != null) { for(PasswordUpdateExtensionPoint ext : pluginRgty.getExtensionList(PasswordUpdateExtensionPoint.class)) { ext.preUpdatePassword(account.getUuid(), account.getPassword(), msg.getPassword()); @@ -115,7 +117,7 @@ public class AccountBase extends AbstractAccount { // execute tf extension point final AccountInventory inventory = AccountInventory.valueOf(account); CollectionUtils.safeForEach(pluginRgty.getExtensionList(BeforeUpdateAccountExtensionPoint.class), - arg -> arg.beforeUpdateAccount(inventory)); + arg -> arg.beforeUpdateAccount(inventory,accountBase)); APIUpdateAccountEvent evt = new APIUpdateAccountEvent(msg.getId()); evt.setInventory(AccountInventory.valueOf(account)); @@ -206,7 +208,7 @@ public class AccountBase extends AbstractAccount { private void handle(final APIDeleteAccountMsg msg) { final APIDeleteAccountEvent evt = new APIDeleteAccountEvent(msg.getId()); - + AccountVO accountBase = Q.New(AccountVO.class).eq(AccountVO_.uuid, msg.getUuid()).find(); deleteAccount(new Completion(msg) { @Override public void success() { @@ -214,7 +216,7 @@ public class AccountBase extends AbstractAccount { final AccountInventory inventory = new AccountInventory(); inventory.setUuid(msg.getUuid() ); CollectionUtils.safeForEach(pluginRgty.getExtensionList(BeforeDeleteAccountExtensionPoint.class), - arg -> arg.beforeDeleteAccount(inventory)); + arg -> arg.beforeDeleteAccount(inventory,accountBase)); bus.publish(evt); } diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/account/AccountSync.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/account/AccountSync.java index daed8aa542..bef1d158da 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/account/AccountSync.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/account/AccountSync.java @@ -1,17 +1,14 @@ package org.zstack.sugonSdnController.account; import org.springframework.beans.factory.annotation.Autowired; -import org.zstack.sugonSdnController.controller.SugonSdnController; -import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant; import org.zstack.core.db.Q; -import org.zstack.header.identity.AccountInventory; -import org.zstack.header.identity.BeforeCreateAccountExtensionPoint; -import org.zstack.header.identity.BeforeDeleteAccountExtensionPoint; -import org.zstack.header.identity.BeforeUpdateAccountExtensionPoint; +import org.zstack.header.identity.*; import org.zstack.sdnController.SdnController; import org.zstack.sdnController.SdnControllerManager; import org.zstack.sdnController.header.SdnControllerVO; import org.zstack.sdnController.header.SdnControllerVO_; +import org.zstack.sugonSdnController.controller.SugonSdnController; +import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant; /** * @description: @@ -31,18 +28,18 @@ public class AccountSync implements BeforeCreateAccountExtensionPoint, BeforeUpd } @Override - public void beforeDeleteAccount(AccountInventory account) { + public void beforeDeleteAccount(AccountInventory account, AccountVO accountBase) { SdnControllerVO sdn = Q.New(SdnControllerVO.class).eq(SdnControllerVO_.vendorType, SugonSdnControllerConstant.TF_CONTROLLER).find(); SdnController sdnController = sdnControllerManager.getSdnController(sdn); SugonSdnController sugonSdnController = (SugonSdnController) sdnController; - sugonSdnController.deleteAccount(account); + sugonSdnController.deleteAccount(account,accountBase); } @Override - public void beforeUpdateAccount(AccountInventory account) { + public void beforeUpdateAccount(AccountInventory account, AccountVO accountBase) { SdnControllerVO sdn = Q.New(SdnControllerVO.class).eq(SdnControllerVO_.vendorType, SugonSdnControllerConstant.TF_CONTROLLER).find(); SdnController sdnController = sdnControllerManager.getSdnController(sdn); SugonSdnController sugonSdnController = (SugonSdnController) sdnController; - sugonSdnController.updateAccount(account); + sugonSdnController.updateAccount(account,accountBase); } } 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 e10c9533c2..5b19491a46 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 @@ -2,12 +2,12 @@ package org.zstack.sugonSdnController.controller; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; +import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.db.Q; import org.zstack.header.core.Completion; -import org.zstack.header.identity.AccountInventory; -import org.zstack.header.identity.AccountVO; -import org.zstack.header.identity.AccountVO_; +import org.zstack.header.identity.*; import org.zstack.header.network.l2.APICreateL2NetworkMsg; import org.zstack.header.network.l2.L2NetworkVO; import org.zstack.header.network.l3.*; @@ -38,6 +38,9 @@ public class SugonSdnController implements TfSdnController, SdnController { private SdnControllerVO sdnControllerVO; + @Autowired + protected CloudBus bus; + public SugonSdnController(SdnControllerVO vo) { sdnControllerVO = vo; } @@ -238,25 +241,32 @@ public class SugonSdnController implements TfSdnController, SdnController { public void createAccount(AccountInventory account) { try { ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT); - Domain domain = (Domain) apiConnector.findByFQN(Domain.class, SugonSdnControllerConstant.TF_DEFAULT_DOMAIN); - Project project = new Project(); - project.setParent(domain); - project.setUuid(StringDSL.transToTfUuid(account.getUuid())); - project.setDisplayName(account.getName()); - project.setName(account.getName()); - Status status = apiConnector.create(project); - if (!status.isSuccess()) { - String message = String.format("create tf project[name:%s] failed due to:%s ",account.getName(), "tf api call failed"); - logger.error(message); + Project checkProject = (Project)apiConnector.findById(Project.class,StringDSL.transToTfUuid(account.getUuid())); + if(checkProject==null) { + Domain domain = (Domain) apiConnector.findByFQN(Domain.class, SugonSdnControllerConstant.TF_DEFAULT_DOMAIN); + Project project = new Project(); + project.setParent(domain); + project.setUuid(StringDSL.transToTfUuid(account.getUuid())); + project.setDisplayName(account.getName()); + project.setName(account.getName()); + Status status = apiConnector.create(project); + if (!status.isSuccess()) { + String message = String.format("create tf project[name:%s] failed due to:%s ", account.getName(), "tf api call failed"); + logger.error(message); + //回滚 + createAccountRollback(account); + } } } catch (Exception e){ String message = String.format("create tf project[name:%s] failed due to:%s ",account.getName(), e.getMessage()); logger.error(message, e); + //回滚 + createAccountRollback(account); } } @Override - public void deleteAccount(AccountInventory account) { + public void deleteAccount(AccountInventory account,AccountVO accountBase) { try { ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT); Project project = new Project(); @@ -265,28 +275,39 @@ public class SugonSdnController implements TfSdnController, SdnController { if (!status.isSuccess()) { String message = String.format("delete tf project[name:%s] failed due to:%s ",account.getName(), "tf api call failed"); logger.error(message); + // 回滚 + deleteAccountRollback(accountBase); } } catch (Exception e){ String message = String.format("delete tf project[name:%s] failed due to:%s ",account.getName(), e.getMessage()); logger.error(message, e); + // 回滚 + deleteAccountRollback(accountBase); } } @Override - public void updateAccount(AccountInventory account) { + public void updateAccount(AccountInventory account,AccountVO accountBase) { try { ApiConnector apiConnector = ApiConnectorFactory.build(sdnControllerVO.getIp(), SugonSdnControllerGlobalProperty.TF_CONTROLLER_PORT); - Project project = new Project(); - project.setUuid(StringDSL.transToTfUuid(account.getUuid())); - project.setDisplayName(account.getName()); - Status status = apiConnector.update(project); - if (!status.isSuccess()) { - String message = String.format("update tf project[name:%s] failed due to:%s ",account.getName(), "tf api call failed"); - logger.error(message); + Project checkProject = (Project)apiConnector.findById(Project.class,StringDSL.transToTfUuid(account.getUuid())); + if(!checkProject.getDisplayName().equals(account.getName())) { + Project project = new Project(); + project.setUuid(StringDSL.transToTfUuid(account.getUuid())); + project.setDisplayName(account.getName()); + Status status = apiConnector.update(project); + if (!status.isSuccess()) { + String message = String.format("update tf project[name:%s] failed due to:%s ", account.getName(), "tf api call failed"); + logger.error(message); + // 回滚 + updateAccountRollback(accountBase); + } } } catch (Exception e){ String message = String.format("update tf project[name:%s] failed due to:%s ",account.getName(), e.getMessage()); logger.error(message, e); + // 回滚 + updateAccountRollback(accountBase); } } @@ -644,4 +665,38 @@ public class SugonSdnController implements TfSdnController, SdnController { String enableDHCP = L3NetworkSystemTags.ENABLE_DHCP.getTokenByResourceUuid(l3Uuid, L3NetworkSystemTags.ENABLE_DHCP_TOKEN); return Boolean.parseBoolean(enableDHCP); } + + private void createAccountRollback(AccountInventory account){ + DeleteAccountMsg msg = new DeleteAccountMsg(); + msg.setUuid(account.getUuid()); + msg.setServiceId(bus.makeLocalServiceId(AccountConstant.SERVICE_ID)); + + bus.send(msg); + } + + private void updateAccountRollback(AccountVO accountBase){ + APIUpdateAccountMsg msg = new APIUpdateAccountMsg(); + msg.setDescription(accountBase.getDescription()); + msg.setName(accountBase.getName()); + msg.setPassword(accountBase.getPassword()); + msg.setUuid(accountBase.getUuid()); + msg.setServiceId(bus.makeLocalServiceId(AccountConstant.SERVICE_ID)); + SessionInventory sessionInventory = new SessionInventory(); + sessionInventory.setAccountUuid(accountBase.getUuid()); + msg.setSession(sessionInventory); + + bus.send(msg); + } + + private void deleteAccountRollback(AccountVO accountBase){ + APICreateAccountMsg msg = new APICreateAccountMsg(); + msg.setPassword(accountBase.getPassword()); + msg.setResourceUuid(accountBase.getUuid()); + msg.setName(accountBase.getName()); + msg.setDescription(accountBase.getDescription()); + msg.setType(accountBase.getType().name()); + msg.setServiceId(bus.makeLocalServiceId(AccountConstant.SERVICE_ID)); + + bus.send(msg); + } } diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/TfSdnController.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/TfSdnController.java index d278b476b3..847b3678e8 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/TfSdnController.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/TfSdnController.java @@ -2,6 +2,7 @@ package org.zstack.sugonSdnController.controller; import org.zstack.header.core.Completion; import org.zstack.header.identity.AccountInventory; +import org.zstack.header.identity.AccountVO; import org.zstack.header.network.l2.APICreateL2NetworkMsg; import org.zstack.header.network.l2.L2NetworkVO; import org.zstack.header.network.l3.*; @@ -16,8 +17,8 @@ public interface TfSdnController { // 账号同步:zstack->tf void createAccount(AccountInventory account); - void deleteAccount(AccountInventory account); - void updateAccount(AccountInventory account); + void deleteAccount(AccountInventory account, AccountVO accountBase); + void updateAccount(AccountInventory account, AccountVO accountBase); // L3网络:zstack->tf void deleteL3Network(L3NetworkVO l3NetworkVO, Completion completion); -- Gitee