From 4063c6bafd525bde59c545c4bf298eb335a7e55a Mon Sep 17 00:00:00 2001 From: LamGC Date: Sat, 16 Jul 2022 01:08:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=E8=AE=A1=E7=AE=97?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E5=90=8E=E6=94=AF=E6=8C=81=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=BC=95=E5=AF=BC=E5=8D=B7.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 先前做删除实例的时候忘记了引导卷, 现在补上(半半半成品, 还差点细节). --- src/main/kotlin/OracleServerExtension.kt | 127 +++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/src/main/kotlin/OracleServerExtension.kt b/src/main/kotlin/OracleServerExtension.kt index 4c92d03..57119ff 100644 --- a/src/main/kotlin/OracleServerExtension.kt +++ b/src/main/kotlin/OracleServerExtension.kt @@ -1,6 +1,8 @@ package net.lamgc.scext.oraclemanager import com.google.gson.JsonElement +import com.google.gson.reflect.TypeToken +import com.oracle.bmc.core.BlockstorageClient import com.oracle.bmc.core.ComputeClient import com.oracle.bmc.core.VirtualNetworkClient import com.oracle.bmc.core.model.* @@ -224,6 +226,14 @@ class OracleServerExtension(private val bot: BaseAbilityBot) : AbilityExtension val client = ComputeClient(profile.getAuthenticationDetailsProvider()) val instanceInfo = ServerInstance.fromJson(upd.callbackQuery.callbackData.extraData[JsonFields.ServerInstance]) try { + val bootVolumeAttachments = client.listBootVolumeAttachments( + ListBootVolumeAttachmentsRequest.builder() + .instanceId(instanceInfo.id) + .compartmentId(profile.tenantId) + .availabilityDomain(instanceInfo.availabilityDomain) + .build() + ).items.map { it.bootVolumeId }.toList() + client.terminateInstance( TerminateInstanceRequest.builder() .instanceId(instanceInfo.id) @@ -234,6 +244,19 @@ class OracleServerExtension(private val bot: BaseAbilityBot) : AbilityExtension .messageId(upd.callbackQuery.message.messageId) .chatId(upd.callbackQuery.message.chatId.toString()) .replyMarkup(InlineKeyboardGroupBuilder() + .rowButton { + text("删除引导卷") + callbackData( + upd.callbackQuery.callbackData.next( + "oc_server_remove_bootvolume", + jsonObjectOf { + JsonFields.AccountProfile += profile + JsonFields.BootVolumeIds += bootVolumeAttachments + }, + replaceData = true + ) + ) + } .rowButton { text("<<< 回到服务器列表") callbackData(upd.callbackQuery.callbackData.next("oc_server_list", jsonObjectOf { @@ -248,6 +271,110 @@ class OracleServerExtension(private val bot: BaseAbilityBot) : AbilityExtension } } + fun removeBootVolumePrompt(): Reply = callbackQueryOf("oc_server_remove_bootvolume") { bot, upd -> + val profile = getProfileByCallback(upd.callbackQuery.callbackData) + val client = BlockstorageClient(profile.getAuthenticationDetailsProvider()) + val bootVolumeIds = + gson.fromJson>( + upd.callbackQuery.callbackData.extraData[JsonFields.BootVolumeIds], + object : TypeToken>() {}.type + ) + + if (bootVolumeIds.isEmpty()) { + bot.silent().send("没有需要删除的引导卷。", upd.callbackQuery.message.chatId) + return@callbackQueryOf + } + + val msgBuilder = StringBuilder( + """ + 确定要删除以下引导卷? + """.trimIndent() + ).append('\n') + + for (bootVolumeId in bootVolumeIds) { + val bootVolume = client.getBootVolume( + GetBootVolumeRequest.builder() + .bootVolumeId(bootVolumeId) + .build() + ).bootVolume + msgBuilder.append("- ${bootVolume.displayName}(${bootVolume.sizeInGBs} GB)") + } + + EditMessageText.builder() + .chatId(upd.callbackQuery.message.chatId.toString()) + .messageId(upd.callbackQuery.message.messageId) + .replyMarkup( + createPromptKeyboard( + yesCallback = upd.callbackQuery.callbackData.next("oc_server_remove_bootvolume::execute"), + noCallback = upd.callbackQuery.callbackData.next("oc_server_list") + ) + ) + .text(msgBuilder.toString()) + .build().execute(bot) + } + + fun removeBootVolumeExecute(): Reply = callbackQueryOf("oc_server_remove_bootvolume::execute") { bot, upd -> + val profile = getProfileByCallback(upd.callbackQuery.callbackData) + val client = BlockstorageClient(profile.getAuthenticationDetailsProvider()) + val bootVolumeIds = + gson.fromJson>( + upd.callbackQuery.callbackData.extraData[JsonFields.BootVolumeIds], + object : TypeToken>() {}.type + ) + + if (bootVolumeIds.isEmpty()) { + bot.silent().send("没有需要删除的引导卷。", upd.callbackQuery.message.chatId) + return@callbackQueryOf + } + + // FIXME: 由于实例仍未释放完成, 引导卷依然挂载在实例上, 会导致引导卷删除失败. + + val msgBuilder = StringBuilder("引导卷删除结果:").append('\n') + var hasError = false + var errorVolume: BootVolume? = null + var error: BmcException? = null + for (bootVolumeId in bootVolumeIds) { + val bootVolume = client.getBootVolume( + GetBootVolumeRequest.builder() + .bootVolumeId(bootVolumeId) + .build() + ).bootVolume + if (hasError) { + msgBuilder.append("[跳过] ${bootVolume.displayName}").append('\n') + continue + } + try { + client.deleteBootVolume( + DeleteBootVolumeRequest.builder() + .bootVolumeId(bootVolumeId) + .build() + ) + msgBuilder.append("[成功] ${bootVolume.displayName}").append('\n') + } catch (e: BmcException) { + hasError = true + errorVolume = bootVolume + error = e + msgBuilder.append("[错误] ${bootVolume.displayName}").append('\n') + } + } + + if (hasError && errorVolume != null) { + msgBuilder.append("\n\n").append("引导卷 ${errorVolume.displayName} (${errorVolume.sizeInGBs} GB) 删除失败:\n") + .append(error!!.message) + } + + EditMessageText.builder() + .chatId(upd.callbackQuery.message.chatId.toString()) + .messageId(upd.callbackQuery.message.messageId) + .replyMarkup( + InlineKeyboardGroupBuilder() + .addBackButton(upd.callbackQuery.callbackData.next("oc_server_list")) + .build() + ) + .text(msgBuilder.toString()) + .build().execute(bot) + } + fun editServerPower(): Reply = callbackQueryOf("oc_server_power_edit") { bot, upd -> val keyboardBuilder = InlineKeyboardGroupBuilder() .rowButton {