From f09a837105ec1f24c05db695367b11fbe604697c Mon Sep 17 00:00:00 2001 From: "tao.gan" Date: Thu, 15 Jan 2026 14:06:14 +0800 Subject: [PATCH] [storage]: res sblk APIImpact Resolves: ZSV-1 Change-Id: I70637377776e777070676c6a6c616e74786b6667 --- .../APITakeoverPrimaryStorageEvent.java | 40 +++++++++ .../primary/APITakeoverPrimaryStorageMsg.java | 38 ++++++++ .../primary/TakeoverPrimaryStorageMsg.java | 16 ++++ .../primary/TakeoverPrimaryStorageReply.java | 6 ++ .../storage/primary/PrimaryStorageBase.java | 86 +++++++++++++++++++ 5 files changed, 186 insertions(+) create mode 100644 header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageEvent.java create mode 100644 header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageMsg.java create mode 100644 header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageMsg.java create mode 100644 header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageReply.java diff --git a/header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageEvent.java b/header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageEvent.java new file mode 100644 index 00000000000..5960db506da --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageEvent.java @@ -0,0 +1,40 @@ +package org.zstack.header.storage.primary; + +import org.zstack.header.message.APIEvent; +import org.zstack.header.rest.RestResponse; + +import java.util.Collections; + +@RestResponse(allTo = "inventory") +public class APITakeoverPrimaryStorageEvent extends APIEvent { + private PrimaryStorageInventory inventory; + + public APITakeoverPrimaryStorageEvent() { + } + + public APITakeoverPrimaryStorageEvent(String apiId) { + super(apiId); + } + + public PrimaryStorageInventory getInventory() { + return inventory; + } + + public void setInventory(PrimaryStorageInventory inventory) { + this.inventory = inventory; + } + + public static APITakeoverPrimaryStorageEvent __example__() { + APITakeoverPrimaryStorageEvent event = new APITakeoverPrimaryStorageEvent(); + + PrimaryStorageInventory ps = new PrimaryStorageInventory(); + ps.setName("PS1"); + ps.setUrl("/zstack_ps"); + ps.setType("LocalStorage"); + ps.setAttachedClusterUuids(Collections.singletonList(uuid())); + + event.setInventory(ps); + return event; + } + +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageMsg.java b/header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageMsg.java new file mode 100644 index 00000000000..075f8efe38f --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/APITakeoverPrimaryStorageMsg.java @@ -0,0 +1,38 @@ +package org.zstack.header.storage.primary; + +import org.springframework.http.HttpMethod; +import org.zstack.header.message.APIMessage; +import org.zstack.header.message.APIParam; +import org.zstack.header.rest.RestRequest; + +@RestRequest( + path = "/primary-storage/{uuid}/takeover", + responseClass = APITakeoverPrimaryStorageEvent.class, + method = HttpMethod.PUT, + isAction = true +) +public class APITakeoverPrimaryStorageMsg extends APIMessage implements PrimaryStorageMessage { + @APIParam(resourceType = PrimaryStorageVO.class) + private String uuid; + + @Override + public String getPrimaryStorageUuid() { + return uuid; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public static APITakeoverPrimaryStorageMsg __example__() { + APITakeoverPrimaryStorageMsg msg = new APITakeoverPrimaryStorageMsg(); + + msg.setUuid(uuid(PrimaryStorageVO.class)); + + return msg; + } +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageMsg.java b/header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageMsg.java new file mode 100644 index 00000000000..04ed7a5a4cd --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageMsg.java @@ -0,0 +1,16 @@ +package org.zstack.header.storage.primary; + +import org.zstack.header.message.NeedReplyMessage; + +public class TakeoverPrimaryStorageMsg extends NeedReplyMessage implements PrimaryStorageMessage { + private String primaryStorageUuid; + + @Override + public String getPrimaryStorageUuid() { + return primaryStorageUuid; + } + + public void setPrimaryStorageUuid(String primaryStorageUuid) { + this.primaryStorageUuid = primaryStorageUuid; + } +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageReply.java b/header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageReply.java new file mode 100644 index 00000000000..7ff2e971582 --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/TakeoverPrimaryStorageReply.java @@ -0,0 +1,6 @@ +package org.zstack.header.storage.primary; + +import org.zstack.header.message.MessageReply; + +public class TakeoverPrimaryStorageReply extends MessageReply { +} \ No newline at end of file diff --git a/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java b/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java index b7f8cfbc24d..6be2e552a92 100755 --- a/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java +++ b/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java @@ -177,6 +177,10 @@ public void setNewAdded(boolean newAdded) { protected abstract void handle(GetVolumeSnapshotEncryptedOnPrimaryStorageMsg msg); + protected void takeoverHook(Completion completion){ + completion.success(); + } + public PrimaryStorageBase(PrimaryStorageVO self) { this.self = self; } @@ -603,6 +607,22 @@ public void fail(ErrorCode errorCode) { }); } + protected void handle(TakeoverPrimaryStorageMsg msg) { + TakeoverPrimaryStorageReply reply = new TakeoverPrimaryStorageReply(); + doTakeover(new ConnectParam(), new Completion(msg) { + @Override + public void success() { + bus.reply(msg, reply); + } + + @Override + public void fail(ErrorCode errorCode) { + reply.setError(errorCode); + bus.reply(msg, reply); + } + }); + } + private void handle(ChangePrimaryStorageStatusMsg msg) { changeStatus(PrimaryStorageStatus.valueOf(msg.getStatus())); ChangePrimaryStorageStatusReply reply = new ChangePrimaryStorageStatusReply(); @@ -695,6 +715,51 @@ public String getName() { }); } + private void doTakeover(ConnectParam param, final Completion completion) { + thdf.chainSubmit(new ChainTask(completion) { + @Override + public String getSyncSignature() { + return getSyncId(); + } + + @Override + public void run(SyncTaskChain chain) { + takeoverHook(new Completion(chain, completion) { + @Override + public void success() { + self = dbf.reload(self); + logger.debug(String.format("successfully reload primary storage[uuid:%s]", self.getUuid())); + + tracker.track(self.getUuid()); + + completion.success(); + chain.next(); + } + + @Override + public void fail(ErrorCode errorCode) { + tracker.track(self.getUuid()); + + self = dbf.reload(self); + if (changeStatus(PrimaryStorageStatus.Disconnected) && !errorCode.isError(PrimaryStorageErrors.DISCONNECTED)) { + fireDisconnectedCanonicalEvent(errorCode); + } + + logger.debug(String.format("failed to connect primary storage[uuid:%s], %s", self.getUuid(), errorCode)); + + completion.fail(errorCode); + chain.next(); + } + }); + } + + @Override + public String getName() { + return String.format("reconnect-primary-storage-%s", self.getUuid()); + } + }); + } + private void handle(final ConnectPrimaryStorageMsg msg) { final ConnectPrimaryStorageReply reply = new ConnectPrimaryStorageReply(); @@ -1397,6 +1462,27 @@ public void run(MessageReply reply) { }); } + protected void handle(APITakeoverPrimaryStorageMsg msg) { + final APITakeoverPrimaryStorageEvent evt = new APITakeoverPrimaryStorageEvent(msg.getId()); + + TakeoverPrimaryStorageMsg rmsg = new TakeoverPrimaryStorageMsg(); + rmsg.setPrimaryStorageUuid(msg.getPrimaryStorageUuid()); + bus.makeTargetServiceIdByResourceUuid(rmsg, PrimaryStorageConstant.SERVICE_ID, rmsg.getPrimaryStorageUuid()); + bus.send(rmsg, new CloudBusCallBack(msg) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + evt.setError(reply.getError()); + } else { + self = dbf.reload(self); + evt.setInventory(getSelfInventory()); + } + + bus.publish(evt); + } + }); + } + // don't use chainTask for this method, the sub-sequential DetachPrimaryStorageFromClusterMsg // is in the queue protected void handle(final APIDetachPrimaryStorageFromClusterMsg msg) {