diff --git a/common/src/main/scala/org/apache/celeborn/common/CelebornConf.scala b/common/src/main/scala/org/apache/celeborn/common/CelebornConf.scala index 290ce60f92..6a3b7e1b49 100644 --- a/common/src/main/scala/org/apache/celeborn/common/CelebornConf.scala +++ b/common/src/main/scala/org/apache/celeborn/common/CelebornConf.scala @@ -766,6 +766,8 @@ class CelebornConf(loadDefaults: Boolean) extends Cloneable with Logging with Se def haMasterRatisClientRpcWatchTimeout: Long = get(HA_MASTER_RATIS_CLIENT_RPC_WATCH_TIMEOUT) def haMasterRatisFirstElectionTimeoutMin: Long = get(HA_MASTER_RATIS_FIRSTELECTION_TIMEOUT_MIN) def haMasterRatisFirstElectionTimeoutMax: Long = get(HA_MASTER_RATIS_FIRSTELECTION_TIMEOUT_MAX) + def hasMasterRatisLeaderElectionMemeberMajorityAdd: Boolean = + get(HA_MASTER_RATIS_LEADER_ELECTION_MEMBER_MAJORITY_ADD) def haMasterRatisNotificationNoLeaderTimeout: Long = get(HA_MASTER_RATIS_NOTIFICATION_NO_LEADER_TIMEOUT) def haMasterRatisRpcSlownessTimeout: Long = get(HA_MASTER_RATIS_RPC_SLOWNESS_TIMEOUT) @@ -2655,6 +2657,14 @@ object CelebornConf extends Logging { .timeConf(TimeUnit.SECONDS) .createWithDefaultString("5s") + val HA_MASTER_RATIS_LEADER_ELECTION_MEMBER_MAJORITY_ADD: ConfigEntry[Boolean] = + buildConf("celeborn.master.ha.ratis.leader.election.member.majority.add") + .internal + .categories("ha") + .version("0.6.0") + .booleanConf + .createWithDefault(false) + val HA_MASTER_RATIS_NOTIFICATION_NO_LEADER_TIMEOUT: ConfigEntry[Long] = buildConf("celeborn.master.ha.ratis.raft.server.notification.no-leader.timeout") .withAlternative("celeborn.ha.master.ratis.raft.server.notification.no-leader.timeout") diff --git a/master/src/main/java/org/apache/celeborn/service/deploy/master/clustermeta/ha/HARaftServer.java b/master/src/main/java/org/apache/celeborn/service/deploy/master/clustermeta/ha/HARaftServer.java index d4e10454d6..71d03cf922 100644 --- a/master/src/main/java/org/apache/celeborn/service/deploy/master/clustermeta/ha/HARaftServer.java +++ b/master/src/main/java/org/apache/celeborn/service/deploy/master/clustermeta/ha/HARaftServer.java @@ -364,6 +364,10 @@ private RaftProperties newRaftProperties(CelebornConf conf, RpcType rpc) { RaftServerConfigKeys.Rpc.setFirstElectionTimeoutMin(properties, firstElectionTimeoutMin); RaftServerConfigKeys.Rpc.setFirstElectionTimeoutMax(properties, firstElectionTimeoutMax); + boolean leaderElectionMemberMajorityAdd = conf.hasMasterRatisLeaderElectionMemeberMajorityAdd(); + RaftServerConfigKeys.LeaderElection.setMemberMajorityAdd( + properties, leaderElectionMemberMajorityAdd); + // Set the rpc client timeout TimeDuration clientRpcTimeout = TimeDuration.valueOf(conf.haMasterRatisClientRpcTimeout(), TimeUnit.SECONDS); diff --git a/master/src/main/scala/org/apache/celeborn/service/deploy/master/http/api/v1/RatisResource.scala b/master/src/main/scala/org/apache/celeborn/service/deploy/master/http/api/v1/RatisResource.scala index a48a39a34f..473843b71f 100644 --- a/master/src/main/scala/org/apache/celeborn/service/deploy/master/http/api/v1/RatisResource.scala +++ b/master/src/main/scala/org/apache/celeborn/service/deploy/master/http/api/v1/RatisResource.scala @@ -17,7 +17,7 @@ package org.apache.celeborn.service.deploy.master.http.api.v1 -import javax.ws.rs.{Consumes, Path, POST, Produces} +import javax.ws.rs.{BadRequestException, Consumes, Path, POST, Produces} import javax.ws.rs.core.MediaType import scala.collection.JavaConverters._ @@ -25,11 +25,12 @@ import scala.collection.JavaConverters._ import io.swagger.v3.oas.annotations.media.{Content, Schema} import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.tags.Tag -import org.apache.ratis.protocol.{LeaderElectionManagementRequest, RaftPeerId, TransferLeadershipRequest} +import org.apache.ratis.protocol.{LeaderElectionManagementRequest, RaftClientReply, RaftPeer, SetConfigurationRequest, TransferLeadershipRequest} import org.apache.ratis.rpc.CallId +import org.apache.celeborn.common.CelebornConf import org.apache.celeborn.common.internal.Logging -import org.apache.celeborn.rest.v1.model.{HandleResponse, RatisElectionTransferRequest} +import org.apache.celeborn.rest.v1.model.{HandleResponse, RatisElectionTransferRequest, RatisPeerAddRequest, RatisPeerRemoveRequest, RatisPeerSetPriorityRequest} import org.apache.celeborn.server.common.http.api.ApiRequestContext import org.apache.celeborn.service.deploy.master.Master import org.apache.celeborn.service.deploy.master.clustermeta.ha.{HAMasterMetaManager, HARaftServer} @@ -92,8 +93,129 @@ class RatisResource extends ApiRequestContext with Logging { applyElectionOp(new LeaderElectionManagementRequest.Resume) } + @ApiResponse( + responseCode = "200", + content = Array(new Content( + mediaType = MediaType.APPLICATION_JSON, + schema = new Schema(implementation = classOf[HandleResponse]))), + description = "Add new peers to the raft group.") + @POST + @Path("/peer/add") + def peerAdd(request: RatisPeerAddRequest): HandleResponse = + ensureLeaderElectionMemberMajorityAddEnabled(master) { + if (request.getPeers.isEmpty) { + throw new BadRequestException("No peers specified.") + } + + val groupInfo = ratisServer.getGroupInfo + + val remaining = getRaftPeers() + val adding = request.getPeers.asScala.map { peer => + if (remaining.exists(e => + e.getId.toString == peer.getId || e.getAddress == peer.getAddress)) { + throw new IllegalArgumentException( + s"Peer $peer with same id or address already exists in group $groupInfo.") + } + RaftPeer.newBuilder() + .setId(peer.getId) + .setAddress(peer.getAddress) + .setPriority(0) + .build() + } + + val peers = (remaining ++ adding).distinct + + logInfo(s"Adding peers: $adding to group $groupInfo.") + logInfo(s"New peers: $peers") + + val reply = setConfiguration(peers) + if (reply.isSuccess) { + new HandleResponse().success(true).message( + s"Successfully added peers $adding to group $groupInfo.") + } else { + new HandleResponse().success(false).message( + s"Failed to add peers $adding to group $groupInfo. $reply") + } + } + + @ApiResponse( + responseCode = "200", + content = Array(new Content( + mediaType = MediaType.APPLICATION_JSON, + schema = new Schema(implementation = classOf[HandleResponse]))), + description = "Remove peers from the raft group.") + @POST + @Path("/peer/remove") + def peerRemove(request: RatisPeerRemoveRequest): HandleResponse = + ensureLeaderElectionMemberMajorityAddEnabled(master) { + if (request.getPeers.isEmpty) { + throw new BadRequestException("No peers specified.") + } + + val groupInfo = ratisServer.getGroupInfo + + val removing = request.getPeers.asScala.map { peer => + getRaftPeers().find { raftPeer => + raftPeer.getId.toString == peer.getId && raftPeer.getAddress == peer.getAddress + }.getOrElse(throw new IllegalArgumentException( + s"Peer $peer not found in group $groupInfo.")) + } + val remaining = getRaftPeers().filterNot(removing.contains) + + logInfo(s"Removing peers:$removing from group $groupInfo.") + logInfo(s"New peers: $remaining") + + val reply = setConfiguration(remaining) + if (reply.isSuccess) { + new HandleResponse().success(true).message( + s"Successfully removed peers $removing from group $groupInfo.") + } else { + new HandleResponse().success(false).message( + s"Failed to remove peers $removing from group $groupInfo. $reply") + } + } + + @ApiResponse( + responseCode = "200", + content = Array(new Content( + mediaType = MediaType.APPLICATION_JSON, + schema = new Schema(implementation = classOf[HandleResponse]))), + description = "Set the priority of the peers in the raft group.") + @POST + @Path("/peer/set_priority") + def peerSetPriority(request: RatisPeerSetPriorityRequest): HandleResponse = + ensureLeaderElectionMemberMajorityAddEnabled(master) { + if (request.getAddressPriorities.isEmpty) { + throw new BadRequestException("No peer priorities specified.") + } + + val peers = getRaftPeers().map { peer => + val newPriority = request.getAddressPriorities.get(peer.getAddress) + val priority: Int = if (newPriority != null) newPriority else peer.getPriority + RaftPeer.newBuilder(peer).setPriority(priority).build() + } + + val peerPriorities = + request.getAddressPriorities.asScala.map { case (a, p) => s"$a:$p" }.mkString(", ") + logInfo(s"Setting peer priorities: $peerPriorities.") + logInfo(s"New peers: $peers") + + val reply = setConfiguration(peers) + if (reply.isSuccess) { + new HandleResponse().success(true).message( + s"Successfully set peer priorities: $peerPriorities.") + } else { + new HandleResponse().success(false).message( + s"Failed to set peer priorities: $peerPriorities. $reply") + } + } + private def transferLeadership(peerAddress: String): HandleResponse = { - val newLeaderId = Option(peerAddress).map(getRaftPeerId).orNull + val newLeaderId = Option(peerAddress).map { addr => + getRaftPeers().find(_.getAddress == addr).map(_.getId).getOrElse( + throw new IllegalArgumentException( + s"Peer $addr not found in group ${ratisServer.getGroupInfo}.")) + }.orNull val op = if (newLeaderId == null) s"step down leader ${ratisServer.getLocalAddress}" else s"transfer leadership from ${ratisServer.getLocalAddress} to $peerAddress" @@ -129,11 +251,26 @@ class RatisResource extends ApiRequestContext with Logging { } } - private def getRaftPeerId(peerAddress: String): RaftPeerId = { - val groupInfo = - master.statusSystem.asInstanceOf[HAMasterMetaManager].getRatisServer.getGroupInfo - groupInfo.getCommitInfos.asScala.filter(peer => peer.getServer.getAddress == peerAddress) - .map(peer => RaftPeerId.valueOf(peer.getServer.getId)).headOption.getOrElse( - throw new IllegalArgumentException(s"Peer $peerAddress not found in group: $groupInfo")) + private def setConfiguration(peers: Seq[RaftPeer]): RaftClientReply = { + ratisServer.getServer.setConfiguration(new SetConfigurationRequest( + ratisServer.getClientId, + ratisServer.getServer.getId, + ratisServer.getGroupId, + CallId.getAndIncrement(), + SetConfigurationRequest.Arguments.newBuilder.setServersInNewConf(peers.asJava).build())) + } + + private def getRaftPeers(): Seq[RaftPeer] = { + ratisServer.getGroupInfo.getGroup.getPeers.asScala.toSeq + } + + private def ensureLeaderElectionMemberMajorityAddEnabled[T](master: Master)(f: => T): T = { + ensureMasterIsLeader(master) { + if (!master.conf.hasMasterRatisLeaderElectionMemeberMajorityAdd) { + throw new BadRequestException(s"This operation can only be done when" + + s" ${CelebornConf.HA_MASTER_RATIS_LEADER_ELECTION_MEMBER_MAJORITY_ADD.key} is true.") + } + f + } } } diff --git a/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/master/RatisApi.java b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/master/RatisApi.java index e71fb80a44..03a3f40366 100644 --- a/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/master/RatisApi.java +++ b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/master/RatisApi.java @@ -27,6 +27,9 @@ import org.apache.celeborn.rest.v1.model.HandleResponse; import org.apache.celeborn.rest.v1.model.RatisElectionTransferRequest; +import org.apache.celeborn.rest.v1.model.RatisPeerAddRequest; +import org.apache.celeborn.rest.v1.model.RatisPeerRemoveRequest; +import org.apache.celeborn.rest.v1.model.RatisPeerSetPriorityRequest; import java.util.ArrayList; @@ -47,6 +50,75 @@ public RatisApi(ApiClient apiClient) { super(apiClient); } + /** + * + * Add new peers to the raft group. + * @param ratisPeerAddRequest (optional) + * @return HandleResponse + * @throws ApiException if fails to make API call + */ + public HandleResponse addRatisPeer(RatisPeerAddRequest ratisPeerAddRequest) throws ApiException { + return this.addRatisPeer(ratisPeerAddRequest, Collections.emptyMap()); + } + + + /** + * + * Add new peers to the raft group. + * @param ratisPeerAddRequest (optional) + * @param additionalHeaders additionalHeaders for this call + * @return HandleResponse + * @throws ApiException if fails to make API call + */ + public HandleResponse addRatisPeer(RatisPeerAddRequest ratisPeerAddRequest, Map additionalHeaders) throws ApiException { + Object localVarPostBody = ratisPeerAddRequest; + + // create path and map variables + String localVarPath = "/api/v1/ratis/peer/add"; + + StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { "basic" }; + + TypeReference localVarReturnType = new TypeReference() {}; + return apiClient.invokeAPI( + localVarPath, + "POST", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + localVarReturnType + ); + } + /** * * Pause leader election at the current server. Then, the current server would not start a leader election. @@ -114,6 +186,75 @@ public HandleResponse pauseRatisElection(Map additionalHeaders) ); } + /** + * + * Remove peers from the raft group. + * @param ratisPeerRemoveRequest (optional) + * @return HandleResponse + * @throws ApiException if fails to make API call + */ + public HandleResponse removeRatisPeer(RatisPeerRemoveRequest ratisPeerRemoveRequest) throws ApiException { + return this.removeRatisPeer(ratisPeerRemoveRequest, Collections.emptyMap()); + } + + + /** + * + * Remove peers from the raft group. + * @param ratisPeerRemoveRequest (optional) + * @param additionalHeaders additionalHeaders for this call + * @return HandleResponse + * @throws ApiException if fails to make API call + */ + public HandleResponse removeRatisPeer(RatisPeerRemoveRequest ratisPeerRemoveRequest, Map additionalHeaders) throws ApiException { + Object localVarPostBody = ratisPeerRemoveRequest; + + // create path and map variables + String localVarPath = "/api/v1/ratis/peer/remove"; + + StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { "basic" }; + + TypeReference localVarReturnType = new TypeReference() {}; + return apiClient.invokeAPI( + localVarPath, + "POST", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + localVarReturnType + ); + } + /** * * Resume leader election at the current server. @@ -181,6 +322,75 @@ public HandleResponse resumeRatisElection(Map additionalHeaders) ); } + /** + * + * Set the priority of the peers in the raft group. + * @param ratisPeerSetPriorityRequest (optional) + * @return HandleResponse + * @throws ApiException if fails to make API call + */ + public HandleResponse setRatisPeerPriority(RatisPeerSetPriorityRequest ratisPeerSetPriorityRequest) throws ApiException { + return this.setRatisPeerPriority(ratisPeerSetPriorityRequest, Collections.emptyMap()); + } + + + /** + * + * Set the priority of the peers in the raft group. + * @param ratisPeerSetPriorityRequest (optional) + * @param additionalHeaders additionalHeaders for this call + * @return HandleResponse + * @throws ApiException if fails to make API call + */ + public HandleResponse setRatisPeerPriority(RatisPeerSetPriorityRequest ratisPeerSetPriorityRequest, Map additionalHeaders) throws ApiException { + Object localVarPostBody = ratisPeerSetPriorityRequest; + + // create path and map variables + String localVarPath = "/api/v1/ratis/peer/set_priority"; + + StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + List localVarQueryParams = new ArrayList(); + List localVarCollectionQueryParams = new ArrayList(); + Map localVarHeaderParams = new HashMap(); + Map localVarCookieParams = new HashMap(); + Map localVarFormParams = new HashMap(); + + + localVarHeaderParams.putAll(additionalHeaders); + + + + final String[] localVarAccepts = { + "application/json" + }; + final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts); + + final String[] localVarContentTypes = { + "application/json" + }; + final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] { "basic" }; + + TypeReference localVarReturnType = new TypeReference() {}; + return apiClient.invokeAPI( + localVarPath, + "POST", + localVarQueryParams, + localVarCollectionQueryParams, + localVarQueryStringJoiner.toString(), + localVarPostBody, + localVarHeaderParams, + localVarCookieParams, + localVarFormParams, + localVarAccept, + localVarContentType, + localVarAuthNames, + localVarReturnType + ); + } + /** * * Make the group leader step down its leadership. diff --git a/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeer.java b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeer.java new file mode 100644 index 0000000000..d746b96d2e --- /dev/null +++ b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeer.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.celeborn.rest.v1.model; + +import java.util.Objects; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonTypeName; + +/** + * RatisPeer + */ +@JsonPropertyOrder({ + RatisPeer.JSON_PROPERTY_ID, + RatisPeer.JSON_PROPERTY_ADDRESS +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.8.0") +public class RatisPeer { + public static final String JSON_PROPERTY_ID = "id"; + private String id; + + public static final String JSON_PROPERTY_ADDRESS = "address"; + private String address; + + public RatisPeer() { + } + + public RatisPeer id(String id) { + + this.id = id; + return this; + } + + /** + * The id of the peer. + * @return id + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_ID) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public String getId() { + return id; + } + + + @JsonProperty(JSON_PROPERTY_ID) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setId(String id) { + this.id = id; + } + + public RatisPeer address(String address) { + + this.address = address; + return this; + } + + /** + * The address of the peer. + * @return address + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_ADDRESS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public String getAddress() { + return address; + } + + + @JsonProperty(JSON_PROPERTY_ADDRESS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setAddress(String address) { + this.address = address; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RatisPeer ratisPeer = (RatisPeer) o; + return Objects.equals(this.id, ratisPeer.id) && + Objects.equals(this.address, ratisPeer.address); + } + + @Override + public int hashCode() { + return Objects.hash(id, address); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RatisPeer {\n"); + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" address: ").append(toIndentedString(address)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerAddRequest.java b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerAddRequest.java new file mode 100644 index 0000000000..f8c621a0e7 --- /dev/null +++ b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerAddRequest.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.celeborn.rest.v1.model; + +import java.util.Objects; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.celeborn.rest.v1.model.RatisPeer; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonTypeName; + +/** + * RatisPeerAddRequest + */ +@JsonPropertyOrder({ + RatisPeerAddRequest.JSON_PROPERTY_PEERS +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.8.0") +public class RatisPeerAddRequest { + public static final String JSON_PROPERTY_PEERS = "peers"; + private List peers = new ArrayList<>(); + + public RatisPeerAddRequest() { + } + + public RatisPeerAddRequest peers(List peers) { + + this.peers = peers; + return this; + } + + public RatisPeerAddRequest addPeersItem(RatisPeer peersItem) { + if (this.peers == null) { + this.peers = new ArrayList<>(); + } + this.peers.add(peersItem); + return this; + } + + /** + * The peers to be added to the raft group. + * @return peers + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_PEERS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public List getPeers() { + return peers; + } + + + @JsonProperty(JSON_PROPERTY_PEERS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setPeers(List peers) { + this.peers = peers; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RatisPeerAddRequest ratisPeerAddRequest = (RatisPeerAddRequest) o; + return Objects.equals(this.peers, ratisPeerAddRequest.peers); + } + + @Override + public int hashCode() { + return Objects.hash(peers); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RatisPeerAddRequest {\n"); + sb.append(" peers: ").append(toIndentedString(peers)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerRemoveRequest.java b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerRemoveRequest.java new file mode 100644 index 0000000000..10d1416b42 --- /dev/null +++ b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerRemoveRequest.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.celeborn.rest.v1.model; + +import java.util.Objects; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.celeborn.rest.v1.model.RatisPeer; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonTypeName; + +/** + * RatisPeerRemoveRequest + */ +@JsonPropertyOrder({ + RatisPeerRemoveRequest.JSON_PROPERTY_PEERS +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.8.0") +public class RatisPeerRemoveRequest { + public static final String JSON_PROPERTY_PEERS = "peers"; + private List peers = new ArrayList<>(); + + public RatisPeerRemoveRequest() { + } + + public RatisPeerRemoveRequest peers(List peers) { + + this.peers = peers; + return this; + } + + public RatisPeerRemoveRequest addPeersItem(RatisPeer peersItem) { + if (this.peers == null) { + this.peers = new ArrayList<>(); + } + this.peers.add(peersItem); + return this; + } + + /** + * The peers to be removed from the raft group. + * @return peers + */ + @javax.annotation.Nonnull + @JsonProperty(JSON_PROPERTY_PEERS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + + public List getPeers() { + return peers; + } + + + @JsonProperty(JSON_PROPERTY_PEERS) + @JsonInclude(value = JsonInclude.Include.ALWAYS) + public void setPeers(List peers) { + this.peers = peers; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RatisPeerRemoveRequest ratisPeerRemoveRequest = (RatisPeerRemoveRequest) o; + return Objects.equals(this.peers, ratisPeerRemoveRequest.peers); + } + + @Override + public int hashCode() { + return Objects.hash(peers); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RatisPeerRemoveRequest {\n"); + sb.append(" peers: ").append(toIndentedString(peers)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerSetPriorityRequest.java b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerSetPriorityRequest.java new file mode 100644 index 0000000000..2cff94e3c8 --- /dev/null +++ b/openapi/openapi-client/src/main/java/org/apache/celeborn/rest/v1/model/RatisPeerSetPriorityRequest.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.celeborn.rest.v1.model; + +import java.util.Objects; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.annotation.JsonTypeName; + +/** + * RatisPeerSetPriorityRequest + */ +@JsonPropertyOrder({ + RatisPeerSetPriorityRequest.JSON_PROPERTY_ADDRESS_PRIORITIES +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.8.0") +public class RatisPeerSetPriorityRequest { + public static final String JSON_PROPERTY_ADDRESS_PRIORITIES = "addressPriorities"; + private Map addressPriorities = new HashMap<>(); + + public RatisPeerSetPriorityRequest() { + } + + public RatisPeerSetPriorityRequest addressPriorities(Map addressPriorities) { + + this.addressPriorities = addressPriorities; + return this; + } + + public RatisPeerSetPriorityRequest putAddressPrioritiesItem(String key, Integer addressPrioritiesItem) { + if (this.addressPriorities == null) { + this.addressPriorities = new HashMap<>(); + } + this.addressPriorities.put(key, addressPrioritiesItem); + return this; + } + + /** + * The peer address and priority of the peer. + * @return addressPriorities + */ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ADDRESS_PRIORITIES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Map getAddressPriorities() { + return addressPriorities; + } + + + @JsonProperty(JSON_PROPERTY_ADDRESS_PRIORITIES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setAddressPriorities(Map addressPriorities) { + this.addressPriorities = addressPriorities; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RatisPeerSetPriorityRequest ratisPeerSetPriorityRequest = (RatisPeerSetPriorityRequest) o; + return Objects.equals(this.addressPriorities, ratisPeerSetPriorityRequest.addressPriorities); + } + + @Override + public int hashCode() { + return Objects.hash(addressPriorities); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class RatisPeerSetPriorityRequest {\n"); + sb.append(" addressPriorities: ").append(toIndentedString(addressPriorities)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + +} + diff --git a/openapi/openapi-client/src/main/openapi3/master_rest_v1.yaml b/openapi/openapi-client/src/main/openapi3/master_rest_v1.yaml index 3db2ce1dc1..ba4ca20969 100644 --- a/openapi/openapi-client/src/main/openapi3/master_rest_v1.yaml +++ b/openapi/openapi-client/src/main/openapi3/master_rest_v1.yaml @@ -319,6 +319,63 @@ paths: schema: $ref: '#/components/schemas/HandleResponse' + /api/v1/ratis/peer/add: + post: + tags: + - Ratis + operationId: addRatisPeer + description: Add new peers to the raft group. + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RatisPeerAddRequest' + responses: + "200": + description: The request was successful. + content: + application/json: + schema: + $ref: '#/components/schemas/HandleResponse' + + /api/v1/ratis/peer/remove: + post: + tags: + - Ratis + operationId: removeRatisPeer + description: Remove peers from the raft group. + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RatisPeerRemoveRequest' + responses: + "200": + description: The request was successful. + content: + application/json: + schema: + $ref: '#/components/schemas/HandleResponse' + + /api/v1/ratis/peer/set_priority: + post: + tags: + - Ratis + operationId: setRatisPeerPriority + description: Set the priority of the peers in the raft group. + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RatisPeerSetPriorityRequest' + responses: + "200": + description: The request was successful. + content: + application/json: + schema: + $ref: '#/components/schemas/HandleResponse' + components: schemas: ConfigData: @@ -824,6 +881,50 @@ components: required: - peerAddress + RatisPeer: + type: object + properties: + id: + type: string + description: The id of the peer. + address: + type: string + description: The address of the peer. + required: + - id + - address + + RatisPeerAddRequest: + type: object + properties: + peers: + type: array + description: The peers to be added to the raft group. + items: + $ref: '#/components/schemas/RatisPeer' + required: + - peers + + RatisPeerRemoveRequest: + type: object + properties: + peers: + type: array + description: The peers to be removed from the raft group. + items: + $ref: '#/components/schemas/RatisPeer' + required: + - peers + + RatisPeerSetPriorityRequest: + type: object + properties: + addressPriorities: + type: object + description: The peer address and priority of the peer. + additionalProperties: + type: integer + HandleResponse: type: object properties: