Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2a5ca85
Introduced a new API checkVolumeAndRepair that allows users or admins…
harikrishna-patnala Feb 20, 2024
af4c422
some fixes
harikrishna-patnala Feb 20, 2024
a365b45
Added unit tests
harikrishna-patnala Feb 20, 2024
f52c819
addressed review comments
harikrishna-patnala Feb 20, 2024
08d3c06
add repair volume while granting access
harikrishna-patnala Jan 10, 2024
3b5514d
Changed repair parameter to accept both leaks/all
harikrishna-patnala Jan 30, 2024
ef1bbdd
Introduced new global setting volume.check.and.repair.before.use to d…
harikrishna-patnala Jan 30, 2024
369e567
Added volume check and repair changes only during VM start and volume…
harikrishna-patnala Jan 12, 2024
6402882
Refactored the names to look similar across the code
harikrishna-patnala Jan 30, 2024
8e4017d
Some code fixes
harikrishna-patnala Jan 29, 2024
a5d3999
remove unused code
harikrishna-patnala Jan 30, 2024
a109da1
Renamed repair values
harikrishna-patnala Jan 30, 2024
d6495c4
Fixed unit tests
harikrishna-patnala Jan 30, 2024
6ff875f
changed version
harikrishna-patnala Jan 30, 2024
a143e82
Address review comments
harikrishna-patnala Feb 20, 2024
3dc2dd9
Code refactored
harikrishna-patnala Feb 1, 2024
c805940
used volume name in logs
harikrishna-patnala Feb 1, 2024
cac4418
Changed the API to Async and the setting scope to storage pool
harikrishna-patnala Feb 5, 2024
0b88d52
Fixed exit value handling with check volume command
harikrishna-patnala Feb 7, 2024
1596d14
Fixed storage scope to the setting
harikrishna-patnala Feb 8, 2024
fb1026b
Fix volume format issues
harikrishna-patnala Feb 20, 2024
2dfeece
Refactored the log messages
harikrishna-patnala Feb 20, 2024
30fa612
Fix formatting
harikrishna-patnala Feb 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/src/main/java/com/cloud/event/EventTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ public class EventTypes {
public static final String EVENT_VOLUME_CREATE = "VOLUME.CREATE";
public static final String EVENT_VOLUME_DELETE = "VOLUME.DELETE";
public static final String EVENT_VOLUME_ATTACH = "VOLUME.ATTACH";
public static final String EVENT_VOLUME_CHECK = "VOLUME.CHECK";
public static final String EVENT_VOLUME_DETACH = "VOLUME.DETACH";
public static final String EVENT_VOLUME_EXTRACT = "VOLUME.EXTRACT";
public static final String EVENT_VOLUME_UPLOAD = "VOLUME.UPLOAD";
Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/com/cloud/storage/VolumeApiService.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import java.util.List;
import java.util.Map;

import com.cloud.utils.Pair;
import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ChangeOfferingForVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CheckAndRepairVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd;
Expand Down Expand Up @@ -178,4 +180,6 @@ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account acc
void publishVolumeCreationUsageEvent(Volume volume);

boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException;

Pair<String, String> checkAndRepairVolume(CheckAndRepairVolumeCmd cmd) throws ResourceAllocationException;
}
4 changes: 4 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ public class ApiConstants {
public static final String RECEIVED_BYTES = "receivedbytes";
public static final String RECONNECT = "reconnect";
public static final String RECOVER = "recover";
public static final String REPAIR = "repair";
public static final String REQUIRES_HVM = "requireshvm";
public static final String RESOURCE_NAME = "resourcename";
public static final String RESOURCE_TYPE = "resourcetype";
Expand Down Expand Up @@ -501,6 +502,9 @@ public class ApiConstants {
public static final String IS_VOLATILE = "isvolatile";
public static final String VOLUME_ID = "volumeid";
public static final String VOLUMES = "volumes";
public static final String VOLUME_CHECK_RESULT = "volumecheckresult";
public static final String VOLUME_REPAIR_RESULT = "volumerepairresult";

public static final String ZONE = "zone";
public static final String ZONE_ID = "zoneid";
public static final String ZONE_NAME = "zonename";
Expand Down
Original file line number Diff line number Diff line change
@@ -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.cloudstack.api.command.user.volume;

import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger;

import com.cloud.exception.ResourceAllocationException;
import com.cloud.storage.Volume;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;

import java.util.Arrays;

@APICommand(name = "checkVolume", description = "Check the volume for any errors or leaks and also repairs when repair parameter is passed, this is currently supported for KVM only", responseObject = VolumeResponse.class, entityType = {Volume.class},
since = "4.19.1",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class CheckAndRepairVolumeCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(CheckAndRepairVolumeCmd.class.getName());

private static final String s_name = "checkandrepairvolumeresponse";

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////

@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "The ID of the volume")
private Long id;

@Parameter(name = ApiConstants.REPAIR, type = CommandType.STRING, required = false, description = "parameter to repair the volume, leaks or all are the possible values")
private String repair;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////

public enum RepairValues {
LEAKS, ALL
}

public Long getId() {
return id;
}

public String getRepair() {
if (org.apache.commons.lang3.StringUtils.isNotEmpty(repair)) {
RepairValues repairType = Enum.valueOf(RepairValues.class, repair.toUpperCase());
if (repairType == null) {
throw new InvalidParameterValueException(String.format("Repair parameter can only take the following values: %s" + Arrays.toString(RepairValues.values())));
}
return repair.toLowerCase();
}
return null;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

@Override
public String getCommandName() {
return s_name;
}

@Override
public long getEntityOwnerId() {
Volume volume = _entityMgr.findById(Volume.class, getId());
if (volume != null) {
return volume.getAccountId();
}

return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}

@Override
public String getEventType() {
return EventTypes.EVENT_VOLUME_CHECK;
}

@Override
public String getEventDescription() {
return String.format("check and repair operation on volume: %s", this._uuidMgr.getUuid(Volume.class, getId()));
}

@Override
public Long getApiResourceId() {
return id;
}

@Override
public ApiCommandResourceType getApiResourceType() {
return ApiCommandResourceType.Volume;
}

@Override
public void execute() throws ResourceAllocationException {
CallContext.current().setEventDetails("Volume Id: " + getId());
Pair<String, String> result = _volumeService.checkAndRepairVolume(this);
Volume volume = _responseGenerator.findVolumeById(getId());
if (result != null) {
VolumeResponse response = _responseGenerator.createVolumeResponse(ResponseView.Full, volume);
response.setVolumeCheckResult(StringUtils.parseJsonToMap(result.first()));
if (getRepair() != null) {
response.setVolumeRepairResult(StringUtils.parseJsonToMap(result.second()));
}
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to check volume and repair");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.apache.cloudstack.acl.RoleType;
Expand Down Expand Up @@ -288,6 +289,14 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co
@Param(description = "volume uuid that is given by virtualisation provider (only for VMware)")
private String externalUuid;

@SerializedName(ApiConstants.VOLUME_CHECK_RESULT)
@Param(description = "details for the volume check result, they may vary for different hypervisors, since = 4.19.1")
private Map<String, String> volumeCheckResult;

@SerializedName(ApiConstants.VOLUME_REPAIR_RESULT)
@Param(description = "details for the volume repair result, they may vary for different hypervisors, since = 4.19.1")
private Map<String, String> volumeRepairResult;

public String getPath() {
return path;
}
Expand Down Expand Up @@ -817,4 +826,20 @@ public String getExternalUuid() {
public void setExternalUuid(String externalUuid) {
this.externalUuid = externalUuid;
}

public Map<String, String> getVolumeCheckResult() {
return volumeCheckResult;
}

public void setVolumeCheckResult(Map<String, String> volumeCheckResult) {
this.volumeCheckResult = volumeCheckResult;
}

public Map<String, String> getVolumeRepairResult() {
return volumeRepairResult;
}

public void setVolumeRepairResult(Map<String, String> volumeRepairResult) {
this.volumeRepairResult = volumeRepairResult;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// 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 com.cloud.agent.api.storage;

import com.cloud.agent.api.Answer;

public class CheckAndRepairVolumeAnswer extends Answer {
private String volumeCheckExecutionResult;
private String volumeRepairExecutionResult;

protected CheckAndRepairVolumeAnswer() {
super();
}

public CheckAndRepairVolumeAnswer(CheckAndRepairVolumeCommand cmd, boolean result, String details, String volumeCheckExecutionResult, String volumeRepairedExecutionResult) {
super(cmd, result, details);
this.volumeCheckExecutionResult = volumeCheckExecutionResult;
this.volumeRepairExecutionResult = volumeRepairedExecutionResult;
}

public CheckAndRepairVolumeAnswer(CheckAndRepairVolumeCommand cmd, boolean result, String details) {
super(cmd, result, details);
}

public String getVolumeCheckExecutionResult() {
return volumeCheckExecutionResult;
}

public String getVolumeRepairExecutionResult() {
return volumeRepairExecutionResult;
}

public void setVolumeCheckExecutionResult(String volumeCheckExecutionResult) {
this.volumeCheckExecutionResult = volumeCheckExecutionResult;
}

public void setVolumeRepairExecutionResult(String volumeRepairExecutionResult) {
this.volumeRepairExecutionResult = volumeRepairExecutionResult;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// 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 com.cloud.agent.api.storage;

import com.cloud.agent.api.Command;
import com.cloud.agent.api.LogLevel;
import com.cloud.agent.api.to.StorageFilerTO;

import java.util.Arrays;

public class CheckAndRepairVolumeCommand extends Command {
private String path;
private StorageFilerTO pool;
private String repair;
@LogLevel(LogLevel.Log4jLevel.Off)
private byte[] passphrase;
private String encryptFormat;

public CheckAndRepairVolumeCommand(String path, StorageFilerTO pool, String repair, byte[] passphrase, String encryptFormat) {
this.path = path;
this.pool = pool;
this.repair = repair;
this.passphrase = passphrase;
this.encryptFormat = encryptFormat;
}

public String getPath() {
return path;
}

public String getPoolUuid() {
return pool.getUuid();
}

public StorageFilerTO getPool() {
return pool;
}

public String getRepair() {
return repair;
}

public String getEncryptFormat() { return encryptFormat; }

public byte[] getPassphrase() { return passphrase; }

public void clearPassphrase() {
if (this.passphrase != null) {
Arrays.fill(this.passphrase, (byte) 0);
}
}

/**
* {@inheritDoc}
*/
@Override
public boolean executeInSequence() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,8 @@ boolean copyPoliciesBetweenVolumesAndDestroySourceVolumeAfterMigration(ObjectInD
VolumeInfo sourceVolume, VolumeInfo destinationVolume, boolean retryExpungeVolumeAsync);

void moveVolumeOnSecondaryStorageToAnotherAccount(Volume volume, Account sourceAccount, Account destAccount);

Pair<String, String> checkAndRepairVolume(VolumeInfo volume);

void checkAndRepairVolumeBasedOnConfig(DataObject dataObject, Host host);
}
Loading