副本重分配-》生成分配计划
This commit is contained in:
@@ -6,22 +6,24 @@
|
||||
<p></p>
|
||||
<hr />
|
||||
<h3>kafka API 版本兼容性</h3>
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="brokerApiVersionInfo"
|
||||
bordered
|
||||
row-key="brokerId"
|
||||
>
|
||||
<div slot="operation" slot-scope="record">
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openApiVersionInfoDialog(record)"
|
||||
>详情
|
||||
</a-button>
|
||||
</div>
|
||||
</a-table>
|
||||
<a-spin :spinning="apiVersionInfoLoading">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="brokerApiVersionInfo"
|
||||
bordered
|
||||
row-key="brokerId"
|
||||
>
|
||||
<div slot="operation" slot-scope="record">
|
||||
<a-button
|
||||
size="small"
|
||||
href="javascript:;"
|
||||
class="operation-btn"
|
||||
@click="openApiVersionInfoDialog(record)"
|
||||
>详情
|
||||
</a-button>
|
||||
</div>
|
||||
</a-table>
|
||||
</a-spin>
|
||||
<VersionInfo
|
||||
:version-info="apiVersionInfo"
|
||||
:visible="showApiVersionInfoDialog"
|
||||
@@ -47,6 +49,7 @@ export default {
|
||||
brokerApiVersionInfo: [],
|
||||
showApiVersionInfoDialog: false,
|
||||
apiVersionInfo: [],
|
||||
apiVersionInfoLoading: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -73,10 +76,12 @@ export default {
|
||||
});
|
||||
}
|
||||
});
|
||||
this.apiVersionInfoLoading = true;
|
||||
request({
|
||||
url: KafkaClusterApi.getBrokerApiVersionInfo.url,
|
||||
method: KafkaClusterApi.getBrokerApiVersionInfo.method,
|
||||
}).then((res) => {
|
||||
this.apiVersionInfoLoading = false;
|
||||
if (res.code == 0) {
|
||||
this.brokerApiVersionInfo = res.data;
|
||||
} else {
|
||||
|
||||
@@ -49,6 +49,15 @@
|
||||
<label>说明:</label>
|
||||
<span>查看正在进行副本变更/重分配的任务,或者将其取消</span>
|
||||
</p>
|
||||
<p>
|
||||
<a-button type="primary" @click="openReplicaReassignDialog">
|
||||
副本重分配
|
||||
</a-button>
|
||||
<label>说明:</label>
|
||||
<span
|
||||
>副本所在节点重新分配,打个比方,集群有6个节点,分区1的3个副本在节点1、2、3上,现在将它们重新分配到3、4、5上</span
|
||||
>
|
||||
</p>
|
||||
</a-card>
|
||||
</div>
|
||||
<!-- 隐藏数据同步相关-->
|
||||
@@ -125,6 +134,11 @@
|
||||
:visible="clusterManager.showClusterInfoDialog"
|
||||
@closeClusterInfoDialog="closeClusterInfoDialog"
|
||||
></ClusterInfo>
|
||||
<ReplicaReassign
|
||||
:visible="replicationManager.showReplicaReassignDialog"
|
||||
@closeReplicaReassignDialog="closeReplicaReassignDialog"
|
||||
>
|
||||
</ReplicaReassign>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -138,6 +152,7 @@ import ConfigThrottle from "@/views/op/ConfigThrottle";
|
||||
import RemoveThrottle from "@/views/op/RemoveThrottle";
|
||||
import CurrentReassignments from "@/views/op/CurrentReassignments";
|
||||
import ClusterInfo from "@/views/op/ClusterInfo";
|
||||
import ReplicaReassign from "@/views/op/ReplicaReassign";
|
||||
export default {
|
||||
name: "Operation",
|
||||
components: {
|
||||
@@ -150,6 +165,7 @@ export default {
|
||||
RemoveThrottle,
|
||||
CurrentReassignments,
|
||||
ClusterInfo,
|
||||
ReplicaReassign,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -162,6 +178,7 @@ export default {
|
||||
replicationManager: {
|
||||
showElectPreferredLeaderDialog: false,
|
||||
showCurrentReassignmentsDialog: false,
|
||||
showReplicaReassignDialog: false,
|
||||
},
|
||||
brokerManager: {
|
||||
showConfigThrottleDialog: false,
|
||||
@@ -227,6 +244,12 @@ export default {
|
||||
closeClusterInfoDialog() {
|
||||
this.clusterManager.showClusterInfoDialog = false;
|
||||
},
|
||||
openReplicaReassignDialog() {
|
||||
this.replicationManager.showReplicaReassignDialog = true;
|
||||
},
|
||||
closeReplicaReassignDialog() {
|
||||
this.replicationManager.showReplicaReassignDialog = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
257
ui/src/views/op/ReplicaReassign.vue
Normal file
257
ui/src/views/op/ReplicaReassign.vue
Normal file
@@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<a-modal
|
||||
title="副本重分配"
|
||||
:visible="show"
|
||||
:width="800"
|
||||
:mask="false"
|
||||
:destroyOnClose="true"
|
||||
:footer="null"
|
||||
:maskClosable="false"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<a-form
|
||||
:form="form"
|
||||
:label-col="{ span: 5 }"
|
||||
:wrapper-col="{ span: 12 }"
|
||||
@submit="handleSubmit"
|
||||
>
|
||||
<a-form-item label="Topic">
|
||||
<a-select
|
||||
@change="handleTopicChange"
|
||||
show-search
|
||||
option-filter-prop="children"
|
||||
v-decorator="[
|
||||
'topic',
|
||||
{ rules: [{ required: true, message: '请选择一个topic!' }] },
|
||||
]"
|
||||
placeholder="请选择一个topic"
|
||||
>
|
||||
<a-select-option v-for="v in topicList" :key="v" :value="v">
|
||||
{{ v }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="分配到Broker">
|
||||
<a-select
|
||||
mode="multiple"
|
||||
option-filter-prop="children"
|
||||
v-decorator="[
|
||||
'brokers',
|
||||
{
|
||||
initialValue: brokers,
|
||||
rules: [{ required: true, message: '请选择一个broker!' }],
|
||||
},
|
||||
]"
|
||||
placeholder="请选择一个broker"
|
||||
>
|
||||
<a-select-option v-for="v in brokers" :key="v" :value="v">
|
||||
<span v-if="v == -1">全部</span> <span v-else>{{ v }}</span>
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-table
|
||||
bordered
|
||||
:columns="columns"
|
||||
:data-source="currentAssignment"
|
||||
:rowKey="
|
||||
(record, index) => {
|
||||
return index;
|
||||
}
|
||||
"
|
||||
>
|
||||
</a-table>
|
||||
<a-form-item :wrapper-col="{ span: 12, offset: 5 }">
|
||||
<a-button type="primary" html-type="submit">
|
||||
重新生成分配计划
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<hr />
|
||||
<h2>新的分配计划</h2>
|
||||
<a-table
|
||||
bordered
|
||||
:columns="columns"
|
||||
:data-source="proposedAssignmentShow"
|
||||
:rowKey="
|
||||
(record, index) => {
|
||||
return index;
|
||||
}
|
||||
"
|
||||
>
|
||||
</a-table>
|
||||
<a-button type="danger"> 更新分配 </a-button>
|
||||
</a-spin>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from "@/utils/request";
|
||||
import { KafkaTopicApi, KafkaOpApi, KafkaClusterApi } from "@/utils/api";
|
||||
import notification from "ant-design-vue/es/notification";
|
||||
export default {
|
||||
name: "ReplicaReassign",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: this.visible,
|
||||
data: [],
|
||||
loading: false,
|
||||
form: this.$form.createForm(this, { name: "ReplicaReassignForm" }),
|
||||
topicList: [],
|
||||
partitions: [],
|
||||
brokers: [],
|
||||
currentAssignment: [],
|
||||
proposedAssignment: [],
|
||||
proposedAssignmentShow: [],
|
||||
columns,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
visible(v) {
|
||||
this.show = v;
|
||||
if (this.show) {
|
||||
this.clearData();
|
||||
this.getTopicNameList();
|
||||
this.getClusterInfo();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
this.getProposedAssignment(values);
|
||||
}
|
||||
});
|
||||
},
|
||||
getTopicReplicaInfo(topic) {
|
||||
this.loading = true;
|
||||
request({
|
||||
url: KafkaTopicApi.getCurrentReplicaAssignment.url + "?topic=" + topic,
|
||||
method: KafkaTopicApi.getCurrentReplicaAssignment.method,
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code == 0) {
|
||||
this.currentAssignment = res.data.partitions;
|
||||
this.currentAssignment.forEach(
|
||||
(e) => (e.replicas = e.replicas.join(","))
|
||||
);
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
description: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getTopicNameList() {
|
||||
request({
|
||||
url: KafkaTopicApi.getTopicNameList.url,
|
||||
method: KafkaTopicApi.getTopicNameList.method,
|
||||
}).then((res) => {
|
||||
if (res.code == 0) {
|
||||
this.topicList = res.data;
|
||||
} else {
|
||||
notification.error({
|
||||
message: "error",
|
||||
description: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getPartitionInfo(topic) {
|
||||
this.loading = true;
|
||||
request({
|
||||
url: KafkaTopicApi.getPartitionInfo.url + "?topic=" + topic,
|
||||
method: KafkaTopicApi.getPartitionInfo.method,
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code != 0) {
|
||||
notification.error({
|
||||
message: "error",
|
||||
description: res.msg,
|
||||
});
|
||||
} else {
|
||||
this.partitions = res.data.map((v) => v.partition);
|
||||
this.partitions.splice(0, 0, -1);
|
||||
}
|
||||
});
|
||||
},
|
||||
handleTopicChange(topic) {
|
||||
// this.getPartitionInfo(topic);
|
||||
this.clearData();
|
||||
this.getTopicReplicaInfo(topic);
|
||||
},
|
||||
getClusterInfo() {
|
||||
this.loading = true;
|
||||
request({
|
||||
url: KafkaClusterApi.getClusterInfo.url,
|
||||
method: KafkaClusterApi.getClusterInfo.method,
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
this.brokers = [];
|
||||
res.data.nodes.forEach((node) => this.brokers.push(node.id));
|
||||
});
|
||||
},
|
||||
getProposedAssignment(params) {
|
||||
this.loading = true;
|
||||
request({
|
||||
url: KafkaOpApi.proposedAssignment.url,
|
||||
method: KafkaOpApi.proposedAssignment.method,
|
||||
data: params,
|
||||
}).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.code != 0) {
|
||||
notification.error({
|
||||
message: "error",
|
||||
description: res.msg,
|
||||
});
|
||||
} else {
|
||||
this.proposedAssignment = res.data;
|
||||
this.proposedAssignmentShow = Object.assign(
|
||||
[],
|
||||
this.proposedAssignment
|
||||
);
|
||||
this.proposedAssignmentShow.forEach(
|
||||
(e) => (e.replicas = e.replicas.join(","))
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
clearData() {
|
||||
this.currentAssignment = [];
|
||||
this.proposedAssignment = [];
|
||||
this.proposedAssignmentShow = [];
|
||||
},
|
||||
handleCancel() {
|
||||
this.data = [];
|
||||
this.$emit("closeReplicaReassignDialog", { refresh: false });
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "分区",
|
||||
dataIndex: "partition",
|
||||
key: "partition",
|
||||
},
|
||||
{
|
||||
title: "副本所在broker",
|
||||
dataIndex: "replicas",
|
||||
key: "replicas",
|
||||
scopedSlots: { customRender: "replicas" },
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
Reference in New Issue
Block a user