Skip to content

Commit bf8dd82

Browse files
committed
CLOUDSTACK-7981: listVirtualMachine is too slow in case of duplicate
resource tags due to joining user_vm_details to user_vm_view.
1 parent 8657659 commit bf8dd82

7 files changed

Lines changed: 213 additions & 85 deletions

File tree

api/src/org/apache/cloudstack/api/response/UserVmResponse.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
240240
@Param(description = "the list of resource tags associated with vm", responseObject = ResourceTagResponse.class)
241241
private Set<ResourceTagResponse> tags;
242242

243+
transient Set<Long> tagIds;
244+
243245
@SerializedName(ApiConstants.DETAILS)
244246
@Param(description = "Vm details in key/value pairs.", since = "4.2.1")
245247
private Map details;
@@ -272,6 +274,7 @@ public UserVmResponse() {
272274
securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
273275
nics = new LinkedHashSet<NicResponse>();
274276
tags = new LinkedHashSet<ResourceTagResponse>();
277+
tagIds = new LinkedHashSet<Long>();
275278
affinityGroupList = new LinkedHashSet<AffinityGroupResponse>();
276279
}
277280

@@ -723,6 +726,10 @@ public void setInstanceName(String instanceName) {
723726
this.instanceName = instanceName;
724727
}
725728

729+
public boolean containTag(Long tagId) {
730+
return tagIds.contains(tagId);
731+
}
732+
726733
public void setTags(Set<ResourceTagResponse> tags) {
727734
this.tags = tags;
728735
}

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,12 +1633,7 @@ public static ResourceTagJoinVO newResourceTagView(ResourceTag sg) {
16331633
}
16341634

16351635
public static ResourceTagJoinVO findResourceTagViewById(Long tagId) {
1636-
List<ResourceTagJoinVO> tags = s_tagJoinDao.searchByIds(tagId);
1637-
if (tags != null && tags.size() > 0) {
1638-
return tags.get(0);
1639-
} else {
1640-
return null;
1641-
}
1636+
return s_tagJoinDao.searchById(tagId);
16421637
}
16431638

16441639
public static EventResponse newEventResponse(EventJoinVO ve) {

server/src/com/cloud/api/query/dao/ResourceTagJoinDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ public interface ResourceTagJoinDao extends GenericDao<ResourceTagJoinVO, Long>
3434
List<ResourceTagJoinVO> searchByIds(Long... ids);
3535

3636
List<ResourceTagJoinVO> listBy(String resourceUUID, ResourceObjectType resourceType);
37+
38+
ResourceTagJoinVO searchById(Long id);
3739
}

server/src/com/cloud/api/query/dao/ResourceTagJoinDaoImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@ public List<ResourceTagJoinVO> searchByIds(Long... tagIds) {
145145
return uvList;
146146
}
147147

148+
@Override
149+
public ResourceTagJoinVO searchById(Long id) {
150+
SearchCriteria<ResourceTagJoinVO> sc = tagIdSearch.create();
151+
sc.setParameters("id", id);
152+
List<ResourceTagJoinVO> vms = searchIncludingRemoved(sc, null, null, false);
153+
assert vms != null && vms.size() == 1 : "No tag found for tag id " + id;
154+
return vms.get(0);
155+
}
156+
148157
@Override
149158
public ResourceTagJoinVO newResourceTagView(ResourceTag vr) {
150159

server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public UserVmResponse newUserVmResponse(ResponseView view, String objectName, Us
262262

263263
// update tag information
264264
long tag_id = userVm.getTagId();
265-
if (tag_id > 0) {
265+
if (tag_id > 0 && !userVmResponse.containTag(tag_id)) {
266266
ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
267267
if (vtag != null) {
268268
userVmResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));
@@ -350,7 +350,7 @@ public UserVmResponse setUserVmResponse(ResponseView view, UserVmResponse userVm
350350
}
351351

352352
long tag_id = uvo.getTagId();
353-
if (tag_id > 0) {
353+
if (tag_id > 0 && !userVmData.containTag(tag_id)) {
354354
ResourceTagJoinVO vtag = ApiDBUtils.findResourceTagViewById(tag_id);
355355
if (vtag != null) {
356356
userVmData.addTag(ApiDBUtils.newResourceTagResponse(vtag, false));

server/src/com/cloud/api/query/vo/UserVmJoinVO.java

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import com.cloud.hypervisor.Hypervisor.HypervisorType;
3232
import com.cloud.network.Network.GuestType;
3333
import com.cloud.network.Networks.TrafficType;
34-
import com.cloud.server.ResourceTag.ResourceObjectType;
3534
import com.cloud.storage.Storage.StoragePoolType;
3635
import com.cloud.storage.Volume;
3736
import com.cloud.utils.db.GenericDao;
@@ -346,34 +345,6 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
346345
@Column(name = "tag_id")
347346
private long tagId;
348347

349-
@Column(name = "tag_uuid")
350-
private String tagUuid;
351-
352-
@Column(name = "tag_key")
353-
private String tagKey;
354-
355-
@Column(name = "tag_value")
356-
private String tagValue;
357-
358-
@Column(name = "tag_domain_id")
359-
private long tagDomainId;
360-
361-
@Column(name = "tag_account_id")
362-
private long tagAccountId;
363-
364-
@Column(name = "tag_resource_id")
365-
private long tagResourceId;
366-
367-
@Column(name = "tag_resource_uuid")
368-
private String tagResourceUuid;
369-
370-
@Column(name = "tag_resource_type")
371-
@Enumerated(value = EnumType.STRING)
372-
private ResourceObjectType tagResourceType;
373-
374-
@Column(name = "tag_customer")
375-
private String tagCustomer;
376-
377348
@Column(name = "affinity_group_id")
378349
private long affinityGroupId;
379350

@@ -397,11 +368,6 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
397368
@Column(name = "dynamically_scalable")
398369
private boolean isDynamicallyScalable;
399370

400-
@Column(name = "detail_name")
401-
private String detailName;
402-
403-
@Column(name = "detail_value")
404-
private String detailValue;
405371

406372
public UserVmJoinVO() {
407373
}
@@ -780,42 +746,6 @@ public long getTagId() {
780746
return tagId;
781747
}
782748

783-
public String getTagUuid() {
784-
return tagUuid;
785-
}
786-
787-
public String getTagKey() {
788-
return tagKey;
789-
}
790-
791-
public String getTagValue() {
792-
return tagValue;
793-
}
794-
795-
public long getTagDomainId() {
796-
return tagDomainId;
797-
}
798-
799-
public long getTagAccountId() {
800-
return tagAccountId;
801-
}
802-
803-
public long getTagResourceId() {
804-
return tagResourceId;
805-
}
806-
807-
public String getTagResourceUuid() {
808-
return tagResourceUuid;
809-
}
810-
811-
public ResourceObjectType getTagResourceType() {
812-
return tagResourceType;
813-
}
814-
815-
public String getTagCustomer() {
816-
return tagCustomer;
817-
}
818-
819749
public boolean isLimitCpuUse() {
820750
return limitCpuUse;
821751
}
@@ -902,13 +832,6 @@ public Boolean isDynamicallyScalable() {
902832
return isDynamicallyScalable;
903833
}
904834

905-
public String getDetailName() {
906-
return detailName;
907-
}
908-
909-
public String getDetailValue() {
910-
return detailValue;
911-
}
912835

913836
@Override
914837
public Class<?> getEntityType() {

setup/db/db/schema-442to450.sql

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,198 @@ CREATE VIEW `cloud`.`domain_router_view` AS
543543
and async_job.instance_type = 'DomainRouter'
544544
and async_job.job_status = 0;
545545

546+
DROP VIEW IF EXISTS `cloud`.`user_vm_view`;
547+
CREATE VIEW `cloud`.`user_vm_view` AS
548+
select
549+
vm_instance.id id,
550+
vm_instance.name name,
551+
user_vm.display_name display_name,
552+
user_vm.user_data user_data,
553+
account.id account_id,
554+
account.uuid account_uuid,
555+
account.account_name account_name,
556+
account.type account_type,
557+
domain.id domain_id,
558+
domain.uuid domain_uuid,
559+
domain.name domain_name,
560+
domain.path domain_path,
561+
projects.id project_id,
562+
projects.uuid project_uuid,
563+
projects.name project_name,
564+
instance_group.id instance_group_id,
565+
instance_group.uuid instance_group_uuid,
566+
instance_group.name instance_group_name,
567+
vm_instance.uuid uuid,
568+
vm_instance.last_host_id last_host_id,
569+
vm_instance.vm_type type,
570+
vm_instance.vnc_password vnc_password,
571+
vm_instance.limit_cpu_use limit_cpu_use,
572+
vm_instance.created created,
573+
vm_instance.state state,
574+
vm_instance.removed removed,
575+
vm_instance.ha_enabled ha_enabled,
576+
vm_instance.hypervisor_type hypervisor_type,
577+
vm_instance.instance_name instance_name,
578+
vm_instance.guest_os_id guest_os_id,
579+
vm_instance.display_vm display_vm,
580+
guest_os.uuid guest_os_uuid,
581+
vm_instance.pod_id pod_id,
582+
host_pod_ref.uuid pod_uuid,
583+
vm_instance.private_ip_address private_ip_address,
584+
vm_instance.private_mac_address private_mac_address,
585+
vm_instance.vm_type vm_type,
586+
data_center.id data_center_id,
587+
data_center.uuid data_center_uuid,
588+
data_center.name data_center_name,
589+
data_center.is_security_group_enabled security_group_enabled,
590+
data_center.networktype data_center_type,
591+
host.id host_id,
592+
host.uuid host_uuid,
593+
host.name host_name,
594+
vm_template.id template_id,
595+
vm_template.uuid template_uuid,
596+
vm_template.name template_name,
597+
vm_template.display_text template_display_text,
598+
vm_template.enable_password password_enabled,
599+
iso.id iso_id,
600+
iso.uuid iso_uuid,
601+
iso.name iso_name,
602+
iso.display_text iso_display_text,
603+
service_offering.id service_offering_id,
604+
svc_disk_offering.uuid service_offering_uuid,
605+
disk_offering.uuid disk_offering_uuid,
606+
disk_offering.id disk_offering_id,
607+
Case
608+
When (`cloud`.`service_offering`.`cpu` is null) then (`custom_cpu`.`value`)
609+
Else ( `cloud`.`service_offering`.`cpu`)
610+
End as `cpu`,
611+
Case
612+
When (`cloud`.`service_offering`.`speed` is null) then (`custom_speed`.`value`)
613+
Else ( `cloud`.`service_offering`.`speed`)
614+
End as `speed`,
615+
Case
616+
When (`cloud`.`service_offering`.`ram_size` is null) then (`custom_ram_size`.`value`)
617+
Else ( `cloud`.`service_offering`.`ram_size`)
618+
END as `ram_size`,
619+
svc_disk_offering.name service_offering_name,
620+
disk_offering.name disk_offering_name,
621+
storage_pool.id pool_id,
622+
storage_pool.uuid pool_uuid,
623+
storage_pool.pool_type pool_type,
624+
volumes.id volume_id,
625+
volumes.uuid volume_uuid,
626+
volumes.device_id volume_device_id,
627+
volumes.volume_type volume_type,
628+
security_group.id security_group_id,
629+
security_group.uuid security_group_uuid,
630+
security_group.name security_group_name,
631+
security_group.description security_group_description,
632+
nics.id nic_id,
633+
nics.uuid nic_uuid,
634+
nics.network_id network_id,
635+
nics.ip4_address ip_address,
636+
nics.ip6_address ip6_address,
637+
nics.ip6_gateway ip6_gateway,
638+
nics.ip6_cidr ip6_cidr,
639+
nics.default_nic is_default_nic,
640+
nics.gateway gateway,
641+
nics.netmask netmask,
642+
nics.mac_address mac_address,
643+
nics.broadcast_uri broadcast_uri,
644+
nics.isolation_uri isolation_uri,
645+
vpc.id vpc_id,
646+
vpc.uuid vpc_uuid,
647+
networks.uuid network_uuid,
648+
networks.name network_name,
649+
networks.traffic_type traffic_type,
650+
networks.guest_type guest_type,
651+
user_ip_address.id public_ip_id,
652+
user_ip_address.uuid public_ip_uuid,
653+
user_ip_address.public_ip_address public_ip_address,
654+
ssh_keypairs.keypair_name keypair_name,
655+
resource_tags.id tag_id,
656+
async_job.id job_id,
657+
async_job.uuid job_uuid,
658+
async_job.job_status job_status,
659+
async_job.account_id job_account_id,
660+
affinity_group.id affinity_group_id,
661+
affinity_group.uuid affinity_group_uuid,
662+
affinity_group.name affinity_group_name,
663+
affinity_group.description affinity_group_description,
664+
vm_instance.dynamically_scalable dynamically_scalable
665+
666+
from
667+
`cloud`.`user_vm`
668+
inner join
669+
`cloud`.`vm_instance` ON vm_instance.id = user_vm.id
670+
and vm_instance.removed is NULL
671+
inner join
672+
`cloud`.`account` ON vm_instance.account_id = account.id
673+
inner join
674+
`cloud`.`domain` ON vm_instance.domain_id = domain.id
675+
left join
676+
`cloud`.`guest_os` ON vm_instance.guest_os_id = guest_os.id
677+
left join
678+
`cloud`.`host_pod_ref` ON vm_instance.pod_id = host_pod_ref.id
679+
left join
680+
`cloud`.`projects` ON projects.project_account_id = account.id
681+
left join
682+
`cloud`.`instance_group_vm_map` ON vm_instance.id = instance_group_vm_map.instance_id
683+
left join
684+
`cloud`.`instance_group` ON instance_group_vm_map.group_id = instance_group.id
685+
left join
686+
`cloud`.`data_center` ON vm_instance.data_center_id = data_center.id
687+
left join
688+
`cloud`.`host` ON vm_instance.host_id = host.id
689+
left join
690+
`cloud`.`vm_template` ON vm_instance.vm_template_id = vm_template.id
691+
left join
692+
`cloud`.`vm_template` iso ON iso.id = user_vm.iso_id
693+
left join
694+
`cloud`.`service_offering` ON vm_instance.service_offering_id = service_offering.id
695+
left join
696+
`cloud`.`disk_offering` svc_disk_offering ON vm_instance.service_offering_id = svc_disk_offering.id
697+
left join
698+
`cloud`.`disk_offering` ON vm_instance.disk_offering_id = disk_offering.id
699+
left join
700+
`cloud`.`volumes` ON vm_instance.id = volumes.instance_id
701+
left join
702+
`cloud`.`storage_pool` ON volumes.pool_id = storage_pool.id
703+
left join
704+
`cloud`.`security_group_vm_map` ON vm_instance.id = security_group_vm_map.instance_id
705+
left join
706+
`cloud`.`security_group` ON security_group_vm_map.security_group_id = security_group.id
707+
left join
708+
`cloud`.`nics` ON vm_instance.id = nics.instance_id and nics.removed is null
709+
left join
710+
`cloud`.`networks` ON nics.network_id = networks.id
711+
left join
712+
`cloud`.`vpc` ON networks.vpc_id = vpc.id and vpc.removed is null
713+
left join
714+
`cloud`.`user_ip_address` ON user_ip_address.vm_id = vm_instance.id
715+
left join
716+
`cloud`.`user_vm_details` as ssh_details ON ssh_details.vm_id = vm_instance.id
717+
and ssh_details.name = 'SSH.PublicKey'
718+
left join
719+
`cloud`.`ssh_keypairs` ON ssh_keypairs.public_key = ssh_details.value
720+
left join
721+
`cloud`.`resource_tags` ON resource_tags.resource_id = vm_instance.id
722+
and resource_tags.resource_type = 'UserVm'
723+
left join
724+
`cloud`.`async_job` ON async_job.instance_id = vm_instance.id
725+
and async_job.instance_type = 'VirtualMachine'
726+
and async_job.job_status = 0
727+
left join
728+
`cloud`.`affinity_group_vm_map` ON vm_instance.id = affinity_group_vm_map.instance_id
729+
left join
730+
`cloud`.`affinity_group` ON affinity_group_vm_map.affinity_group_id = affinity_group.id
731+
left join
732+
`cloud`.`user_vm_details` `custom_cpu` ON (((`custom_cpu`.`vm_id` = `cloud`.`vm_instance`.`id`) and (`custom_cpu`.`name` = 'CpuNumber')))
733+
left join
734+
`cloud`.`user_vm_details` `custom_speed` ON (((`custom_speed`.`vm_id` = `cloud`.`vm_instance`.`id`) and (`custom_speed`.`name` = 'CpuSpeed')))
735+
left join
736+
`cloud`.`user_vm_details` `custom_ram_size` ON (((`custom_ram_size`.`vm_id` = `cloud`.`vm_instance`.`id`) and (`custom_ram_size`.`name` = 'memory')));
737+
546738

547739
INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name, created) VALUES (231, UUID(), 1, 'CentOS 5 (32-bit)', utc_timestamp());
548740
INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name, created) VALUES (232, UUID(), 1, 'CentOS 5 (64-bit)', utc_timestamp());

0 commit comments

Comments
 (0)