Skip to content
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
f7ea076
New feature: Change storage pool scope
abh1sar Apr 1, 2024
d6aa362
Added checks for Ceph/RBD
abh1sar Apr 2, 2024
5a1e7bd
Update op_host_capacity table on primary storage scope change
abh1sar Apr 2, 2024
5bd6995
Storage pool scope change integration test
abh1sar Apr 3, 2024
c5cbd5d
pull 8875 : Addressed review comments
abh1sar Apr 4, 2024
0fab7a3
Pull 8875: remove storage checks, AbstractPrimayStorageLifeCycleImpl …
abh1sar Apr 6, 2024
283db1f
Pull 8875: Fixed integration test failure
abh1sar Apr 8, 2024
fb976d9
Pull 8875: Review comments
abh1sar Apr 9, 2024
042aef7
Pull 8875: review comments + broke changeStoragePoolScope into smalle…
abh1sar Apr 12, 2024
72160ea
Added UT for changeStoragePoolScope
abh1sar Apr 22, 2024
abf7082
Rename AbstractPrimaryDataStoreLifeCycleImpl to BasePrimaryDataStoreL…
abh1sar Apr 22, 2024
5ba040d
Pull 8875: Dao review comments
abh1sar Apr 22, 2024
ca36119
Pull 8875: Rename changeStoragePoolScope.vue to ChangeStoragePoolScop…
abh1sar Apr 22, 2024
962d0f3
Pull 8875: Created a new smokes test file + A single warning msg in ui
abh1sar Apr 22, 2024
f98b754
Merge with latest 4.19
abh1sar Apr 23, 2024
3753be3
Merge remote-tracking branch 'upstream/4.19' into changescope419
abh1sar Apr 24, 2024
30d628d
Merge branch '4.19' into 419-changescope
abh1sar Apr 24, 2024
aa83ec0
Pull 8875: Added cleanup in test_primary_storage_scope.py
abh1sar Apr 24, 2024
dcb9449
Pull 8875: Type in en.json
abh1sar Apr 24, 2024
8ce579a
Merge remote-tracking branch 'upstream/4.19' into changescope419
abh1sar Apr 24, 2024
bc4e700
Merge branch '4.19' into 419-changescope
abh1sar Apr 24, 2024
d714b8c
Merge remote-tracking branch 'upstream/4.19' into 419
abh1sar Apr 24, 2024
8de7aa6
Pull 8875: cleanup array in test_primary_storage_scope.py
abh1sar Apr 24, 2024
4b07a6c
Merge branch '4.19' into 419-changescope
abh1sar Apr 25, 2024
b3245cd
Pull:8875 Removing extra whitespace at eof of StorageManagerImplTest
abh1sar Apr 25, 2024
f3bdae8
Merge branch '419-changescope' of http://github.com/abh1sar/cloudstac…
abh1sar Apr 25, 2024
9657a10
Pull 8875: Added UT for PrimaryDataStoreHelper and BasePrimaryDataSto…
abh1sar Apr 29, 2024
8d36db0
Pull 8875: Added license header
abh1sar Apr 29, 2024
5ef41e1
Merge remote-tracking branch 'upstream/4.19' into changescope419
abh1sar Apr 29, 2024
aad87f2
Pull 8875: Fixed sql query for vmstates
abh1sar Apr 30, 2024
85a6340
Pull 8875: Changed icon plus info on disabled mode in apidoc
abh1sar May 1, 2024
49341db
Merge remote-tracking branch 'upstream/4.19' into changescope419
abh1sar May 6, 2024
419e5a4
Pull 8875: Change scope should not work for local storage
abh1sar May 6, 2024
d611198
Pull 8875: Change scope completion event
abh1sar May 6, 2024
9da8382
Pull 8875: Added api findAffectedVmsForStorageScopeChange
abh1sar May 19, 2024
8646c80
Merge remote-tracking branch 'upstream/4.19' into changescope419
abh1sar May 19, 2024
35c8b00
Pull 8875: Added UT for findAffectedVmsForStorageScopeChange and remo…
abh1sar May 21, 2024
ba397d7
Pull 8875: Review comments + Vm name in response
abh1sar May 22, 2024
81a2c67
Pull 8875: listByVmsNotInClusterUsingPool was returning duplicate VM …
abh1sar May 22, 2024
c502838
Pull 8875: fixed listAffectedVmsForStorageScopeChange UT
abh1sar May 22, 2024
edea352
Merge remote-tracking branch 'upstream/4.19' into changescope419
abh1sar May 23, 2024
3af24b4
Merge remote-tracking branch 'upstream/4.19' into scope
abh1sar Jun 18, 2024
cc08595
listAffectedVmsForStorageScopeChange should work if the pool is not d…
abh1sar Jun 18, 2024
0b75de1
Fix listAffectedVmsForStorageScopeChangeTest UT
abh1sar Jun 18, 2024
eedb361
Merge branch '4.19' into 419-changescope
abh1sar Jun 18, 2024
e62551b
Merge remote-tracking branch 'upstream/4.19' into cs
abh1sar Jun 19, 2024
57c4a2f
Pull 8875: add volume.removed not null check in VmsNotInClusterUsingP…
abh1sar Jun 19, 2024
271d526
Pull 8875: minor refactoring in changeStoragePoolScopeToCluster
abh1sar Jun 19, 2024
0821cc7
Update server/src/main/java/com/cloud/storage/StorageManagerImpl.java
sureshanaparti Jun 25, 2024
0507508
Merge remote-tracking branch 'upstream/4.19' into cs
abh1sar Jun 26, 2024
afd107b
fix eof
abh1sar Jun 26, 2024
2bdd974
Merge branch '4.19' into 419-changescope
abh1sar Jun 26, 2024
e40c14a
Merge branch '4.19' into 419-changescope
abh1sar Jun 27, 2024
e0cec9e
changeStoragePoolScopeToZone should connect pool to all Up hosts
abh1sar Jun 28, 2024
11b43b2
Merge branch '4.19' into 419-changescope
abh1sar Jun 28, 2024
25c4a01
Merge branch '4.19' into 419-changescope
abh1sar Jun 28, 2024
1b698c1
Merge branch '4.19' into 419-changescope
abh1sar Jun 29, 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
2 changes: 2 additions & 0 deletions api/src/main/java/com/cloud/event/EventTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ public class EventTypes {
public static final String EVENT_ENABLE_PRIMARY_STORAGE = "ENABLE.PS";
public static final String EVENT_DISABLE_PRIMARY_STORAGE = "DISABLE.PS";
public static final String EVENT_SYNC_STORAGE_POOL = "SYNC.STORAGE.POOL";
public static final String EVENT_CHANGE_STORAGE_POOL_SCOPE = "CHANGE.STORAGE.POOL.SCOPE";

// VPN
public static final String EVENT_REMOTE_ACCESS_VPN_CREATE = "VPN.REMOTE.ACCESS.CREATE";
Expand Down Expand Up @@ -1000,6 +1001,7 @@ public class EventTypes {
// Primary storage pool
entityEventDetails.put(EVENT_ENABLE_PRIMARY_STORAGE, StoragePool.class);
entityEventDetails.put(EVENT_DISABLE_PRIMARY_STORAGE, StoragePool.class);
entityEventDetails.put(EVENT_CHANGE_STORAGE_POOL_SCOPE, StoragePool.class);

// VPN
entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_CREATE, RemoteAccessVpn.class);
Expand Down
4 changes: 4 additions & 0 deletions api/src/main/java/com/cloud/storage/StorageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Map;

import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.storage.ChangeStoragePoolScopeCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
Expand All @@ -35,6 +36,7 @@
import com.cloud.exception.DiscoveryException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.exception.ResourceUnavailableException;
import org.apache.cloudstack.api.command.admin.storage.heuristics.CreateSecondaryStorageSelectorCmd;
Expand Down Expand Up @@ -130,4 +132,6 @@ public interface StorageService {
boolean deleteObjectStore(DeleteObjectStoragePoolCmd cmd);

ObjectStore updateObjectStore(Long id, UpdateObjectStoragePoolCmd cmd);

void changeStoragePoolScope(ChangeStoragePoolScopeCmd cmd) throws IllegalArgumentException, InvalidParameterValueException, PermissionDeniedException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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.admin.storage;

import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;

import com.cloud.event.EventTypes;
import com.cloud.storage.StoragePool;

@APICommand(name = "changeStoragePoolScope", description = "Changes the scope of a storage pool when the pool is in Disabled state." +
"This feature is officially tested and supported for Hypervisors: KVM and VMware, Protocols: NFS and Ceph, and Storage Provider: DefaultPrimary. " +
"There might be extra steps involved to make this work for other hypervisors and storage options.",
responseObject = SuccessResponse.class, since= "4.19.1", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ChangeStoragePoolScopeCmd extends BaseAsyncCmd {

@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, required = true, description = "the Id of the storage pool")
private Long id;

@Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, required = true, description = "the scope of the storage: cluster or zone")
private String scope;

@Parameter(name = ApiConstants.CLUSTER_ID, type = CommandType.UUID, entityType = ClusterResponse.class, description = "the Id of the cluster to use if scope is being set to Cluster")
private Long clusterId;

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

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

public String getEventType() {
return EventTypes.EVENT_CHANGE_STORAGE_POOL_SCOPE;
}

@Override
public String getEventDescription() {
String description = "Change storage pool scope. Storage pool Id: ";
StoragePool pool = _entityMgr.findById(StoragePool.class, getId());
if (pool != null) {
description += pool.getUuid();
} else {
description += getId();
}
description += " to " + getScope();
return description;
}

@Override
public void execute() {
_storageService.changeStoragePoolScope(this);
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);
}

@Override
public long getEntityOwnerId() {
return CallContext.current().getCallingAccountId();
}

public Long getId() {
return id;
}

public String getScope() {
return scope;
}

public Long getClusterId() {
return clusterId;
}
}
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 org.apache.cloudstack.api.command.admin.vm;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.VirtualMachineResponse;

import com.cloud.vm.VirtualMachine;

@APICommand(name = "listAffectedVmsForStorageScopeChange",
description = "List user and system VMs that need to be stopped and destroyed respectively for changing the scope of the storage pool from Zone to Cluster.",
responseObject = VirtualMachineResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.1",
authorized = {RoleType.Admin})
public class ListAffectedVmsForStorageScopeChangeCmd extends BaseListCmd {

@Parameter(name = ApiConstants.CLUSTER_ID,
type = CommandType.UUID,
entityType = ClusterResponse.class,
required = true,
description = "the Id of the cluster the scope of the storage pool is being changed to")
private Long clusterIdForScopeChange;

@Parameter(name = ApiConstants.STORAGE_ID,
type = CommandType.UUID,
entityType = StoragePoolResponse.class,
required = true,
description = "the Id of the storage pool on which change scope operation is being done")
private Long storageId;

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

public Long getClusterIdForScopeChange() {
return clusterIdForScopeChange;
}

public Long getStorageId() {
return storageId;
}

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

@Override
public void execute() {
ListResponse<VirtualMachineResponse> response = _queryService.listAffectedVmsForStorageScopeChange(this);
response.setResponseName(getCommandName());
response.setObjectName(VirtualMachine.class.getSimpleName().toLowerCase());
setResponseObject(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Licensed to the Apache Software Foundation (ASF) under one
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this class? Is it possible to use UserVmResponse or do we also have affected VR and system VMs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if storage scope is changed from Zone to Cluster, the hosts in other cluster will disconnect from the storage.
the running VMs (user vms, vr, system vms) on the hosts will be affected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the response can return system VMs as well.

// 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.response;

import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;

import com.cloud.serializer.Param;
import com.cloud.vm.VirtualMachine;
import com.google.gson.annotations.SerializedName;

@EntityReference(value = VirtualMachine.class)
public class VirtualMachineResponse extends BaseResponse {
@SerializedName("id")
@Param(description = "the ID of the VM")
private String id;

@SerializedName("type")
@Param(description = "the type of VM")
private String type;

@SerializedName("name")
@Param(description = "the name of the VM")
private String name;

@SerializedName("clusterid")
@Param(description = "the cluster ID for the VM")
private String clusterId;

@SerializedName("clustername")
@Param(description = "the cluster name for the VM")
private String clusterName;

@SerializedName("hostid")
@Param(description = "the host ID for the VM")
private String hostId;

@SerializedName("hostname")
@Param(description = "the hostname for the VM")
private String hostName;

@Override
public String getObjectId() {
return this.getId();
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getVmType() {
return type;
}

public void setVmType(String type) {
this.type = type;
}

public String getVmName() {
return name;
}

public void setVmName(String name) {
this.name = name;
}

public String getClusterId() {
return clusterId;
}

public void setClusterId(String clusterId) {
this.clusterId = clusterId;
}

public String getClusterName() {
return clusterName;
}

public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getHostId() {
return hostId;
}

public void setHostId(String hostId) {
this.hostId = hostId;
}

public String getHostName() {
return hostName;
}

public void setHostName(String hostName) {
this.hostName = hostName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
import org.apache.cloudstack.api.command.user.tag.ListTagsCmd;
import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd;
import org.apache.cloudstack.api.command.admin.vm.ListAffectedVmsForStorageScopeChangeCmd;
import org.apache.cloudstack.api.command.user.vm.ListVMsCmd;
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd;
Expand Down Expand Up @@ -89,6 +90,7 @@
import org.apache.cloudstack.api.response.TemplateResponse;
import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VirtualMachineResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
Expand Down Expand Up @@ -140,6 +142,8 @@ public interface QueryService {

ListResponse<UserVmResponse> searchForUserVMs(ListVMsCmd cmd);

ListResponse<VirtualMachineResponse> listAffectedVmsForStorageScopeChange(ListAffectedVmsForStorageScopeChangeCmd cmd);

ListResponse<SecurityGroupResponse> searchForSecurityGroups(ListSecurityGroupsCmd cmd);

ListResponse<DomainRouterResponse> searchForRouters(ListRoutersCmd cmd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.util.Map;

import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.StoragePool;

public interface PrimaryDataStoreLifeCycle extends DataStoreLifeCycle {
Expand All @@ -29,4 +30,6 @@ public interface PrimaryDataStoreLifeCycle extends DataStoreLifeCycle {
void updateStoragePool(StoragePool storagePool, Map<String, String> details);
void enableStoragePool(DataStore store);
void disableStoragePool(DataStore store);
void changeStoragePoolScopeToZone(DataStore store, ClusterScope clusterScope, Hypervisor.HypervisorType hypervisorType);
void changeStoragePoolScopeToCluster(DataStore store, ClusterScope clusterScope, Hypervisor.HypervisorType hypervisorType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ public interface ResourceManager extends ResourceService, Configurable {

public List<HostVO> listAllHostsInAllZonesByType(Type type);

public List<HostVO> listAllHostsInOneZoneNotInClusterByHypervisor(final HypervisorType type, long dcId, long clusterId);

public List<HostVO> listAllHostsInOneZoneNotInClusterByHypervisors(List<HypervisorType> types, long dcId, long clusterId);

public List<HypervisorType> listAvailHypervisorInZone(Long hostId, Long zoneId);

public HostVO findHostByGuid(String guid);
Expand Down
Loading