diff --git a/build/pom.xml b/build/pom.xml index 0ad16da49c57950659a386b3f8da600b0cd89328..b4fac6c222df2667142a4962efa3c5dac00096b9 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 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 50b68eb89a4c9245dcd50b4baecd164ac4b28b85..c349978495c735cc60dde85968f105e5a04d46f1 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 285eb860a4f3f30ca0df7ee5c7fc86c69084ad41..bcf3e93110a10f3cc65a71ff100e0f8e21ab7ed6 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 8411958ae925b777182eaade0415101455a46abb..6efd37bc9112ce89f26500e042549d6cfa5862bc 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 daed8aa5425b498fe808ff129cb85f07a4a8dea1..bef1d158dab85302337946635fa0f82f0e6401ca 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 e10c9533c2e5fd4ad5494ac4e04219ad2a7678c9..5b19491a463df72793aeb024ad672b860b2e5d4e 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 d278b476b38fae01272e6bc54891cb8089226e43..847b3678e8146a15529e2c796fdfdb41f9e60117 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);