diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/node/service/impl/NodeServiceImpl.java b/dsms-engine-application/src/main/java/com/dsms/modules/node/service/impl/NodeServiceImpl.java index 608c2cbf52e4733a7c586ef4c11498d1680dcb48..42ce8de1fbb13ca39e49824b5dab3d79584c46c6 100644 --- a/dsms-engine-application/src/main/java/com/dsms/modules/node/service/impl/NodeServiceImpl.java +++ b/dsms-engine-application/src/main/java/com/dsms/modules/node/service/impl/NodeServiceImpl.java @@ -142,6 +142,10 @@ public class NodeServiceImpl implements INodeService { //obtain the info of osd occupied by the storage pool for (Device device : devices) { try { + //ignore the devices which is not osd + if (ObjectUtils.isEmpty(device.getOsdId())) { + continue; + } OSDResult osd = osdApi.getOsdById(RemoteCallUtil.generateRemoteRequest(), device.getOsdId()); if (osd.getPools().size() != 0) { ResponseStoragePool storagePoolByPoolId = storagePoolApi.getStoragePoolByPoolId(RemoteCallUtil.generateRemoteRequest(), osd.getPools().get(0)); @@ -151,8 +155,12 @@ public class NodeServiceImpl implements INodeService { log.warn("get osd's pool info from dsms-storage fail", e); } } + //count pool used osd long poolUsedDevice = devices.stream().filter(device -> device.getUsedPool() != null).count(); node.setPoolUsedDevice((int) poolUsedDevice); + //count all osd + long nodeUsedDevice = devices.stream().filter(device -> device.getOsdId() != null).count(); + node.setNodeUsedDevice((int) nodeUsedDevice); node.setDevices(devices); return node; diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/controller/StoragePoolController.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/controller/StoragePoolController.java index ee34632b5aa2df5ae984a439fd217affdace936f..65bb7daf5e90b751131ac5e6e3b52937cdf1f329 100644 --- a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/controller/StoragePoolController.java +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/controller/StoragePoolController.java @@ -18,13 +18,14 @@ package com.dsms.modules.storagepool.controller; import com.dsms.common.constant.StoragePoolTypeEnum; import com.dsms.common.model.Result; +import com.dsms.dfsbroker.node.model.dto.NodeDto; import com.dsms.dfsbroker.osd.ecprofile.model.dto.EcProfileDto; import com.dsms.dfsbroker.storagepool.model.StoragePool; -import com.dsms.dfsbroker.storagepool.model.dto.ErasureCreateDTO; -import com.dsms.dfsbroker.storagepool.model.dto.ReplicatedCreateDTO; -import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolCreateDTO; +import com.dsms.dfsbroker.storagepool.model.dto.*; import com.dsms.dfsbroker.storagepool.service.IStoragePoolService; import com.dsms.modules.storagepool.model.vo.StoragePoolCreateVO; +import com.dsms.modules.storagepool.model.vo.StoragePoolDiskManageVO; +import com.dsms.modules.storagepool.model.vo.StoragePoolNodeManageVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; @@ -80,4 +81,58 @@ public class StoragePoolController { } return Result.OK(storagePoolService.create(storagePoolCreateDTO)); } + + @ApiOperation("存储池模块-获取存储池所有已使用的节点、磁盘") + @PostMapping("/list_used_disk") + public Result> listUsedDisk(@RequestBody StoragePoolNodeManageVO storagePoolNodeManageVO) { + List storagePoolList = storagePoolService.listUsedDisk(storagePoolNodeManageVO.getPoolName()); + return Result.OK(storagePoolList); + } + + @ApiOperation("存储池模块-获取存储池在某节点未使用的磁盘") + @PostMapping("/list_unused_disk") + public Result listUnusedDisk(@RequestBody StoragePoolNodeManageVO storagePoolNodeManageVO) { + NodeDto storagePoolList = storagePoolService.listUnusedDisk(storagePoolNodeManageVO.getPoolName(), storagePoolNodeManageVO.getNodeName()); + return Result.OK(storagePoolList); + } + + @ApiOperation("存储池模块-存储池添加节点") + @PostMapping("/add_node") + public Result addNode(@RequestBody StoragePoolNodeManageVO storagePoolNodeManageVO) { + StoragePoolNodeManageDTO storagePoolNodeManageDTO = new StoragePoolNodeManageDTO( + storagePoolNodeManageVO.getPoolName(), + storagePoolNodeManageVO.getNodeNames() + ); + return Result.OK(storagePoolService.addNode(storagePoolNodeManageDTO)); + } + + @ApiOperation("存储池模块-存储池移除节点") + @PostMapping("/remove_node") + public Result removeNode(@RequestBody StoragePoolNodeManageVO storagePoolNodeManageVO) { + StoragePoolNodeManageDTO storagePoolNodeManageDTO = new StoragePoolNodeManageDTO( + storagePoolNodeManageVO.getPoolName(), + storagePoolNodeManageVO.getNodeName() + ); + return Result.OK(storagePoolService.removeNode(storagePoolNodeManageDTO)); + } + + @ApiOperation("存储池模块-存储池添加磁盘") + @PostMapping("/add_disk") + public Result addDisk(@RequestBody StoragePoolDiskManageVO storagePoolDiskManageVO) { + StoragePoolDiskManageDTO storagePoolDiskManageDTO = new StoragePoolDiskManageDTO( + storagePoolDiskManageVO.getPoolName(), + storagePoolDiskManageVO.getOsd() + ); + return Result.OK(storagePoolService.addDisk(storagePoolDiskManageDTO)); + } + + @ApiOperation("存储池模块-存储池移除磁盘") + @PostMapping("/remove_disk") + public Result removeDisk(@RequestBody StoragePoolDiskManageVO storagePoolDiskManageVO) { + StoragePoolDiskManageDTO storagePoolDiskManageDTO = new StoragePoolDiskManageDTO( + storagePoolDiskManageVO.getPoolName(), + storagePoolDiskManageVO.getOsd() + ); + return Result.OK(storagePoolService.removeDisk(storagePoolDiskManageDTO)); + } } diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/model/vo/StoragePoolDiskManageVO.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/model/vo/StoragePoolDiskManageVO.java new file mode 100644 index 0000000000000000000000000000000000000000..5acf831443e50b29a39828b7d55c61d8bf1a106f --- /dev/null +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/model/vo/StoragePoolDiskManageVO.java @@ -0,0 +1,41 @@ +/* + * Copyright 2022 The DSMS Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.dsms.modules.storagepool.model.vo; + +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolDiskManageDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; + +@ApiModel(value = "存储池磁盘管理VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class StoragePoolDiskManageVO { + @ApiModelProperty(value = "存储池名称", example = "pool1") + @NotBlank(message = "存储池名称不能为空") + private String poolName; + + @ApiModelProperty(value = "节点名称", example = "node1") + private StoragePoolDiskManageDTO.Osd osd; +} diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/model/vo/StoragePoolNodeManageVO.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/model/vo/StoragePoolNodeManageVO.java new file mode 100644 index 0000000000000000000000000000000000000000..4259480f3498859fceef792c23174626d1f464a4 --- /dev/null +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/model/vo/StoragePoolNodeManageVO.java @@ -0,0 +1,46 @@ +/* + * Copyright 2022 The DSMS Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.dsms.modules.storagepool.model.vo; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@ApiModel(value = "存储池节点管理VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class StoragePoolNodeManageVO { + @ApiModelProperty(value = "存储池名称", example = "pool1") + private String poolName; + + //use to remove single node of storage pool + @ApiModelProperty(value = "节点名称", example = "node1") + private String nodeName; + + //use to add nodes of storage pool + @ApiModelProperty(value = "节点名称列表", example = "['node1','node2']") + @JsonProperty("nodeNames") + private List nodeNames; +} diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/service/impl/StoragePoolImpl.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/service/impl/StoragePoolImpl.java index fe81699c58c7235c6a1e65e4acf9dc546161d400..f8f80e149469e5f7627d7d4d26fceface45481ff 100644 --- a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/service/impl/StoragePoolImpl.java +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/service/impl/StoragePoolImpl.java @@ -19,6 +19,7 @@ package com.dsms.modules.storagepool.service.impl; import cn.hutool.json.JSONUtil; import com.dsms.common.constant.*; import com.dsms.common.exception.DsmsEngineException; +import com.dsms.common.remotecall.model.RemoteResponse; import com.dsms.common.taskmanager.TaskContext; import com.dsms.common.taskmanager.model.AsyncStep; import com.dsms.common.taskmanager.model.AsyncTask; @@ -29,9 +30,17 @@ import com.dsms.common.taskmanager.service.ITaskService; import com.dsms.common.util.ByteUtil; import com.dsms.dfsbroker.filesystem.api.FileSystemApi; import com.dsms.dfsbroker.filesystem.model.remote.FsLsResponse; +import com.dsms.dfsbroker.node.model.Device; +import com.dsms.dfsbroker.node.model.Node; +import com.dsms.dfsbroker.node.model.dto.NodeDto; +import com.dsms.dfsbroker.node.service.INodeService; +import com.dsms.dfsbroker.osd.crushmap.api.CrushmapApi; +import com.dsms.dfsbroker.osd.crushmap.model.remote.CrushmapBucket; import com.dsms.dfsbroker.storagepool.api.StoragePoolApi; import com.dsms.dfsbroker.storagepool.model.StoragePool; import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolCreateDTO; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolDiskManageDTO; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolNodeManageDTO; import com.dsms.dfsbroker.storagepool.model.remote.DfResponse; import com.dsms.dfsbroker.storagepool.model.remote.ResponseStoragePool; import com.dsms.dfsbroker.storagepool.service.IStoragePoolService; @@ -43,6 +52,7 @@ import org.springframework.util.ObjectUtils; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Service @Slf4j @@ -54,6 +64,9 @@ public class StoragePoolImpl implements IStoragePoolService { @Autowired FileSystemApi fileSystemApi; + @Autowired + CrushmapApi crushmapApi; + @Autowired private ITaskService taskService; @@ -63,6 +76,11 @@ public class StoragePoolImpl implements IStoragePoolService { @Autowired private TaskContext taskContext; + @Autowired + private INodeService nodeService; + + private RemoteResponse response; + @Override public List list() { List storagePoolList = new ArrayList<>(); @@ -137,6 +155,48 @@ public class StoragePoolImpl implements IStoragePoolService { return storagePoolList; } + @Override + public NodeDto listUnusedDisk(String poolName, String nodeName) { + //get current node's device info + Node nodeInfo = nodeService.getNodeInfo(nodeName); + //collect the unused osd + List device = nodeInfo.getDevices().stream().filter(n -> !ObjectUtils.nullSafeEquals(n.getOsdId(), null) + && !ObjectUtils.nullSafeEquals(n.getUsedPool(), poolName)).collect(Collectors.toList()); + return new NodeDto(nodeInfo.getNodeId(), nodeInfo.getNodeName(), nodeInfo.getPoolUsedDevice(), nodeInfo.getNodeAllDevice(), device); + } + + @Override + public List listUsedDisk(String poolName) { + List nodeNames = new ArrayList<>(); + List nodeDtoList = new ArrayList<>(); + try { + //get current pool's host bucket in crushmap + CrushmapBucket crushmapBuckets = crushmapApi.getCrushmapBuckets(RemoteCallUtil.generateRemoteRequest()); + for (CrushmapBucket.BucketsDTO bucket : crushmapBuckets.getBuckets()) { + //host bucketName construct with poolName + BUCKET_NAME_CONNECTOR("_") + nodeName. example:pool1_node1 + //ceph also create a bucket named bucketName + AUTO_GENERATED_BUCKET_NAME_CONNECTOR("~") + "hdd"/"ssd", it's useless for dsms-engine,so we should ignore them + if (bucket.getName().startsWith(poolName + CrushmapConst.BUCKET_NAME_CONNECTOR) && !bucket.getName().contains(CrushmapConst.AUTO_GENERATED_BUCKET_NAME_CONNECTOR)) { + //get node's name + String nodeName = bucket.getName().split(CrushmapConst.BUCKET_NAME_CONNECTOR)[1]; + nodeNames.add(nodeName); + } + } + } catch (Throwable e) { + log.error("get pool's bucket error:" + e.getMessage()); + throw new RuntimeException(e); + } + + for (String nodeName : nodeNames) { + //get every single node's device info + Node nodeInfo = nodeService.getNodeInfo(nodeName); + //collect the used osd + List device = nodeInfo.getDevices().stream().filter(n -> ObjectUtils.nullSafeEquals(n.getUsedPool(), poolName)).collect(Collectors.toList()); + NodeDto nodeDto = new NodeDto(nodeInfo.getNodeId(), nodeInfo.getNodeName(), device); + nodeDtoList.add(nodeDto); + } + return nodeDtoList; + } + @Override public boolean create(StoragePoolCreateDTO storagePoolCreateDTO) { if (ObjectUtils.isEmpty(storagePoolCreateDTO)) { @@ -155,13 +215,102 @@ public class StoragePoolImpl implements IStoragePoolService { if (taskService.save(task)) { return createStepTask(task.getId(), storagePoolCreateDTO.getPoolName(), StoragePoolTypeEnum.getPoolType(storagePoolCreateDTO.getPoolType())); } - + + log.error("the task for creating storage pool has been created failed"); + return false; + } + + @Override + public boolean addNode(StoragePoolNodeManageDTO storagePoolNodeManageDto) { + if (ObjectUtils.isEmpty(storagePoolNodeManageDto)) { + log.error("storagePoolNodeManageDto can not be empty"); + return false; + } + + Task task = new AsyncTask( + TaskTypeEnum.POOL_ADD_NODE.getName(), + TaskTypeEnum.POOL_ADD_NODE.getType(), + TaskStatusEnum.QUEUE.getStatus(), + TaskTypeEnum.POOL_ADD_NODE.getName() + ":" + storagePoolNodeManageDto.getPoolName(), + JSONUtil.toJsonStr(storagePoolNodeManageDto)); + + if (taskService.save(task)) { + return addNodeStepTask(task.getId(), storagePoolNodeManageDto); + } + log.error("the task for creating storage pool has been created failed"); return false; } + @Override + public boolean removeNode(StoragePoolNodeManageDTO storagePoolNodeManageDto) { + if (ObjectUtils.isEmpty(storagePoolNodeManageDto)) { + log.error("storagePoolNodeManageDto can not be empty"); + return false; + } + + Task task = new AsyncTask( + TaskTypeEnum.POOL_REMOVE_NODE.getName(), + TaskTypeEnum.POOL_REMOVE_NODE.getType(), + TaskStatusEnum.QUEUE.getStatus(), + TaskTypeEnum.POOL_REMOVE_NODE.getName() + ":" + storagePoolNodeManageDto.getPoolName(), + JSONUtil.toJsonStr(storagePoolNodeManageDto)); + + if (taskService.save(task)) { + return removeNodeStepTask(task.getId(), storagePoolNodeManageDto); + } + + log.error("the task for remove node for storage pool has been created failed"); + return false; + + } + + @Override + public boolean addDisk(StoragePoolDiskManageDTO storagePoolDiskManageDto) { + if (ObjectUtils.isEmpty(storagePoolDiskManageDto)) { + log.error("storagePoolNodeManageDto can not be empty"); + return false; + } + + Task task = new AsyncTask( + TaskTypeEnum.POOL_ADD_DISK.getName(), + TaskTypeEnum.POOL_ADD_DISK.getType(), + TaskStatusEnum.QUEUE.getStatus(), + TaskTypeEnum.POOL_ADD_DISK.getName() + ":" + storagePoolDiskManageDto.getPoolName(), + JSONUtil.toJsonStr(storagePoolDiskManageDto)); + + if (taskService.save(task)) { + return addDiskStepTask(task.getId(), storagePoolDiskManageDto); + } + + log.error("the task for remove node for storage pool has been created failed"); + return false; + } + + @Override + public boolean removeDisk(StoragePoolDiskManageDTO storagePoolDiskManageDto) { + if (ObjectUtils.isEmpty(storagePoolDiskManageDto)) { + log.error("storagePoolNodeManageDto can not be empty"); + return false; + } + + Task task = new AsyncTask( + TaskTypeEnum.POOL_REMOVE_DISK.getName(), + TaskTypeEnum.POOL_REMOVE_DISK.getType(), + TaskStatusEnum.QUEUE.getStatus(), + TaskTypeEnum.POOL_REMOVE_DISK.getName() + ":" + storagePoolDiskManageDto.getPoolName(), + JSONUtil.toJsonStr(storagePoolDiskManageDto)); + + if (taskService.save(task)) { + return removeDiskStepTask(task.getId(), storagePoolDiskManageDto); + } + + log.error("the task for remove node for storage pool has been created failed"); + return false; + } + /* - create step tasks base the main task + create pool step tasks base the main task */ private boolean createStepTask(int taskId, String poolName, String poolType) { //1.create root bucket step @@ -230,4 +379,87 @@ public class StoragePoolImpl implements IStoragePoolService { log.error("the task for creating storage pool has been created failed"); return false; } + + /* + pool add node step tasks base the main task + */ + private boolean addNodeStepTask(int taskId, StoragePoolNodeManageDTO storagePoolNodeManageDto) { + String poolName = storagePoolNodeManageDto.getPoolName(); + for (String nodeName : storagePoolNodeManageDto.getNodeNames()) { + Step createBucketStep = new AsyncStep( + taskId, + StepTypeEnum.CREATE_HOST_BUCKET.getName(), + StepTypeEnum.CREATE_HOST_BUCKET.getType(), + StepTypeEnum.CREATE_HOST_BUCKET.getName() + ":" + poolName + CrushmapConst.BUCKET_NAME_CONNECTOR + nodeName, + TaskStatusEnum.QUEUE.getStatus(), + nodeName); + if (!stepService.save(createBucketStep)) { + log.error("the task for creating bucket has been created failed"); + return false; + } + } + return true; + } + + /* + pool remove node step tasks base the main task + */ + private boolean removeNodeStepTask(int taskId, StoragePoolNodeManageDTO storagePoolNodeManageDto) { + String poolName = storagePoolNodeManageDto.getPoolName(); + String nodeName = storagePoolNodeManageDto.getNodeName(); + Step deleteBucketStep = new AsyncStep( + taskId, + StepTypeEnum.DELETE_HOST_BUCKET.getName(), + StepTypeEnum.DELETE_HOST_BUCKET.getType(), + StepTypeEnum.DELETE_HOST_BUCKET.getName() + ":" + poolName + CrushmapConst.BUCKET_NAME_CONNECTOR + nodeName, + TaskStatusEnum.QUEUE.getStatus(), + nodeName); + if (!stepService.save(deleteBucketStep)) { + log.error("the task for delete bucket has been created failed"); + return false; + } + return true; + } + + /* + add disk step tasks base the main task + */ + private boolean addDiskStepTask(int taskId, StoragePoolDiskManageDTO storagePoolDiskManageDto) { + String poolName = storagePoolDiskManageDto.getPoolName(); + for (int osdid : storagePoolDiskManageDto.getOsd().getOsdIds()) { + Step addDiskStep = new AsyncStep( + taskId, + StepTypeEnum.POOL_ADD_DISK.getName(), + StepTypeEnum.POOL_ADD_DISK.getType(), + StepTypeEnum.POOL_ADD_DISK.getName() + ":" + poolName + CrushmapConst.BUCKET_NAME_CONNECTOR + poolName, + TaskStatusEnum.QUEUE.getStatus(), + String.valueOf(osdid)); + if (!stepService.save(addDiskStep)) { + log.error("the task for pool add disk has been created failed"); + return false; + } + } + return true; + } + + /* + remove disk step tasks base the main task + */ + private boolean removeDiskStepTask(int taskId, StoragePoolDiskManageDTO storagePoolDiskManageDto) { + String poolName = storagePoolDiskManageDto.getPoolName(); + for (int osdid : storagePoolDiskManageDto.getOsd().getOsdIds()) { + Step removeDiskStep = new AsyncStep( + taskId, + StepTypeEnum.POOL_REMOVE_DISK.getName(), + StepTypeEnum.POOL_REMOVE_DISK.getType(), + StepTypeEnum.POOL_REMOVE_DISK.getName() + ":" + poolName + CrushmapConst.BUCKET_NAME_CONNECTOR + poolName, + TaskStatusEnum.QUEUE.getStatus(), + String.valueOf(osdid)); + if (!stepService.save(removeDiskStep)) { + log.error("the task for pool remove disk has been created failed"); + return false; + } + } + return true; + } } diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/GetCrushmapStepResult.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/GetCrushmapStepResult.java new file mode 100644 index 0000000000000000000000000000000000000000..b2999b85a593055a123d15398cfd3873013cd086 --- /dev/null +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/GetCrushmapStepResult.java @@ -0,0 +1,89 @@ +/* + * Copyright 2022 The DSMS Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.dsms.modules.storagepool.task; + +import com.alibaba.fastjson2.JSON; +import com.dsms.common.constant.RemoteResponseStatusEnum; +import com.dsms.common.constant.TaskStatusEnum; +import com.dsms.common.remotecall.model.FailedDetail; +import com.dsms.common.remotecall.model.FinishedDetail; +import com.dsms.common.remotecall.model.RemoteResponse; +import com.dsms.common.taskmanager.TaskException; +import com.dsms.common.taskmanager.model.Step; +import com.dsms.common.taskmanager.service.IStepService; +import com.dsms.dfsbroker.osd.crushmap.api.CrushmapApi; +import com.dsms.modules.util.RemoteCallUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import java.util.List; +import java.util.Objects; + +@Component +public class GetCrushmapStepResult { + @Autowired + CrushmapApi crushmapApi; + @Autowired + IStepService stepService; + + /** + * this function used to get the response of update crushmap, and according response to update the step in database + * + * @param step + * @param executeResponse the response of dsms-broker's asynchronous request + * @param require the required string used to determine whether the task was successful + * @param errMsg the step error message prefix. example: pool add node failed + * @return Step + * @throws Throwable + */ + public Step getStepResponse(Step step, RemoteResponse executeResponse, String require, String errMsg) throws Throwable { + //get response of step request + RemoteResponse resultResponse = crushmapApi.getUpdateCrushmapResult(RemoteCallUtil.generateRemoteRequest(), executeResponse.getId()); + + //analytic response result + if (Objects.equals(resultResponse.getState(), RemoteResponseStatusEnum.SUCCESS.getMessage())) { + List finished = resultResponse.getFinished(); + String outs = finished.get(0).getOuts(); + String outb = finished.get(0).getOutb(); + String out = StringUtils.hasText(outs) ? outs : outb; + if (Objects.equals(require, out) || out.startsWith(require)) { + step.setStepStatus(TaskStatusEnum.FINISH.getStatus()); + } else { + step.setStepErrorMessage(out); + step.setStepStatus(TaskStatusEnum.FAIL.getStatus()); + stepService.updateById(step); + throw new TaskException(errMsg + ":" + out); + } + } else if (Objects.equals(resultResponse.getState(), RemoteResponseStatusEnum.FAILED.getMessage())) { + List failed = resultResponse.getFailed(); + String outs = failed.get(0).getOuts(); + String outb = failed.get(0).getOutb(); + String out = StringUtils.hasText(outs) ? outs : outb; + step.setStepErrorMessage(out); + step.setStepStatus(TaskStatusEnum.FAIL.getStatus()); + stepService.updateById(step); + throw new TaskException(errMsg + "," + out); + } else if (ObjectUtils.isEmpty(resultResponse.getState())) { + stepService.updateById(step); + throw new TaskException("unknown request state,response:" + JSON.toJSONString(resultResponse)); + } + stepService.updateById(step); + return step; + } +} diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolAddDiskTask.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolAddDiskTask.java new file mode 100644 index 0000000000000000000000000000000000000000..d21804cf5458dca3e10068c675162a2283a0ec6e --- /dev/null +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolAddDiskTask.java @@ -0,0 +1,92 @@ +package com.dsms.modules.storagepool.task; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.dsms.common.constant.*; +import com.dsms.common.exception.DsmsEngineException; +import com.dsms.common.remotecall.model.RemoteResponse; +import com.dsms.common.taskmanager.TaskStrategy; +import com.dsms.common.taskmanager.model.Step; +import com.dsms.common.taskmanager.model.Task; +import com.dsms.common.taskmanager.service.IStepService; +import com.dsms.common.taskmanager.service.ITaskService; +import com.dsms.dfsbroker.osd.crushmap.api.CrushmapApi; +import com.dsms.dfsbroker.osd.osd.api.OsdApi; +import com.dsms.dfsbroker.osd.osd.model.remote.OSDResult; +import com.dsms.dfsbroker.osd.osd.request.UpdateOsdBucketRequest; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolDiskManageDTO; +import com.dsms.modules.util.RemoteCallUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.time.LocalDateTime; +import java.util.List; + + +@Slf4j +@Service(TaskTypeEnum.TypeConstants.POOL_ADD_DISK) +public class StoragePoolAddDiskTask implements TaskStrategy { + @Autowired + OsdApi osdApi; + @Autowired + private CrushmapApi crushmapApi; + @Autowired + private ITaskService taskService; + @Autowired + private IStepService stepService; + @Autowired + private GetCrushmapStepResult getCrushmapStepResult; + + @Override + public Task execute(Task task) { + String taskParam = task.getTaskParam(); + if (ObjectUtils.isEmpty(taskParam)) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + return task; + } + StoragePoolDiskManageDTO storagePoolDiskManageDTO = JSONUtil.toBean(taskParam, StoragePoolDiskManageDTO.class); + String poolName = storagePoolDiskManageDTO.getPoolName(); + String nodeName = storagePoolDiskManageDTO.getOsd().getNodeName(); + //get step task + Integer taskId = task.getId(); + List steps = stepService.list(new LambdaQueryWrapper().eq(Step::getTaskId, taskId)); + for (Step step : steps) { + try { + int osdId = Integer.parseInt(step.getStepParam()); + OSDResult osd = osdApi.getOsdById(RemoteCallUtil.generateRemoteRequest(), osdId); + //check if osd is existed + if (ObjectUtils.isEmpty(osd.getOsd())) { + throw new DsmsEngineException(ResultCode.POOL_DISKNOTEXIST_ERROR); + } + //check if osd has been used + if (osd.getPools().size() != 0) { + throw new DsmsEngineException(ResultCode.POOL_DISKUSEDD_ERROR); + } + + //construct the host bucket name. example: pool1_node1 + String bucketName = poolName + CrushmapConst.BUCKET_NAME_CONNECTOR + nodeName; + //move osd in crushmap + RemoteResponse response = osdApi.updateOsdBucketRequest(RemoteCallUtil.generateRemoteRequest(), osdId, CrushFailureDomainEnum.HOST, bucketName); + getCrushmapStepResult.getStepResponse(step, response, String.format(UpdateOsdBucketRequest.UPDATE_SUCCESS, osdId, osdId, bucketName), ResultCode.POOL_ADDDISK_ERROR.getMessage()); + } catch (Throwable e) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + task.setTaskErrorMessage(e.getMessage()); + return task; + } + } + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FINISH.getStatus()); + return task; + } + + @Override + public boolean validateTask(String[] validateParam) { + return false; + } + +} + diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolAddNodeTask.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolAddNodeTask.java new file mode 100644 index 0000000000000000000000000000000000000000..3d94a04d618b1969d8d9fa22a2571aa983eca5db --- /dev/null +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolAddNodeTask.java @@ -0,0 +1,79 @@ +package com.dsms.modules.storagepool.task; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.dsms.common.constant.*; +import com.dsms.common.remotecall.model.RemoteResponse; +import com.dsms.common.taskmanager.TaskStrategy; +import com.dsms.common.taskmanager.model.Step; +import com.dsms.common.taskmanager.model.Task; +import com.dsms.common.taskmanager.service.IStepService; +import com.dsms.common.taskmanager.service.ITaskService; +import com.dsms.dfsbroker.osd.crushmap.api.CrushmapApi; +import com.dsms.dfsbroker.osd.crushmap.request.CreateBucketRequest; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolNodeManageDTO; +import com.dsms.modules.util.RemoteCallUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.time.LocalDateTime; +import java.util.List; + + +@Slf4j +@Service(TaskTypeEnum.TypeConstants.POOL_ADD_NODE) +public class StoragePoolAddNodeTask implements TaskStrategy { + @Autowired + private CrushmapApi crushmapApi; + + @Autowired + private ITaskService taskService; + + @Autowired + private IStepService stepService; + + @Autowired + private GetCrushmapStepResult getCrushmapStepResult; + + @Override + public Task execute(Task task) { + String taskParam = task.getTaskParam(); + if (ObjectUtils.isEmpty(taskParam)) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + return task; + } + StoragePoolNodeManageDTO storagePoolNodeManageDTO = JSONUtil.toBean(taskParam, StoragePoolNodeManageDTO.class); + String poolName = storagePoolNodeManageDTO.getPoolName(); + //get step task + Integer taskId = task.getId(); + List steps = stepService.list(new LambdaQueryWrapper().eq(Step::getTaskId, taskId)); + for (Step step : steps) { + String nodeName = step.getStepParam(); + //construct the host bucket name. example: pool1_node1 + String hostBucketName = storagePoolNodeManageDTO.getPoolName() + CrushmapConst.BUCKET_NAME_CONNECTOR + nodeName; + try { + //create bucket in crushmap + RemoteResponse response = crushmapApi.createBucket(RemoteCallUtil.generateRemoteRequest(), hostBucketName, CrushFailureDomainEnum.HOST.getTypeId(), poolName); + getCrushmapStepResult.getStepResponse(step, response, String.format(CreateBucketRequest.Create_HOST_BUCKET_SUCCESS, hostBucketName, storagePoolNodeManageDTO.getPoolName()), ResultCode.POOL_ADDNODE_ERROR.getMessage()); + } catch (Throwable e) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + task.setTaskErrorMessage(e.getMessage()); + return task; + } + } + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FINISH.getStatus()); + return task; + } + + @Override + public boolean validateTask(String[] validateParam) { + return false; + } + +} + diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolRemoveDiskTask.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolRemoveDiskTask.java new file mode 100644 index 0000000000000000000000000000000000000000..4cac60b669c10986110893b98d6addddb777613e --- /dev/null +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolRemoveDiskTask.java @@ -0,0 +1,79 @@ +package com.dsms.modules.storagepool.task; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.dsms.common.constant.CrushFailureDomainEnum; +import com.dsms.common.constant.ResultCode; +import com.dsms.common.constant.TaskStatusEnum; +import com.dsms.common.constant.TaskTypeEnum; +import com.dsms.common.remotecall.model.RemoteResponse; +import com.dsms.common.taskmanager.TaskStrategy; +import com.dsms.common.taskmanager.model.Step; +import com.dsms.common.taskmanager.model.Task; +import com.dsms.common.taskmanager.service.IStepService; +import com.dsms.common.taskmanager.service.ITaskService; +import com.dsms.dfsbroker.osd.crushmap.api.CrushmapApi; +import com.dsms.dfsbroker.osd.osd.api.OsdApi; +import com.dsms.dfsbroker.osd.osd.request.UpdateOsdBucketRequest; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolDiskManageDTO; +import com.dsms.modules.util.RemoteCallUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.time.LocalDateTime; +import java.util.List; + + +@Slf4j +@Service(TaskTypeEnum.TypeConstants.POOL_REMOVE_DISK) +public class StoragePoolRemoveDiskTask implements TaskStrategy { + @Autowired + OsdApi osdApi; + @Autowired + private CrushmapApi crushmapApi; + @Autowired + private ITaskService taskService; + @Autowired + private IStepService stepService; + @Autowired + private GetCrushmapStepResult getCrushmapStepResult; + + @Override + public Task execute(Task task) { + String taskParam = task.getTaskParam(); + if (ObjectUtils.isEmpty(taskParam)) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + return task; + } + StoragePoolDiskManageDTO storagePoolDiskManageDTO = JSONUtil.toBean(taskParam, StoragePoolDiskManageDTO.class); + String nodeName = storagePoolDiskManageDTO.getOsd().getNodeName(); + //get step task + Integer taskId = task.getId(); + List steps = stepService.list(new LambdaQueryWrapper().eq(Step::getTaskId, taskId)); + for (Step step : steps) { + try { + int osdId = Integer.parseInt(step.getStepParam()); + RemoteResponse response = osdApi.updateOsdBucketRequest(RemoteCallUtil.generateRemoteRequest(), osdId, CrushFailureDomainEnum.HOST, nodeName); + getCrushmapStepResult.getStepResponse(step, response, String.format(UpdateOsdBucketRequest.UPDATE_SUCCESS, osdId, osdId, nodeName), ResultCode.POOL_REMOVEDISK_ERROR.getMessage()); + } catch (Throwable e) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + task.setTaskErrorMessage(e.getMessage()); + return task; + } + } + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FINISH.getStatus()); + return task; + } + + @Override + public boolean validateTask(String[] validateParam) { + return false; + } + +} + diff --git a/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolRemoveNodeTask.java b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolRemoveNodeTask.java new file mode 100644 index 0000000000000000000000000000000000000000..31af7f444d1959a998c65b824913a2945e290c70 --- /dev/null +++ b/dsms-engine-application/src/main/java/com/dsms/modules/storagepool/task/StoragePoolRemoveNodeTask.java @@ -0,0 +1,80 @@ +package com.dsms.modules.storagepool.task; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.dsms.common.constant.CrushmapConst; +import com.dsms.common.constant.ResultCode; +import com.dsms.common.constant.TaskStatusEnum; +import com.dsms.common.constant.TaskTypeEnum; +import com.dsms.common.remotecall.model.RemoteResponse; +import com.dsms.common.taskmanager.TaskStrategy; +import com.dsms.common.taskmanager.model.Step; +import com.dsms.common.taskmanager.model.Task; +import com.dsms.common.taskmanager.service.IStepService; +import com.dsms.common.taskmanager.service.ITaskService; +import com.dsms.dfsbroker.osd.crushmap.api.CrushmapApi; +import com.dsms.dfsbroker.osd.crushmap.request.DelBucketRequest; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolNodeManageDTO; +import com.dsms.modules.util.RemoteCallUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.time.LocalDateTime; +import java.util.List; + + +@Slf4j +@Service(TaskTypeEnum.TypeConstants.POOL_REMOVE_NODE) +public class StoragePoolRemoveNodeTask implements TaskStrategy { + @Autowired + private CrushmapApi crushmapApi; + + @Autowired + private ITaskService taskService; + + @Autowired + private IStepService stepService; + @Autowired + private GetCrushmapStepResult getCrushmapStepResult; + + @Override + public Task execute(Task task) { + String taskParam = task.getTaskParam(); + if (ObjectUtils.isEmpty(taskParam)) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + return task; + } + StoragePoolNodeManageDTO storagePoolNodeManageDTO = JSONUtil.toBean(taskParam, StoragePoolNodeManageDTO.class); + //get step task + Integer taskId = task.getId(); + List steps = stepService.list(new LambdaQueryWrapper().eq(Step::getTaskId, taskId)); + for (Step step : steps) { + String nodeName = step.getStepParam(); + //construct the host bucket name. example: pool1_node1 + String hostBucketName = storagePoolNodeManageDTO.getPoolName() + CrushmapConst.BUCKET_NAME_CONNECTOR + nodeName; + try { + //delete bucket in crushmap + RemoteResponse response = crushmapApi.delBucket(RemoteCallUtil.generateRemoteRequest(), hostBucketName); + getCrushmapStepResult.getStepResponse(step, response, DelBucketRequest.DELETE_BUCKET_SUCCESS, ResultCode.POOL_REMOVENODE_ERROR.getMessage()); + } catch (Throwable e) { + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FAIL.getStatus()); + task.setTaskErrorMessage(e.getMessage()); + return task; + } + } + task.setTaskEndTime(LocalDateTime.now()); + task.setTaskStatus(TaskStatusEnum.FINISH.getStatus()); + return task; + } + + @Override + public boolean validateTask(String[] validateParam) { + return false; + } + +} + diff --git a/dsms-engine-common/src/main/java/com/dsms/common/constant/CrushmapConst.java b/dsms-engine-common/src/main/java/com/dsms/common/constant/CrushmapConst.java new file mode 100644 index 0000000000000000000000000000000000000000..502fd22713b8d52b45ab07e868e638c1f1d8e5a7 --- /dev/null +++ b/dsms-engine-common/src/main/java/com/dsms/common/constant/CrushmapConst.java @@ -0,0 +1,28 @@ +/* + * Copyright 2022 The DSMS Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.dsms.common.constant; + +public class CrushmapConst { + /** + * bucket name's connective character + */ + public static final String BUCKET_NAME_CONNECTOR = "_"; + /** + * automatically generated bucket name's connective character + */ + public static final String AUTO_GENERATED_BUCKET_NAME_CONNECTOR = "~"; +} diff --git a/dsms-engine-common/src/main/java/com/dsms/common/constant/ResultCode.java b/dsms-engine-common/src/main/java/com/dsms/common/constant/ResultCode.java index 24f37eff65cfba1635e5b0371e18e6aafe3a6fc7..d18f598f850d40412dd46899219eb6824ef15c5a 100644 --- a/dsms-engine-common/src/main/java/com/dsms/common/constant/ResultCode.java +++ b/dsms-engine-common/src/main/java/com/dsms/common/constant/ResultCode.java @@ -60,9 +60,16 @@ public enum ResultCode { NODE_REMOVE_OSD_TASK_EXIST(1207, "节点移除磁盘任务已存在"), NODE_ADD_OSD_TASK_EXIST(1208, "节点管理磁盘任务已存在"), - POOL_LISTPOOL_ERROR(1300,"获取存储池信息失败"), - POOL_GETPOOLCAPACITY_ERROR(1301,"获取存储池容量信息失败"), - POOL_GETFILESYSTEM_ERROR(1302,"获取存储池文件系统使用信息失败"), + POOL_LISTPOOL_ERROR(1300, "获取存储池信息失败"), + POOL_GETPOOLCAPACITY_ERROR(1301, "获取存储池容量信息失败"), + POOL_GETFILESYSTEM_ERROR(1302, "获取存储池文件系统使用信息失败"), + POOL_CREATEPOOL_ERROR(1303, "创建存储池失败"), + POOL_DISKUSEDD_ERROR(1304, "磁盘已被其余存储池使用"), + POOL_ADDDISK_ERROR(1305, "新增磁盘失败"), + POOL_DISKNOTEXIST_ERROR(1306, "磁盘不存在"), + POOL_REMOVEDISK_ERROR(1307, "移除磁盘失败"), + POOL_ADDNODE_ERROR(1308, "新增节点失败"), + POOL_REMOVENODE_ERROR(1309, "移除节点失败"), FS_LIST_ERROR(1401,"获取文件系统信息失败") ; diff --git a/dsms-engine-common/src/main/java/com/dsms/common/constant/StepTypeEnum.java b/dsms-engine-common/src/main/java/com/dsms/common/constant/StepTypeEnum.java index 490f1e83df6be621dbedeb6824679f5379203b9a..5f757137445bfdd0fe7cee2dae53fa5f462d4a93 100644 --- a/dsms-engine-common/src/main/java/com/dsms/common/constant/StepTypeEnum.java +++ b/dsms-engine-common/src/main/java/com/dsms/common/constant/StepTypeEnum.java @@ -34,6 +34,10 @@ public enum StepTypeEnum { * create a host bucket in crushmap */ CREATE_HOST_BUCKET("create_host_bucket", "创建host级bucket"), + /** + * delete a host bucket in crushmap + */ + DELETE_HOST_BUCKET("delete_host_bucket", "删除host级bucket"), /** * create a rule in crushmap */ @@ -49,7 +53,16 @@ public enum StepTypeEnum { /** * create a erasure storage pool */ - CREATE_ERASURE_POOL("create_erasure_pool", "创建纠删码池"); + CREATE_ERASURE_POOL("create_erasure_pool", "创建纠删码池"), + /** + * storage pool add disk + */ + POOL_ADD_DISK("pool_add_disk", "存储池添加磁盘"), + /** + * storage pool remove disk + */ + POOL_REMOVE_DISK("pool_remove_disk", "存储池移除磁盘"), + ; private final String type; private final String name; diff --git a/dsms-engine-common/src/main/java/com/dsms/common/constant/TaskTypeEnum.java b/dsms-engine-common/src/main/java/com/dsms/common/constant/TaskTypeEnum.java index f77747895d72ca7320b9bff936848237042f84a2..7dfca5d256c5ab208eae2aa2735ab08fc89c3028 100644 --- a/dsms-engine-common/src/main/java/com/dsms/common/constant/TaskTypeEnum.java +++ b/dsms-engine-common/src/main/java/com/dsms/common/constant/TaskTypeEnum.java @@ -38,7 +38,18 @@ public enum TaskTypeEnum { /** * create pool task */ - CREATE_POOL(TypeConstants.CREATE_POOL, "创建存储池"); + CREATE_POOL(TypeConstants.CREATE_POOL, "创建存储池"), + /** + * pool add node task + */ + POOL_ADD_NODE(TypeConstants.POOL_ADD_NODE, "存储池添加节点"), + /** + * pool remove node task + */ + POOL_REMOVE_NODE(TypeConstants.POOL_REMOVE_NODE, "存储池移除节点"), + POOL_ADD_DISK(TypeConstants.POOL_ADD_DISK, "存储池添加磁盘"), + POOL_REMOVE_DISK(TypeConstants.POOL_REMOVE_DISK, "存储池移除磁盘"), + ; private final String type; private final String name; @@ -51,6 +62,10 @@ public enum TaskTypeEnum { public static final String ADD_OSD = "add_osd"; public static final String REMOVE_OSD = "remove_osd"; public static final String CREATE_POOL = "create_pool"; + public static final String POOL_ADD_NODE = "pool_add_node"; + public static final String POOL_REMOVE_NODE = "pool_remove_node"; + public static final String POOL_ADD_DISK = "pool_add_disk"; + public static final String POOL_REMOVE_DISK = "pool_remove_disk"; } diff --git a/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/AsyncStep.java b/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/AsyncStep.java index 4ee1082487741900736c2721bdbb515af9d7ba8e..7106e38919955c1e949e0b745787d73dd33607b6 100644 --- a/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/AsyncStep.java +++ b/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/AsyncStep.java @@ -26,4 +26,8 @@ public class AsyncStep extends Step { public AsyncStep(Integer id, String stepName, String stepType, String stepMessage, Integer stepStatus) { super(id, stepName, stepType, stepMessage, stepStatus); } + + public AsyncStep(Integer id, String stepName, String stepType, String stepMessage, Integer stepStatus, String stepParam) { + super(id, stepName, stepType, stepMessage, stepStatus, stepParam); + } } diff --git a/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/Step.java b/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/Step.java index 6ae39ca27eed381dc29cbdea08cb50ef9ffc3773..3f121bc7622d60d5ea39c102b01355fe415e7093 100644 --- a/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/Step.java +++ b/dsms-engine-common/src/main/java/com/dsms/common/taskmanager/model/Step.java @@ -75,4 +75,14 @@ public class Step implements Serializable { this.stepMessage = stepMessage; this.stepStatus = stepStatus; } + + public Step(Integer taskId, String stepName, String stepType, String stepMessage, Integer stepStatus, String stepParam) { + this.taskId = taskId; + this.stepName = stepName; + this.stepType = stepType; + this.stepMessage = stepMessage; + this.stepStatus = stepStatus; + this.stepParam = stepParam; + } + } diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/node/model/dto/NodeDto.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/node/model/dto/NodeDto.java index c4203cc78c80e60a8a9f673bf1d49c61b78ffc1b..288c9c5911f91856fbd18fe51ee546d6b298ede3 100644 --- a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/node/model/dto/NodeDto.java +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/node/model/dto/NodeDto.java @@ -18,14 +18,12 @@ package com.dsms.dfsbroker.node.model.dto; import com.dsms.dfsbroker.node.model.Device; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @NoArgsConstructor -@AllArgsConstructor @Data public class NodeDto { @@ -33,7 +31,26 @@ public class NodeDto { private String nodeId; @JsonProperty("nodeName") private String nodeName; + //the number of usable osd on node + @JsonProperty("usedDevice") + private Integer usedDevice; + //the number of all osd on node + @JsonProperty("totalDevice") + private Integer totalDevice; @JsonProperty("nodeDevices") private List nodeDevices; + public NodeDto(String nodeId, String nodeName, List nodeDevices) { + this.nodeId = nodeId; + this.nodeName = nodeName; + this.nodeDevices = nodeDevices; + } + + public NodeDto(String nodeId, String nodeName, Integer usedDevice, Integer totalDevice, List nodeDevices) { + this.nodeId = nodeId; + this.nodeName = nodeName; + this.nodeDevices = nodeDevices; + this.usedDevice = usedDevice; + this.totalDevice = totalDevice; + } } diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/api/CrushmapApi.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/api/CrushmapApi.java index 6676f24377a1f4c7c91cd058c305147aa713011b..c7fc0e0dd897ee284bf803698f09b4cda23fccdd 100644 --- a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/api/CrushmapApi.java +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/api/CrushmapApi.java @@ -16,6 +16,7 @@ package com.dsms.dfsbroker.osd.crushmap.api; +import com.dsms.common.constant.RemoteResponseStatusEnum; import com.dsms.common.remotecall.model.RemoteRequest; import com.dsms.common.remotecall.model.RemoteResponse; import com.dsms.dfsbroker.common.CommandDirector; @@ -24,6 +25,9 @@ import com.dsms.dfsbroker.osd.crushmap.model.remote.CrushmapBucket; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + @Component public class CrushmapApi { public static final int MAX_RETRIES = 3; @@ -58,7 +62,19 @@ public class CrushmapApi { */ public RemoteResponse getUpdateCrushmapResult(RemoteRequest remoteRequest, String requestId) throws Throwable { CommandDirector.constructGetRequest(remoteRequest, requestId); - return commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class); + + boolean flag = true; + int pendingRetrys = 0; + RemoteResponse response = null; + while (flag && pendingRetrys < MAX_RETRIES) { + response = commonApi.remoteCall(remoteRequest, MAX_RETRIES, RemoteResponse.class); + if (!Objects.equals(response.getState(), RemoteResponseStatusEnum.PENDING.getMessage())) { + flag = false; + } + pendingRetrys++; + TimeUnit.SECONDS.sleep(1); + } + return response; } /** diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/model/remote/CrushmapBucket.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/model/remote/CrushmapBucket.java index 3e150434ac80ff949e55dcbdade1ade3d79585d2..c5e7326363af04a44786de41a4cfe880c690601a 100644 --- a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/model/remote/CrushmapBucket.java +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/model/remote/CrushmapBucket.java @@ -40,6 +40,7 @@ public class CrushmapBucket { private Integer id; @JsonProperty("name") private String name; + //the crush failure domain id of bucket @JsonProperty("type_id") private Integer typeId; //the bucket type name,only support "HOST" and "ROOT" now diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/request/DelBucketRequest.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/request/DelBucketRequest.java index 58804374db3ef1e04a339bc983af40b42ed3ddc0..da2d5ab09729aca2193cd68c04a456240eafed3e 100644 --- a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/request/DelBucketRequest.java +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/crushmap/request/DelBucketRequest.java @@ -12,6 +12,8 @@ import java.util.Map; public class DelBucketRequest extends RemoteRequest { + public static final String DELETE_BUCKET_SUCCESS = "removed item"; + public DelBucketRequest(String bucketName) { if (ObjectUtils.isEmpty(bucketName)) { throw new IllegalArgumentException("bucketName must not be blank"); diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/osd/request/UpdateOsdBucketRequest.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/osd/request/UpdateOsdBucketRequest.java index 9ea44a6038c678e00cfb9fdcaa69ed36041d8c89..0c3528eebde1ff17231603d9bec19d091a3cfdc7 100644 --- a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/osd/request/UpdateOsdBucketRequest.java +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/osd/osd/request/UpdateOsdBucketRequest.java @@ -29,6 +29,7 @@ import java.util.Map; public class UpdateOsdBucketRequest extends RemoteRequest { public static final float DEFAULT_WEIGHT = 1.0F; + public static final String UPDATE_SUCCESS = "set item id %s name 'osd.%s' weight 1 at location {host=%s} to crush map"; public UpdateOsdBucketRequest(int osdId, CrushFailureDomainEnum crushFailureDomainEnum, String targetBucket) { if (ObjectUtil.checkObjFieldContainNull(osdId)) { diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/model/dto/StoragePoolDiskManageDTO.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/model/dto/StoragePoolDiskManageDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..df4eb5a276b27fa4ed323ef2d9ec835b6d6a5582 --- /dev/null +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/model/dto/StoragePoolDiskManageDTO.java @@ -0,0 +1,44 @@ +/* + * Copyright 2022 The DSMS Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.dsms.dfsbroker.storagepool.model.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class StoragePoolDiskManageDTO { + + private String poolName; + + private Osd osd; + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class Osd { + @ApiModelProperty(value = "osdId列表", example = "[0,1,2]") + List osdIds; + @ApiModelProperty(value = "osd所在节点名称", example = "node1") + private String nodeName; + } +} diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/model/dto/StoragePoolNodeManageDTO.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/model/dto/StoragePoolNodeManageDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..03e70e19bb63f98126273ff4a2bc69005bca9b3b --- /dev/null +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/model/dto/StoragePoolNodeManageDTO.java @@ -0,0 +1,45 @@ +/* + * Copyright 2022 The DSMS Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.dsms.dfsbroker.storagepool.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class StoragePoolNodeManageDTO { + + private String poolName; + //use to remove single node of storage pool + private String nodeName; + //use to add nodes of storage pool + private List nodeNames; + + public StoragePoolNodeManageDTO(String poolName, List nodeNames) { + this.poolName = poolName; + this.nodeNames = nodeNames; + } + + public StoragePoolNodeManageDTO(String poolName, String nodeName) { + this.poolName = poolName; + this.nodeName = nodeName; + } +} diff --git a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/service/IStoragePoolService.java b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/service/IStoragePoolService.java index 4f991a06e224f4644329e2c1689787fa38e1c006..9b28739a612ff5db04a1719843d22ddee8000623 100644 --- a/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/service/IStoragePoolService.java +++ b/dsms-engine-dfsbroker/src/main/java/com/dsms/dfsbroker/storagepool/service/IStoragePoolService.java @@ -16,8 +16,11 @@ package com.dsms.dfsbroker.storagepool.service; +import com.dsms.dfsbroker.node.model.dto.NodeDto; import com.dsms.dfsbroker.storagepool.model.StoragePool; import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolCreateDTO; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolDiskManageDTO; +import com.dsms.dfsbroker.storagepool.model.dto.StoragePoolNodeManageDTO; import java.util.List; @@ -35,4 +38,46 @@ public interface IStoragePoolService { * @return boolean */ boolean create(StoragePoolCreateDTO storagePoolCreateDTO); + + /** + * list storage pool's all used disk and node + * + * @return the list of NodeDto + */ + List listUsedDisk(String PoolName); + + /** + * list storage pool's unused disk on one node + * + * @return NodeDto + */ + NodeDto listUnusedDisk(String poolName, String nodeName); + + /** + * create add node for storage pool task + * + * @return boolean + */ + boolean addNode(StoragePoolNodeManageDTO storagePoolNodeManageDTO); + + /** + * create remove node for storage pool task + * + * @return boolean + */ + boolean removeNode(StoragePoolNodeManageDTO storagePoolNodeManageDTO); + + /** + * create add disk for storage pool on one node task + * + * @return boolean + */ + boolean addDisk(StoragePoolDiskManageDTO storagePoolDiskManageDto); + + /** + * create remove node for storage pool on one node task + * + * @return boolean + */ + boolean removeDisk(StoragePoolDiskManageDTO storagePoolDiskManageDTO); }