Skip to content

Commit b0e780a

Browse files
GutoVeroneziGutoVeronezi
andauthored
Enable system VM volume migration for KVM (#6341)
Release 4.16.0.0 introduced a feature for migrating system VM volumes (#4385). However, it was enabled only for VMWare. This PR intends to enable the feature for KVM too. Co-authored-by: GutoVeronezi <daniel@scclouds.com.br>
1 parent 167cd17 commit b0e780a

File tree

7 files changed

+118
-25
lines changed

7 files changed

+118
-25
lines changed

engine/schema/src/main/resources/META-INF/db/schema-41700to41710.sql

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,109 @@
2020
--;
2121

2222
UPDATE `cloud`.`configuration` SET `value` = 'false' WHERE `name` = 'network.disable.rpfilter' AND `value` != 'true';
23-
UPDATE `cloud`.`configuration` SET `value` = 'false' WHERE `name` = 'consoleproxy.disable.rpfilter' AND `value` != 'true';
23+
UPDATE `cloud`.`configuration` SET `value` = 'false' WHERE `name` = 'consoleproxy.disable.rpfilter' AND `value` != 'true';
24+
25+
-- Retrieve the hypervisor_type from vm_instance
26+
DROP VIEW IF EXISTS `cloud`.`domain_router_view`;
27+
CREATE VIEW `cloud`.`domain_router_view` AS
28+
select
29+
vm_instance.id id,
30+
vm_instance.name name,
31+
account.id account_id,
32+
account.uuid account_uuid,
33+
account.account_name account_name,
34+
account.type account_type,
35+
domain.id domain_id,
36+
domain.uuid domain_uuid,
37+
domain.name domain_name,
38+
domain.path domain_path,
39+
projects.id project_id,
40+
projects.uuid project_uuid,
41+
projects.name project_name,
42+
vm_instance.uuid uuid,
43+
vm_instance.created created,
44+
vm_instance.state state,
45+
vm_instance.removed removed,
46+
vm_instance.pod_id pod_id,
47+
vm_instance.instance_name instance_name,
48+
vm_instance.hypervisor_type,
49+
host_pod_ref.uuid pod_uuid,
50+
data_center.id data_center_id,
51+
data_center.uuid data_center_uuid,
52+
data_center.name data_center_name,
53+
data_center.networktype data_center_type,
54+
data_center.dns1 dns1,
55+
data_center.dns2 dns2,
56+
data_center.ip6_dns1 ip6_dns1,
57+
data_center.ip6_dns2 ip6_dns2,
58+
host.id host_id,
59+
host.uuid host_uuid,
60+
host.name host_name,
61+
host.cluster_id cluster_id,
62+
vm_template.id template_id,
63+
vm_template.uuid template_uuid,
64+
service_offering.id service_offering_id,
65+
service_offering.uuid service_offering_uuid,
66+
service_offering.name service_offering_name,
67+
nics.id nic_id,
68+
nics.uuid nic_uuid,
69+
nics.network_id network_id,
70+
nics.ip4_address ip_address,
71+
nics.ip6_address ip6_address,
72+
nics.ip6_gateway ip6_gateway,
73+
nics.ip6_cidr ip6_cidr,
74+
nics.default_nic is_default_nic,
75+
nics.gateway gateway,
76+
nics.netmask netmask,
77+
nics.mac_address mac_address,
78+
nics.broadcast_uri broadcast_uri,
79+
nics.isolation_uri isolation_uri,
80+
vpc.id vpc_id,
81+
vpc.uuid vpc_uuid,
82+
vpc.name vpc_name,
83+
networks.uuid network_uuid,
84+
networks.name network_name,
85+
networks.network_domain network_domain,
86+
networks.traffic_type traffic_type,
87+
networks.guest_type guest_type,
88+
async_job.id job_id,
89+
async_job.uuid job_uuid,
90+
async_job.job_status job_status,
91+
async_job.account_id job_account_id,
92+
domain_router.template_version template_version,
93+
domain_router.scripts_version scripts_version,
94+
domain_router.is_redundant_router is_redundant_router,
95+
domain_router.redundant_state redundant_state,
96+
domain_router.stop_pending stop_pending,
97+
domain_router.role role,
98+
domain_router.software_version software_version
99+
from
100+
`cloud`.`domain_router`
101+
inner join
102+
`cloud`.`vm_instance` ON vm_instance.id = domain_router.id
103+
inner join
104+
`cloud`.`account` ON vm_instance.account_id = account.id
105+
inner join
106+
`cloud`.`domain` ON vm_instance.domain_id = domain.id
107+
left join
108+
`cloud`.`host_pod_ref` ON vm_instance.pod_id = host_pod_ref.id
109+
left join
110+
`cloud`.`projects` ON projects.project_account_id = account.id
111+
left join
112+
`cloud`.`data_center` ON vm_instance.data_center_id = data_center.id
113+
left join
114+
`cloud`.`host` ON vm_instance.host_id = host.id
115+
left join
116+
`cloud`.`vm_template` ON vm_instance.vm_template_id = vm_template.id
117+
left join
118+
`cloud`.`service_offering` ON vm_instance.service_offering_id = service_offering.id
119+
left join
120+
`cloud`.`nics` ON vm_instance.id = nics.instance_id and nics.removed is null
121+
left join
122+
`cloud`.`networks` ON nics.network_id = networks.id
123+
left join
124+
`cloud`.`vpc` ON domain_router.vpc_id = vpc.id and vpc.removed is null
125+
left join
126+
`cloud`.`async_job` ON async_job.instance_id = vm_instance.id
127+
and async_job.instance_type = 'DomainRouter'
128+
and async_job.job_status = 0;

server/src/main/java/com/cloud/api/ApiDBUtils.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,6 @@
329329
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
330330
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
331331
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
332-
import org.apache.commons.lang3.StringUtils;
333332

334333
import javax.annotation.PostConstruct;
335334
import javax.inject.Inject;
@@ -1795,17 +1794,7 @@ public static String findJobInstanceUuid(AsyncJob job) {
17951794
///////////////////////////////////////////////////////////////////////
17961795

17971796
public static DomainRouterResponse newDomainRouterResponse(DomainRouterJoinVO vr, Account caller) {
1798-
DomainRouterResponse response = s_domainRouterJoinDao.newDomainRouterResponse(vr, caller);
1799-
if (StringUtils.isBlank(response.getHypervisor())) {
1800-
VMInstanceVO vm = ApiDBUtils.findVMInstanceById(vr.getId());
1801-
if (vm.getLastHostId() != null) {
1802-
HostVO lastHost = ApiDBUtils.findHostById(vm.getLastHostId());
1803-
if (lastHost != null) {
1804-
response.setHypervisor(lastHost.getHypervisorType().toString());
1805-
}
1806-
}
1807-
}
1808-
return response;
1797+
return s_domainRouterJoinDao.newDomainRouterResponse(vr, caller);
18091798
}
18101799

18111800
public static DomainRouterResponse fillRouterDetails(DomainRouterResponse vrData, DomainRouterJoinVO vr) {

server/src/main/java/com/cloud/api/ApiResponseHelper.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,18 +1536,13 @@ public SystemVmResponse createSystemVmResponse(VirtualMachine vm) {
15361536
vmResponse.setTemplateName(template.getName());
15371537
}
15381538
vmResponse.setCreated(vm.getCreated());
1539+
vmResponse.setHypervisor(vm.getHypervisorType().toString());
15391540

15401541
if (vm.getHostId() != null) {
15411542
Host host = ApiDBUtils.findHostById(vm.getHostId());
15421543
if (host != null) {
15431544
vmResponse.setHostId(host.getUuid());
15441545
vmResponse.setHostName(host.getName());
1545-
vmResponse.setHypervisor(host.getHypervisorType().toString());
1546-
}
1547-
} else if (vm.getLastHostId() != null) {
1548-
Host lastHost = ApiDBUtils.findHostById(vm.getLastHostId());
1549-
if (lastHost != null) {
1550-
vmResponse.setHypervisor(lastHost.getHypervisorType().toString());
15511546
}
15521547
}
15531548

server/src/main/java/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public DomainRouterResponse newDomainRouterResponse(DomainRouterJoinVO router, A
118118
routerResponse.setRequiresUpgrade(true);
119119
}
120120

121+
routerResponse.setHypervisor(router.getHypervisorType().toString());
121122
routerResponse.setHasAnnotation(annotationDao.hasAnnotations(router.getUuid(), AnnotationService.EntityType.VR.name(),
122123
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
123124

@@ -126,7 +127,6 @@ public DomainRouterResponse newDomainRouterResponse(DomainRouterJoinVO router, A
126127
if (router.getHostId() != null) {
127128
routerResponse.setHostId(router.getHostUuid());
128129
routerResponse.setHostName(router.getHostName());
129-
routerResponse.setHypervisor(router.getHypervisorType().toString());
130130
}
131131
routerResponse.setPodId(router.getPodUuid());
132132
HostPodVO pod = ApiDBUtils.findPodById(router.getPodId());

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
630630
HypervisorType.Simulator
631631
));
632632

633+
private static final List<HypervisorType> HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS = Arrays.asList(HypervisorType.KVM, HypervisorType.VMware);
634+
633635
@Override
634636
public UserVmVO getVirtualMachine(long vmId) {
635637
return _vmDao.findById(vmId);
@@ -6093,16 +6095,18 @@ private VMInstanceVO preVmStorageMigrationCheck(Long vmId) {
60936095
throw ex;
60946096
}
60956097

6096-
if (vm.getType() != VirtualMachine.Type.User && !HypervisorType.VMware.equals(vm.getHypervisorType())) {
6097-
throw new InvalidParameterValueException("cannot do storage migration on non-user vm for hypervisor: " + vm.getHypervisorType().toString() + ", only supported for VMware");
6098+
HypervisorType hypervisorType = vm.getHypervisorType();
6099+
if (vm.getType() != VirtualMachine.Type.User && !HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS.contains(hypervisorType)) {
6100+
throw new InvalidParameterValueException(String.format("Unable to migrate storage of non-user VMs for hypervisor [%s]. Operation only supported for the following"
6101+
+ " hypervisors: [%s].", hypervisorType, HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS));
60986102
}
60996103

61006104
List<VolumeVO> vols = _volsDao.findByInstance(vm.getId());
61016105
if (vols.size() > 1) {
61026106
// OffLineVmwareMigration: data disks are not permitted, here!
61036107
if (vols.size() > 1 &&
61046108
// OffLineVmwareMigration: allow multiple disks for vmware
6105-
!HypervisorType.VMware.equals(vm.getHypervisorType())) {
6109+
!HypervisorType.VMware.equals(hypervisorType)) {
61066110
throw new InvalidParameterValueException("Data disks attached to the vm, can not migrate. Need to detach data disks first");
61076111
}
61086112
}

ui/src/config/section/infra/routers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ export default {
193193
icon: 'drag-outlined',
194194
label: 'label.action.migrate.systemvm.to.ps',
195195
dataView: true,
196-
show: (record, store) => { return ['Stopped'].includes(record.state) && ['VMware'].includes(record.hypervisor) },
196+
show: (record, store) => { return ['Stopped'].includes(record.state) && ['VMware', 'KVM'].includes(record.hypervisor) },
197197
component: shallowRef(defineAsyncComponent(() => import('@/views/compute/MigrateVMStorage'))),
198198
popup: true
199199
},

ui/src/config/section/infra/systemVms.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export default {
109109
icon: 'drag-outlined',
110110
label: 'label.action.migrate.systemvm.to.ps',
111111
dataView: true,
112-
show: (record, store) => { return ['Stopped'].includes(record.state) && ['VMware'].includes(record.hypervisor) },
112+
show: (record, store) => { return ['Stopped'].includes(record.state) && ['VMware', 'KVM'].includes(record.hypervisor) },
113113
component: shallowRef(defineAsyncComponent(() => import('@/views/compute/MigrateVMStorage'))),
114114
popup: true
115115
},

0 commit comments

Comments
 (0)