From 8d4b4dcec42f2eccb63e563ba14197ae229474f0 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 16 Feb 2024 15:01:27 +0100 Subject: [PATCH 1/9] CKS: add kube config path in extra control nodes (#8658) --- .../src/main/resources/conf/k8s-control-node-add.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml index b4167147ba4..2c18efa0189 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml +++ b/plugins/integrations/kubernetes-service/src/main/resources/conf/k8s-control-node-add.yml @@ -221,6 +221,10 @@ write_files: fi kubeadm join {{ k8s_control_node.join_ip }}:6443 --token {{ k8s_control_node.cluster.token }} --control-plane --certificate-key {{ k8s_control_node.cluster.ha.certificate.key }} --discovery-token-unsafe-skip-ca-verification + mkdir -p /root/.kube + cp -i /etc/kubernetes/admin.conf /root/.kube/config + chown $(id -u):$(id -g) /root/.kube/config + sudo touch /home/cloud/success echo "true" > /home/cloud/success From e9416c4987e77a658a82197ee9288e404fdfb139 Mon Sep 17 00:00:00 2001 From: dahn Date: Sat, 17 Feb 2024 09:31:43 +0100 Subject: [PATCH 2/9] Move views into separate files for easier modification (#8647) * volume view in separate file for easier modification * eof * remaining views * lintworm --- .../db/views/cloud.account_netstats_view.sql | 31 ++++ .../META-INF/db/views/cloud.account_view.sql | 166 ++++++++++++++++++ .../db/views/cloud.account_vmstats_view.sql | 35 ++++ .../db/views/cloud.affinity_group_view.sql | 60 +++++++ .../META-INF/db/views/cloud.domain_view.sql | 60 +++++++ .../META-INF/db/views/cloud.event_view.sql | 63 +++++++ .../META-INF/db/views/cloud.free_ip_view.sql | 32 ++++ .../db/views/cloud.image_store_view.sql | 45 +++++ .../db/views/cloud.instance_group_view.sql | 48 +++++ .../db/views/cloud.last_annotation_view.sql | 43 +++++ .../META-INF/db/views/cloud.mshost_view.sql | 46 +++++ .../db/views/cloud.project_account_view.sql | 54 ++++++ .../views/cloud.project_invitation_view.sql | 52 ++++++ .../META-INF/db/views/cloud.project_view.sql | 50 ++++++ .../db/views/cloud.resource_tag_view.sql | 51 ++++++ .../db/views/cloud.security_group_view.sql | 79 +++++++++ .../META-INF/db/views/cloud.volume_view.sql | 156 ++++++++++++++++ .../db/views/cloud.vpc_offering_view.sql | 63 +++++++ 18 files changed, 1134 insertions(+) create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.account_netstats_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.account_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.account_vmstats_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.affinity_group_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.domain_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.event_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.free_ip_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.image_store_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.instance_group_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.last_annotation_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.mshost_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.project_account_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.project_invitation_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.project_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.resource_tag_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.security_group_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql create mode 100644 engine/schema/src/main/resources/META-INF/db/views/cloud.vpc_offering_view.sql diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.account_netstats_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.account_netstats_view.sql new file mode 100644 index 00000000000..11193c465fd --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.account_netstats_view.sql @@ -0,0 +1,31 @@ +-- 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. + +-- cloud.account_netstats_view source + + +DROP VIEW IF EXISTS `cloud`.`account_netstats_view`; + +CREATE VIEW `cloud`.`account_netstats_view` AS +select + `user_statistics`.`account_id` AS `account_id`, + (sum(`user_statistics`.`net_bytes_received`) + sum(`user_statistics`.`current_bytes_received`)) AS `bytesReceived`, + (sum(`user_statistics`.`net_bytes_sent`) + sum(`user_statistics`.`current_bytes_sent`)) AS `bytesSent` +from + `user_statistics` +group by + `user_statistics`.`account_id`; diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.account_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.account_view.sql new file mode 100644 index 00000000000..27d70b4171c --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.account_view.sql @@ -0,0 +1,166 @@ +-- 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. + +-- cloud.account_view source + + +DROP VIEW IF EXISTS `cloud`.`account_view`; + +CREATE VIEW `cloud`.`account_view` AS +select + `account`.`id` AS `id`, + `account`.`uuid` AS `uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `type`, + `account`.`role_id` AS `role_id`, + `account`.`state` AS `state`, + `account`.`created` AS `created`, + `account`.`removed` AS `removed`, + `account`.`cleanup_needed` AS `cleanup_needed`, + `account`.`network_domain` AS `network_domain`, + `account`.`default` AS `default`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `data_center`.`id` AS `data_center_id`, + `data_center`.`uuid` AS `data_center_uuid`, + `data_center`.`name` AS `data_center_name`, + `account_netstats_view`.`bytesReceived` AS `bytesReceived`, + `account_netstats_view`.`bytesSent` AS `bytesSent`, + `vmlimit`.`max` AS `vmLimit`, + `vmcount`.`count` AS `vmTotal`, + `runningvm`.`vmcount` AS `runningVms`, + `stoppedvm`.`vmcount` AS `stoppedVms`, + `iplimit`.`max` AS `ipLimit`, + `ipcount`.`count` AS `ipTotal`, + `free_ip_view`.`free_ip` AS `ipFree`, + `volumelimit`.`max` AS `volumeLimit`, + `volumecount`.`count` AS `volumeTotal`, + `snapshotlimit`.`max` AS `snapshotLimit`, + `snapshotcount`.`count` AS `snapshotTotal`, + `templatelimit`.`max` AS `templateLimit`, + `templatecount`.`count` AS `templateTotal`, + `vpclimit`.`max` AS `vpcLimit`, + `vpccount`.`count` AS `vpcTotal`, + `projectlimit`.`max` AS `projectLimit`, + `projectcount`.`count` AS `projectTotal`, + `networklimit`.`max` AS `networkLimit`, + `networkcount`.`count` AS `networkTotal`, + `cpulimit`.`max` AS `cpuLimit`, + `cpucount`.`count` AS `cpuTotal`, + `memorylimit`.`max` AS `memoryLimit`, + `memorycount`.`count` AS `memoryTotal`, + `primary_storage_limit`.`max` AS `primaryStorageLimit`, + `primary_storage_count`.`count` AS `primaryStorageTotal`, + `secondary_storage_limit`.`max` AS `secondaryStorageLimit`, + `secondary_storage_count`.`count` AS `secondaryStorageTotal`, + `async_job`.`id` AS `job_id`, + `async_job`.`uuid` AS `job_uuid`, + `async_job`.`job_status` AS `job_status`, + `async_job`.`account_id` AS `job_account_id` +from + (`free_ip_view` +join ((((((((((((((((((((((((((((((`account` +join `domain` on + ((`account`.`domain_id` = `domain`.`id`))) +left join `data_center` on + ((`account`.`default_zone_id` = `data_center`.`id`))) +left join `account_netstats_view` on + ((`account`.`id` = `account_netstats_view`.`account_id`))) +left join `resource_limit` `vmlimit` on + (((`account`.`id` = `vmlimit`.`account_id`) + and (`vmlimit`.`type` = 'user_vm')))) +left join `resource_count` `vmcount` on + (((`account`.`id` = `vmcount`.`account_id`) + and (`vmcount`.`type` = 'user_vm')))) +left join `account_vmstats_view` `runningvm` on + (((`account`.`id` = `runningvm`.`account_id`) + and (`runningvm`.`state` = 'Running')))) +left join `account_vmstats_view` `stoppedvm` on + (((`account`.`id` = `stoppedvm`.`account_id`) + and (`stoppedvm`.`state` = 'Stopped')))) +left join `resource_limit` `iplimit` on + (((`account`.`id` = `iplimit`.`account_id`) + and (`iplimit`.`type` = 'public_ip')))) +left join `resource_count` `ipcount` on + (((`account`.`id` = `ipcount`.`account_id`) + and (`ipcount`.`type` = 'public_ip')))) +left join `resource_limit` `volumelimit` on + (((`account`.`id` = `volumelimit`.`account_id`) + and (`volumelimit`.`type` = 'volume')))) +left join `resource_count` `volumecount` on + (((`account`.`id` = `volumecount`.`account_id`) + and (`volumecount`.`type` = 'volume')))) +left join `resource_limit` `snapshotlimit` on + (((`account`.`id` = `snapshotlimit`.`account_id`) + and (`snapshotlimit`.`type` = 'snapshot')))) +left join `resource_count` `snapshotcount` on + (((`account`.`id` = `snapshotcount`.`account_id`) + and (`snapshotcount`.`type` = 'snapshot')))) +left join `resource_limit` `templatelimit` on + (((`account`.`id` = `templatelimit`.`account_id`) + and (`templatelimit`.`type` = 'template')))) +left join `resource_count` `templatecount` on + (((`account`.`id` = `templatecount`.`account_id`) + and (`templatecount`.`type` = 'template')))) +left join `resource_limit` `vpclimit` on + (((`account`.`id` = `vpclimit`.`account_id`) + and (`vpclimit`.`type` = 'vpc')))) +left join `resource_count` `vpccount` on + (((`account`.`id` = `vpccount`.`account_id`) + and (`vpccount`.`type` = 'vpc')))) +left join `resource_limit` `projectlimit` on + (((`account`.`id` = `projectlimit`.`account_id`) + and (`projectlimit`.`type` = 'project')))) +left join `resource_count` `projectcount` on + (((`account`.`id` = `projectcount`.`account_id`) + and (`projectcount`.`type` = 'project')))) +left join `resource_limit` `networklimit` on + (((`account`.`id` = `networklimit`.`account_id`) + and (`networklimit`.`type` = 'network')))) +left join `resource_count` `networkcount` on + (((`account`.`id` = `networkcount`.`account_id`) + and (`networkcount`.`type` = 'network')))) +left join `resource_limit` `cpulimit` on + (((`account`.`id` = `cpulimit`.`account_id`) + and (`cpulimit`.`type` = 'cpu')))) +left join `resource_count` `cpucount` on + (((`account`.`id` = `cpucount`.`account_id`) + and (`cpucount`.`type` = 'cpu')))) +left join `resource_limit` `memorylimit` on + (((`account`.`id` = `memorylimit`.`account_id`) + and (`memorylimit`.`type` = 'memory')))) +left join `resource_count` `memorycount` on + (((`account`.`id` = `memorycount`.`account_id`) + and (`memorycount`.`type` = 'memory')))) +left join `resource_limit` `primary_storage_limit` on + (((`account`.`id` = `primary_storage_limit`.`account_id`) + and (`primary_storage_limit`.`type` = 'primary_storage')))) +left join `resource_count` `primary_storage_count` on + (((`account`.`id` = `primary_storage_count`.`account_id`) + and (`primary_storage_count`.`type` = 'primary_storage')))) +left join `resource_limit` `secondary_storage_limit` on + (((`account`.`id` = `secondary_storage_limit`.`account_id`) + and (`secondary_storage_limit`.`type` = 'secondary_storage')))) +left join `resource_count` `secondary_storage_count` on + (((`account`.`id` = `secondary_storage_count`.`account_id`) + and (`secondary_storage_count`.`type` = 'secondary_storage')))) +left join `async_job` on + (((`async_job`.`instance_id` = `account`.`id`) + and (`async_job`.`instance_type` = 'Account') + and (`async_job`.`job_status` = 0))))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.account_vmstats_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.account_vmstats_view.sql new file mode 100644 index 00000000000..df6a216b0f8 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.account_vmstats_view.sql @@ -0,0 +1,35 @@ +-- 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. + +-- cloud.account_vmstats_view source + + +DROP VIEW IF EXISTS `cloud`.`account_vmstats_view`; + +CREATE VIEW `cloud`.`account_vmstats_view` AS +select + `vm_instance`.`account_id` AS `account_id`, + `vm_instance`.`state` AS `state`, + count(0) AS `vmcount` +from + `vm_instance` +where + ((`vm_instance`.`vm_type` = 'User') + and (`vm_instance`.`removed` is null)) +group by + `vm_instance`.`account_id`, + `vm_instance`.`state`; diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.affinity_group_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.affinity_group_view.sql new file mode 100644 index 00000000000..90a398e1ec5 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.affinity_group_view.sql @@ -0,0 +1,60 @@ +-- 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. + +-- cloud.affinity_group_view source + + +DROP VIEW IF EXISTS `cloud`.`affinity_group_view`; + +CREATE VIEW `cloud`.`affinity_group_view` AS +select + `affinity_group`.`id` AS `id`, + `affinity_group`.`name` AS `name`, + `affinity_group`.`type` AS `type`, + `affinity_group`.`description` AS `description`, + `affinity_group`.`uuid` AS `uuid`, + `affinity_group`.`acl_type` AS `acl_type`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name`, + `vm_instance`.`id` AS `vm_id`, + `vm_instance`.`uuid` AS `vm_uuid`, + `vm_instance`.`name` AS `vm_name`, + `vm_instance`.`state` AS `vm_state`, + `user_vm`.`display_name` AS `vm_display_name` +from + ((((((`affinity_group` +join `account` on + ((`affinity_group`.`account_id` = `account`.`id`))) +join `domain` on + ((`affinity_group`.`domain_id` = `domain`.`id`))) +left join `projects` on + ((`projects`.`project_account_id` = `account`.`id`))) +left join `affinity_group_vm_map` on + ((`affinity_group`.`id` = `affinity_group_vm_map`.`affinity_group_id`))) +left join `vm_instance` on + ((`vm_instance`.`id` = `affinity_group_vm_map`.`instance_id`))) +left join `user_vm` on + ((`user_vm`.`id` = `vm_instance`.`id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.domain_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.domain_view.sql new file mode 100644 index 00000000000..90a398e1ec5 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.domain_view.sql @@ -0,0 +1,60 @@ +-- 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. + +-- cloud.affinity_group_view source + + +DROP VIEW IF EXISTS `cloud`.`affinity_group_view`; + +CREATE VIEW `cloud`.`affinity_group_view` AS +select + `affinity_group`.`id` AS `id`, + `affinity_group`.`name` AS `name`, + `affinity_group`.`type` AS `type`, + `affinity_group`.`description` AS `description`, + `affinity_group`.`uuid` AS `uuid`, + `affinity_group`.`acl_type` AS `acl_type`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name`, + `vm_instance`.`id` AS `vm_id`, + `vm_instance`.`uuid` AS `vm_uuid`, + `vm_instance`.`name` AS `vm_name`, + `vm_instance`.`state` AS `vm_state`, + `user_vm`.`display_name` AS `vm_display_name` +from + ((((((`affinity_group` +join `account` on + ((`affinity_group`.`account_id` = `account`.`id`))) +join `domain` on + ((`affinity_group`.`domain_id` = `domain`.`id`))) +left join `projects` on + ((`projects`.`project_account_id` = `account`.`id`))) +left join `affinity_group_vm_map` on + ((`affinity_group`.`id` = `affinity_group_vm_map`.`affinity_group_id`))) +left join `vm_instance` on + ((`vm_instance`.`id` = `affinity_group_vm_map`.`instance_id`))) +left join `user_vm` on + ((`user_vm`.`id` = `vm_instance`.`id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.event_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.event_view.sql new file mode 100644 index 00000000000..0a15ae4c0c9 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.event_view.sql @@ -0,0 +1,63 @@ +-- 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. + +-- cloud.event_view source + + +DROP VIEW IF EXISTS `cloud`.`event_view`; + +CREATE VIEW `cloud`.`event_view` AS +select + `event`.`id` AS `id`, + `event`.`uuid` AS `uuid`, + `event`.`type` AS `type`, + `event`.`state` AS `state`, + `event`.`description` AS `description`, + `event`.`resource_id` AS `resource_id`, + `event`.`resource_type` AS `resource_type`, + `event`.`created` AS `created`, + `event`.`level` AS `level`, + `event`.`parameters` AS `parameters`, + `event`.`start_id` AS `start_id`, + `eve`.`uuid` AS `start_uuid`, + `event`.`user_id` AS `user_id`, + `event`.`archived` AS `archived`, + `event`.`display` AS `display`, + `user`.`username` AS `user_name`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name` +from + (((((`event` +join `account` on + ((`event`.`account_id` = `account`.`id`))) +join `domain` on + ((`event`.`domain_id` = `domain`.`id`))) +join `user` on + ((`event`.`user_id` = `user`.`id`))) +left join `projects` on + ((`projects`.`project_account_id` = `event`.`account_id`))) +left join `event` `eve` on + ((`event`.`start_id` = `eve`.`id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.free_ip_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.free_ip_view.sql new file mode 100644 index 00000000000..29c22f33215 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.free_ip_view.sql @@ -0,0 +1,32 @@ +-- 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. + +-- cloud.free_ip_view source + + +DROP VIEW IF EXISTS `cloud`.`free_ip_view`; + +CREATE VIEW `cloud`.`free_ip_view` AS +select + count(`user_ip_address`.`id`) AS `free_ip` +from + (`user_ip_address` +join `vlan` on + (((`vlan`.`id` = `user_ip_address`.`vlan_db_id`) + and (`vlan`.`vlan_type` = 'VirtualNetwork')))) +where + (`user_ip_address`.`state` = 'Free'); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.image_store_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.image_store_view.sql new file mode 100644 index 00000000000..88d68302d4c --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.image_store_view.sql @@ -0,0 +1,45 @@ +-- 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. + +-- cloud.image_store_view source + + +DROP VIEW IF EXISTS `cloud`.`image_store_view`; + +CREATE VIEW `cloud`.`image_store_view` AS +select + `image_store`.`id` AS `id`, + `image_store`.`uuid` AS `uuid`, + `image_store`.`name` AS `name`, + `image_store`.`image_provider_name` AS `image_provider_name`, + `image_store`.`protocol` AS `protocol`, + `image_store`.`url` AS `url`, + `image_store`.`scope` AS `scope`, + `image_store`.`role` AS `role`, + `image_store`.`readonly` AS `readonly`, + `image_store`.`removed` AS `removed`, + `data_center`.`id` AS `data_center_id`, + `data_center`.`uuid` AS `data_center_uuid`, + `data_center`.`name` AS `data_center_name`, + `image_store_details`.`name` AS `detail_name`, + `image_store_details`.`value` AS `detail_value` +from + ((`image_store` +left join `data_center` on + ((`image_store`.`data_center_id` = `data_center`.`id`))) +left join `image_store_details` on + ((`image_store_details`.`store_id` = `image_store`.`id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.instance_group_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.instance_group_view.sql new file mode 100644 index 00000000000..8bdc8184718 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.instance_group_view.sql @@ -0,0 +1,48 @@ +-- 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. + +-- cloud.instance_group_view source + + +DROP VIEW IF EXISTS `cloud`.`instance_group_view`; + +CREATE VIEW `cloud`.`instance_group_view` AS +select + `instance_group`.`id` AS `id`, + `instance_group`.`uuid` AS `uuid`, + `instance_group`.`name` AS `name`, + `instance_group`.`removed` AS `removed`, + `instance_group`.`created` AS `created`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name` +from + (((`instance_group` +join `account` on + ((`instance_group`.`account_id` = `account`.`id`))) +join `domain` on + ((`account`.`domain_id` = `domain`.`id`))) +left join `projects` on + ((`projects`.`project_account_id` = `instance_group`.`account_id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.last_annotation_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.last_annotation_view.sql new file mode 100644 index 00000000000..f317fbacc4d --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.last_annotation_view.sql @@ -0,0 +1,43 @@ +-- 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. + +-- cloud.last_annotation_view source + + +DROP VIEW IF EXISTS `cloud`.`last_annotation_view`; + +CREATE VIEW `cloud`.`last_annotation_view` AS +select + `annotations`.`uuid` AS `uuid`, + `annotations`.`annotation` AS `annotation`, + `annotations`.`entity_uuid` AS `entity_uuid`, + `annotations`.`entity_type` AS `entity_type`, + `annotations`.`user_uuid` AS `user_uuid`, + `annotations`.`created` AS `created`, + `annotations`.`removed` AS `removed` +from + `annotations` +where + `annotations`.`created` in ( + select + max(`annotations`.`created`) + from + `annotations` + where + (`annotations`.`removed` is null) + group by + `annotations`.`entity_uuid`); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.mshost_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.mshost_view.sql new file mode 100644 index 00000000000..9b68f170e38 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.mshost_view.sql @@ -0,0 +1,46 @@ +-- 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. + +-- cloud.mshost_view source + + +DROP VIEW IF EXISTS `cloud`.`mshost_view`; + +CREATE VIEW `cloud`.`mshost_view` AS +select + `mshost`.`id` AS `id`, + `mshost`.`msid` AS `msid`, + `mshost`.`runid` AS `runid`, + `mshost`.`name` AS `name`, + `mshost`.`uuid` AS `uuid`, + `mshost`.`state` AS `state`, + `mshost`.`version` AS `version`, + `mshost`.`service_ip` AS `service_ip`, + `mshost`.`service_port` AS `service_port`, + `mshost`.`last_update` AS `last_update`, + `mshost`.`removed` AS `removed`, + `mshost`.`alert_count` AS `alert_count`, + `mshost_status`.`last_jvm_start` AS `last_jvm_start`, + `mshost_status`.`last_jvm_stop` AS `last_jvm_stop`, + `mshost_status`.`last_system_boot` AS `last_system_boot`, + `mshost_status`.`os_distribution` AS `os_distribution`, + `mshost_status`.`java_name` AS `java_name`, + `mshost_status`.`java_version` AS `java_version` +from + (`mshost` +left join `mshost_status` on + ((`mshost`.`uuid` = `mshost_status`.`ms_id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.project_account_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.project_account_view.sql new file mode 100644 index 00000000000..c89618970cd --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.project_account_view.sql @@ -0,0 +1,54 @@ +-- 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. + +-- cloud.project_account_view source + + +DROP VIEW IF EXISTS `cloud`.`project_account_view`; + +CREATE VIEW `cloud`.`project_account_view` AS +select + `project_account`.`id` AS `id`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `user`.`id` AS `user_id`, + `user`.`uuid` AS `user_uuid`, + `user`.`username` AS `user_name`, + `project_account`.`account_role` AS `account_role`, + `project_role`.`id` AS `project_role_id`, + `project_role`.`uuid` AS `project_role_uuid`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path` +from + (((((`project_account` +join `account` on + ((`project_account`.`account_id` = `account`.`id`))) +join `domain` on + ((`account`.`domain_id` = `domain`.`id`))) +join `projects` on + ((`projects`.`id` = `project_account`.`project_id`))) +left join `project_role` on + ((`project_account`.`project_role_id` = `project_role`.`id`))) +left join `user` on + ((`project_account`.`user_id` = `user`.`id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.project_invitation_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.project_invitation_view.sql new file mode 100644 index 00000000000..fae35b9373e --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.project_invitation_view.sql @@ -0,0 +1,52 @@ +-- 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. + +-- cloud.project_invitation_view source + + +DROP VIEW IF EXISTS `cloud`.`project_invitation_view`; + +CREATE VIEW `cloud`.`project_invitation_view` AS +select + `project_invitations`.`id` AS `id`, + `project_invitations`.`uuid` AS `uuid`, + `project_invitations`.`email` AS `email`, + `project_invitations`.`created` AS `created`, + `project_invitations`.`state` AS `state`, + `project_invitations`.`project_role_id` AS `project_role_id`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `user`.`id` AS `user_id`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path` +from + ((((`project_invitations` +left join `account` on + ((`project_invitations`.`account_id` = `account`.`id`))) +left join `domain` on + ((`project_invitations`.`domain_id` = `domain`.`id`))) +left join `projects` on + ((`projects`.`id` = `project_invitations`.`project_id`))) +left join `user` on + ((`project_invitations`.`user_id` = `user`.`id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.project_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.project_view.sql new file mode 100644 index 00000000000..31461b1dd1e --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.project_view.sql @@ -0,0 +1,50 @@ +-- 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. + +-- cloud.project_view source + + +DROP VIEW IF EXISTS `cloud`.`project_view`; + +CREATE VIEW `cloud`.`project_view` AS +select + `projects`.`id` AS `id`, + `projects`.`uuid` AS `uuid`, + `projects`.`name` AS `name`, + `projects`.`display_text` AS `display_text`, + `projects`.`state` AS `state`, + `projects`.`removed` AS `removed`, + `projects`.`created` AS `created`, + `projects`.`project_account_id` AS `project_account_id`, + `account`.`account_name` AS `owner`, + `pacct`.`account_id` AS `account_id`, + `pacct`.`user_id` AS `user_id`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path` +from + ((((`projects` +join `domain` on + ((`projects`.`domain_id` = `domain`.`id`))) +join `project_account` on + (((`projects`.`id` = `project_account`.`project_id`) + and (`project_account`.`account_role` = 'Admin')))) +join `account` on + ((`account`.`id` = `project_account`.`account_id`))) +left join `project_account` `pacct` on + ((`projects`.`id` = `pacct`.`project_id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.resource_tag_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.resource_tag_view.sql new file mode 100644 index 00000000000..3d77d49f870 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.resource_tag_view.sql @@ -0,0 +1,51 @@ +-- 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. + +-- cloud.resource_tag_view source + + +DROP VIEW IF EXISTS `cloud`.`resource_tag_view`; + +CREATE VIEW `cloud`.`resource_tag_view` AS +select + `resource_tags`.`id` AS `id`, + `resource_tags`.`uuid` AS `uuid`, + `resource_tags`.`key` AS `key`, + `resource_tags`.`value` AS `value`, + `resource_tags`.`resource_id` AS `resource_id`, + `resource_tags`.`resource_uuid` AS `resource_uuid`, + `resource_tags`.`resource_type` AS `resource_type`, + `resource_tags`.`customer` AS `customer`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name` +from + (((`resource_tags` +join `account` on + ((`resource_tags`.`account_id` = `account`.`id`))) +join `domain` on + ((`resource_tags`.`domain_id` = `domain`.`id`))) +left join `projects` on + ((`projects`.`project_account_id` = `resource_tags`.`account_id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.security_group_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.security_group_view.sql new file mode 100644 index 00000000000..3cae860c1c3 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.security_group_view.sql @@ -0,0 +1,79 @@ +-- 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. + +-- cloud.security_group_view source + + +DROP VIEW IF EXISTS `cloud`.`security_group_view`; + +CREATE VIEW `cloud`.`security_group_view` AS +select + `security_group`.`id` AS `id`, + `security_group`.`name` AS `name`, + `security_group`.`description` AS `description`, + `security_group`.`uuid` AS `uuid`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name`, + `security_group_rule`.`id` AS `rule_id`, + `security_group_rule`.`uuid` AS `rule_uuid`, + `security_group_rule`.`type` AS `rule_type`, + `security_group_rule`.`start_port` AS `rule_start_port`, + `security_group_rule`.`end_port` AS `rule_end_port`, + `security_group_rule`.`protocol` AS `rule_protocol`, + `security_group_rule`.`allowed_network_id` AS `rule_allowed_network_id`, + `security_group_rule`.`allowed_ip_cidr` AS `rule_allowed_ip_cidr`, + `security_group_rule`.`create_status` AS `rule_create_status`, + `resource_tags`.`id` AS `tag_id`, + `resource_tags`.`uuid` AS `tag_uuid`, + `resource_tags`.`key` AS `tag_key`, + `resource_tags`.`value` AS `tag_value`, + `resource_tags`.`domain_id` AS `tag_domain_id`, + `resource_tags`.`account_id` AS `tag_account_id`, + `resource_tags`.`resource_id` AS `tag_resource_id`, + `resource_tags`.`resource_uuid` AS `tag_resource_uuid`, + `resource_tags`.`resource_type` AS `tag_resource_type`, + `resource_tags`.`customer` AS `tag_customer`, + `async_job`.`id` AS `job_id`, + `async_job`.`uuid` AS `job_uuid`, + `async_job`.`job_status` AS `job_status`, + `async_job`.`account_id` AS `job_account_id` +from + ((((((`security_group` +left join `security_group_rule` on + ((`security_group`.`id` = `security_group_rule`.`security_group_id`))) +join `account` on + ((`security_group`.`account_id` = `account`.`id`))) +join `domain` on + ((`security_group`.`domain_id` = `domain`.`id`))) +left join `projects` on + ((`projects`.`project_account_id` = `security_group`.`account_id`))) +left join `resource_tags` on + (((`resource_tags`.`resource_id` = `security_group`.`id`) + and (`resource_tags`.`resource_type` = 'SecurityGroup')))) +left join `async_job` on + (((`async_job`.`instance_id` = `security_group`.`id`) + and (`async_job`.`instance_type` = 'SecurityGroup') + and (`async_job`.`job_status` = 0)))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql new file mode 100644 index 00000000000..fd21fff1494 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql @@ -0,0 +1,156 @@ +-- 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. + +-- VIEW `cloud`.`volume_view`; + +DROP VIEW IF EXISTS `cloud`.`volume_view`; + +CREATE VIEW `cloud`.`volume_view` AS +SELECT + `volumes`.`id` AS `id`, + `volumes`.`uuid` AS `uuid`, + `volumes`.`name` AS `name`, + `volumes`.`device_id` AS `device_id`, + `volumes`.`volume_type` AS `volume_type`, + `volumes`.`provisioning_type` AS `provisioning_type`, + `volumes`.`size` AS `size`, + `volumes`.`min_iops` AS `min_iops`, + `volumes`.`max_iops` AS `max_iops`, + `volumes`.`created` AS `created`, + `volumes`.`state` AS `state`, + `volumes`.`attached` AS `attached`, + `volumes`.`removed` AS `removed`, + `volumes`.`display_volume` AS `display_volume`, + `volumes`.`format` AS `format`, + `volumes`.`path` AS `path`, + `volumes`.`chain_info` AS `chain_info`, + `volumes`.`external_uuid` AS `external_uuid`, + `account`.`id` AS `account_id`, + `account`.`uuid` AS `account_uuid`, + `account`.`account_name` AS `account_name`, + `account`.`type` AS `account_type`, + `domain`.`id` AS `domain_id`, + `domain`.`uuid` AS `domain_uuid`, + `domain`.`name` AS `domain_name`, + `domain`.`path` AS `domain_path`, + `projects`.`id` AS `project_id`, + `projects`.`uuid` AS `project_uuid`, + `projects`.`name` AS `project_name`, + `data_center`.`id` AS `data_center_id`, + `data_center`.`uuid` AS `data_center_uuid`, + `data_center`.`name` AS `data_center_name`, + `data_center`.`networktype` AS `data_center_type`, + `vm_instance`.`id` AS `vm_id`, + `vm_instance`.`uuid` AS `vm_uuid`, + `vm_instance`.`name` AS `vm_name`, + `vm_instance`.`state` AS `vm_state`, + `vm_instance`.`vm_type` AS `vm_type`, + `user_vm`.`display_name` AS `vm_display_name`, + `volume_store_ref`.`size` AS `volume_store_size`, + `volume_store_ref`.`download_pct` AS `download_pct`, + `volume_store_ref`.`download_state` AS `download_state`, + `volume_store_ref`.`error_str` AS `error_str`, + `volume_store_ref`.`created` AS `created_on_store`, + `disk_offering`.`id` AS `disk_offering_id`, + `disk_offering`.`uuid` AS `disk_offering_uuid`, + `disk_offering`.`name` AS `disk_offering_name`, + `disk_offering`.`display_text` AS `disk_offering_display_text`, + `disk_offering`.`use_local_storage` AS `use_local_storage`, + `service_offering`.`system_use` AS `system_use`, + `disk_offering`.`bytes_read_rate` AS `bytes_read_rate`, + `disk_offering`.`bytes_write_rate` AS `bytes_write_rate`, + `disk_offering`.`iops_read_rate` AS `iops_read_rate`, + `disk_offering`.`iops_write_rate` AS `iops_write_rate`, + `disk_offering`.`cache_mode` AS `cache_mode`, + `storage_pool`.`id` AS `pool_id`, + `storage_pool`.`uuid` AS `pool_uuid`, + `storage_pool`.`name` AS `pool_name`, + `cluster`.`id` AS `cluster_id`, + `cluster`.`name` AS `cluster_name`, + `cluster`.`uuid` AS `cluster_uuid`, + `cluster`.`hypervisor_type` AS `hypervisor_type`, + `vm_template`.`id` AS `template_id`, + `vm_template`.`uuid` AS `template_uuid`, + `vm_template`.`extractable` AS `extractable`, + `vm_template`.`type` AS `template_type`, + `vm_template`.`name` AS `template_name`, + `vm_template`.`display_text` AS `template_display_text`, + `iso`.`id` AS `iso_id`, + `iso`.`uuid` AS `iso_uuid`, + `iso`.`name` AS `iso_name`, + `iso`.`display_text` AS `iso_display_text`, + `resource_tags`.`id` AS `tag_id`, + `resource_tags`.`uuid` AS `tag_uuid`, + `resource_tags`.`key` AS `tag_key`, + `resource_tags`.`value` AS `tag_value`, + `resource_tags`.`domain_id` AS `tag_domain_id`, + `resource_tags`.`account_id` AS `tag_account_id`, + `resource_tags`.`resource_id` AS `tag_resource_id`, + `resource_tags`.`resource_uuid` AS `tag_resource_uuid`, + `resource_tags`.`resource_type` AS `tag_resource_type`, + `resource_tags`.`customer` AS `tag_customer`, + `async_job`.`id` AS `job_id`, + `async_job`.`uuid` AS `job_uuid`, + `async_job`.`job_status` AS `job_status`, + `async_job`.`account_id` AS `job_account_id`, + `host_pod_ref`.`id` AS `pod_id`, + `host_pod_ref`.`uuid` AS `pod_uuid`, + `host_pod_ref`.`name` AS `pod_name`, + `resource_tag_account`.`account_name` AS `tag_account_name`, + `resource_tag_domain`.`uuid` AS `tag_domain_uuid`, + `resource_tag_domain`.`name` AS `tag_domain_name` +FROM + ((((((((((((((((((`volumes` +JOIN `account`ON + ((`volumes`.`account_id` = `account`.`id`))) +JOIN `domain`ON + ((`volumes`.`domain_id` = `domain`.`id`))) +LEFT JOIN `projects`ON + ((`projects`.`project_account_id` = `account`.`id`))) +LEFT JOIN `data_center`ON + ((`volumes`.`data_center_id` = `data_center`.`id`))) +LEFT JOIN `vm_instance`ON + ((`volumes`.`instance_id` = `vm_instance`.`id`))) +LEFT JOIN `user_vm`ON + ((`user_vm`.`id` = `vm_instance`.`id`))) +LEFT JOIN `volume_store_ref`ON + ((`volumes`.`id` = `volume_store_ref`.`volume_id`))) +LEFT JOIN `service_offering`ON + ((`vm_instance`.`service_offering_id` = `service_offering`.`id`))) +LEFT JOIN `disk_offering`ON + ((`volumes`.`disk_offering_id` = `disk_offering`.`id`))) +LEFT JOIN `storage_pool`ON + ((`volumes`.`pool_id` = `storage_pool`.`id`))) +LEFT JOIN `host_pod_ref`ON + ((`storage_pool`.`pod_id` = `host_pod_ref`.`id`))) +LEFT JOIN `cluster`ON + ((`storage_pool`.`cluster_id` = `cluster`.`id`))) +LEFT JOIN `vm_template`ON + ((`volumes`.`template_id` = `vm_template`.`id`))) +LEFT JOIN `vm_template` `iso`ON + ((`iso`.`id` = `volumes`.`iso_id`))) +LEFT JOIN `resource_tags`ON + (((`resource_tags`.`resource_id` = `volumes`.`id`) + and (`resource_tags`.`resource_type` = 'Volume')))) +LEFT JOIN `async_job`ON + (((`async_job`.`instance_id` = `volumes`.`id`) + and (`async_job`.`instance_type` = 'Volume') + and (`async_job`.`job_status` = 0)))) +LEFT JOIN `account` `resource_tag_account`ON + ((`resource_tag_account`.`id` = `resource_tags`.`account_id`))) +LEFT JOIN `domain` `resource_tag_domain`ON + ((`resource_tag_domain`.`id` = `resource_tags`.`domain_id`))); diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.vpc_offering_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.vpc_offering_view.sql new file mode 100644 index 00000000000..cb762a57883 --- /dev/null +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.vpc_offering_view.sql @@ -0,0 +1,63 @@ +-- 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. + +-- cloud.vpc_offering_view source + + +DROP VIEW IF EXISTS `cloud`.`vpc_offering_view`; + +CREATE VIEW `cloud`.`vpc_offering_view` AS +select + `vpc_offerings`.`id` AS `id`, + `vpc_offerings`.`uuid` AS `uuid`, + `vpc_offerings`.`name` AS `name`, + `vpc_offerings`.`unique_name` AS `unique_name`, + `vpc_offerings`.`display_text` AS `display_text`, + `vpc_offerings`.`state` AS `state`, + `vpc_offerings`.`default` AS `default`, + `vpc_offerings`.`created` AS `created`, + `vpc_offerings`.`removed` AS `removed`, + `vpc_offerings`.`service_offering_id` AS `service_offering_id`, + `vpc_offerings`.`supports_distributed_router` AS `supports_distributed_router`, + `vpc_offerings`.`supports_region_level_vpc` AS `supports_region_level_vpc`, + `vpc_offerings`.`redundant_router_service` AS `redundant_router_service`, + `vpc_offerings`.`sort_key` AS `sort_key`, + group_concat(distinct `domain`.`id` separator ',') AS `domain_id`, + group_concat(distinct `domain`.`uuid` separator ',') AS `domain_uuid`, + group_concat(distinct `domain`.`name` separator ',') AS `domain_name`, + group_concat(distinct `domain`.`path` separator ',') AS `domain_path`, + group_concat(distinct `zone`.`id` separator ',') AS `zone_id`, + group_concat(distinct `zone`.`uuid` separator ',') AS `zone_uuid`, + group_concat(distinct `zone`.`name` separator ',') AS `zone_name`, + `offering_details`.`value` AS `internet_protocol` +from + (((((`vpc_offerings` +left join `vpc_offering_details` `domain_details` on + (((`domain_details`.`offering_id` = `vpc_offerings`.`id`) + and (`domain_details`.`name` = 'domainid')))) +left join `domain` on + ((0 <> find_in_set(`domain`.`id`, `domain_details`.`value`)))) +left join `vpc_offering_details` `zone_details` on + (((`zone_details`.`offering_id` = `vpc_offerings`.`id`) + and (`zone_details`.`name` = 'zoneid')))) +left join `data_center` `zone` on + ((0 <> find_in_set(`zone`.`id`, `zone_details`.`value`)))) +left join `vpc_offering_details` `offering_details` on + (((`offering_details`.`offering_id` = `vpc_offerings`.`id`) + and (`offering_details`.`name` = 'internetprotocol')))) +group by + `vpc_offerings`.`id`; From e74a72b4ef88655e88e8821a9a59170b04413b4f Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Sat, 17 Feb 2024 09:32:37 +0100 Subject: [PATCH 3/9] test: fix test_guest_os.py failure on xcpng82 (#8659) on xenserver-71, supported Debian OSes are ``` name-label ( RW): Debian Squeeze 6.0 (32-bit) name-label ( RW): Debian Jessie 8.0 name-label ( RW): Debian Wheezy 7.0 (32-bit) name-label ( RW): Debian Squeeze 6.0 (64-bit) name-label ( RW): Debian Wheezy 7.0 (64-bit) ``` on xcpng82, supported Debian OSes are ``` name-label ( RW): Debian Jessie 8.0 name-label ( RW): Debian Buster 10 name-label ( RW): Debian Stretch 9.0 ``` --- test/integration/smoke/test_guest_os.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/smoke/test_guest_os.py b/test/integration/smoke/test_guest_os.py index 01fe34395e0..c9d50a7c523 100644 --- a/test/integration/smoke/test_guest_os.py +++ b/test/integration/smoke/test_guest_os.py @@ -181,7 +181,7 @@ class TestGuestOS(cloudstackTestCase): raise unittest.SkipTest("OS name check with hypervisor is supported only on XenServer and VMware") if self.hypervisor.hypervisor.lower() == "xenserver": - testosname="Debian Squeeze 6.0 (32-bit)" + testosname="Debian Jessie 8.0" else: testosname="debian4_64Guest" From 275abaff6bcc942dd35972e6bd7808166a397391 Mon Sep 17 00:00:00 2001 From: Henrique Sato Date: Mon, 19 Feb 2024 06:29:45 -0300 Subject: [PATCH 4/9] Refactor updateDiskOffering API (#8446) Co-authored-by: Henrique Sato --- .../ConfigurationManagerImpl.java | 208 +++++++++++------- .../ConfigurationManagerImplTest.java | 157 +++++++++++++ 2 files changed, 289 insertions(+), 76 deletions(-) diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index d84673efd6b..de5311be635 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -3919,22 +3919,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati List existingZoneIds = diskOfferingDetailsDao.findZoneIds(diskOfferingId); Collections.sort(existingZoneIds); - // check if valid domain - if (CollectionUtils.isNotEmpty(domainIds)) { - for (final Long domainId: domainIds) { - if (_domainDao.findById(domainId) == null) { - throw new InvalidParameterValueException("Please specify a valid domain id"); - } - } - } + validateDomain(domainIds); - // check if valid zone - if (CollectionUtils.isNotEmpty(zoneIds)) { - for (Long zoneId : zoneIds) { - if (_zoneDao.findById(zoneId) == null) - throw new InvalidParameterValueException("Please specify a valid zone id"); - } - } + validateZone(zoneIds); Long userId = CallContext.current().getCallingUserId(); if (userId == null) { @@ -3957,35 +3944,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati Collections.sort(filteredZoneIds); if (account.getType() == Account.Type.DOMAIN_ADMIN) { - if (!filteredZoneIds.equals(existingZoneIds)) { // Domain-admins cannot update zone(s) for offerings - throw new InvalidParameterValueException(String.format("Unable to update zone(s) for disk offering: %s by admin: %s as it is domain-admin", diskOfferingHandle.getUuid(), user.getUuid())); - } - if (existingDomainIds.isEmpty()) { - throw new InvalidParameterValueException(String.format("Unable to update public disk offering: %s by user: %s because it is domain-admin", diskOfferingHandle.getUuid(), user.getUuid())); - } else { - if (filteredDomainIds.isEmpty()) { - throw new InvalidParameterValueException(String.format("Unable to update disk offering: %s to a public offering by user: %s because it is domain-admin", diskOfferingHandle.getUuid(), user.getUuid())); - } - } + checkDomainAdminUpdateOfferingRestrictions(diskOfferingHandle, user, filteredZoneIds, existingZoneIds, existingDomainIds, filteredDomainIds); + if (StringUtils.isNotBlank(tags) && !ALLOW_DOMAIN_ADMINS_TO_CREATE_TAGGED_OFFERINGS.valueIn(account.getAccountId())) { throw new InvalidParameterValueException(String.format("User [%s] is unable to update disk offering tags.", user.getUuid())); } - List nonChildDomains = new ArrayList<>(); - for (Long domainId : existingDomainIds) { - if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) { - if (name != null || displayText != null || sortKey != null) { // Domain-admins cannot update name, display text, sort key for offerings with domain which are not child domains for domain-admin - throw new InvalidParameterValueException(String.format("Unable to update disk offering: %s as it has linked domain(s) which are not child domain for domain-admin: %s", diskOfferingHandle.getUuid(), user.getUuid())); - } - nonChildDomains.add(domainId); - } - } - for (Long domainId : filteredDomainIds) { - if (!_domainDao.isChildDomain(account.getDomainId(), domainId)) { - Domain domain = _entityMgr.findById(Domain.class, domainId); - throw new InvalidParameterValueException(String.format("Unable to update disk offering: %s by domain-admin: %s with domain: %3$s which is not a child domain", diskOfferingHandle.getUuid(), user.getUuid(), domain.getUuid())); - } - } + List nonChildDomains = getAccountNonChildDomains(diskOfferingHandle, account, user, cmd, existingDomainIds); + + checkIfDomainIsChildDomain(diskOfferingHandle, account, user, filteredDomainIds); + filteredDomainIds.addAll(nonChildDomains); // Final list must include domains which were not child domain for domain-admin but specified for this offering prior to update } else if (account.getType() != Account.Type.ADMIN) { throw new InvalidParameterValueException(String.format("Unable to update disk offering: %s by id user: %s because it is not root-admin or domain-admin", diskOfferingHandle.getUuid(), user.getUuid())); @@ -4001,22 +3969,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } final DiskOfferingVO diskOffering = _diskOfferingDao.createForUpdate(diskOfferingId); - - if (name != null) { - diskOffering.setName(name); - } - - if (displayText != null) { - diskOffering.setDisplayText(displayText); - } - - if (sortKey != null) { - diskOffering.setSortKey(sortKey); - } - - if (displayDiskOffering != null) { - diskOffering.setDisplayOffering(displayDiskOffering); - } + updateDiskOfferingIfCmdAttributeNotNull(diskOffering, cmd); updateOfferingTagsIfIsNotNull(tags, diskOffering); @@ -4039,26 +3992,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } List detailsVO = new ArrayList<>(); if(detailsUpdateNeeded) { - SearchBuilder sb = diskOfferingDetailsDao.createSearchBuilder(); - sb.and("offeringId", sb.entity().getResourceId(), SearchCriteria.Op.EQ); - sb.and("detailName", sb.entity().getName(), SearchCriteria.Op.EQ); - sb.done(); - SearchCriteria sc = sb.create(); - sc.setParameters("offeringId", String.valueOf(diskOfferingId)); - if(!filteredDomainIds.equals(existingDomainIds)) { - sc.setParameters("detailName", ApiConstants.DOMAIN_ID); - diskOfferingDetailsDao.remove(sc); - for (Long domainId : filteredDomainIds) { - detailsVO.add(new DiskOfferingDetailVO(diskOfferingId, ApiConstants.DOMAIN_ID, String.valueOf(domainId), false)); - } - } - if(!filteredZoneIds.equals(existingZoneIds)) { - sc.setParameters("detailName", ApiConstants.ZONE_ID); - diskOfferingDetailsDao.remove(sc); - for (Long zoneId : filteredZoneIds) { - detailsVO.add(new DiskOfferingDetailVO(diskOfferingId, ApiConstants.ZONE_ID, String.valueOf(zoneId), false)); - } - } + updateDiskOfferingDetails(detailsVO, diskOfferingId, filteredDomainIds, existingDomainIds, filteredZoneIds, existingZoneIds); } if (!detailsVO.isEmpty()) { for (DiskOfferingDetailVO detailVO : detailsVO) { @@ -4069,6 +4003,128 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return _diskOfferingDao.findById(diskOfferingId); } + protected void validateDomain(List domainIds) { + if (CollectionUtils.isEmpty(domainIds)) { + return; + } + + for (final Long domainId: domainIds) { + if (_domainDao.findById(domainId) == null) { + throw new InvalidParameterValueException("Please specify a valid domain id."); + } + } + } + + protected void validateZone(List zoneIds) { + if (CollectionUtils.isEmpty(zoneIds)) { + return; + } + + for (Long zoneId : zoneIds) { + if (_zoneDao.findById(zoneId) == null) { + throw new InvalidParameterValueException("Please specify a valid zone id."); + } + } + } + + protected void updateDiskOfferingIfCmdAttributeNotNull(DiskOfferingVO diskOffering, UpdateDiskOfferingCmd cmd) { + if (cmd.getDiskOfferingName() != null) { + diskOffering.setName(cmd.getDiskOfferingName()); + } + + if (cmd.getDisplayText() != null) { + diskOffering.setDisplayText(cmd.getDisplayText()); + } + + if (cmd.getSortKey() != null) { + diskOffering.setSortKey(cmd.getSortKey()); + } + + if (cmd.getDisplayOffering() != null) { + diskOffering.setDisplayOffering(cmd.getDisplayOffering()); + } + } + + protected void updateDiskOfferingDetails(List detailsVO, Long diskOfferingId, List filteredDomainIds, + List existingDomainIds, List filteredZoneIds, List existingZoneIds) { + SearchBuilder sb = diskOfferingDetailsDao.createSearchBuilder(); + sb.and("offeringId", sb.entity().getResourceId(), SearchCriteria.Op.EQ); + sb.and("detailName", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.done(); + SearchCriteria sc = sb.create(); + sc.setParameters("offeringId", String.valueOf(diskOfferingId)); + + updateDiskOfferingDetailsDomainIds(detailsVO, sc, diskOfferingId, filteredDomainIds, existingDomainIds); + updateDiskOfferingDetailsZoneIds(detailsVO, sc, diskOfferingId, filteredZoneIds, existingZoneIds); + } + + protected void updateDiskOfferingDetailsDomainIds(List detailsVO, SearchCriteria sc, Long diskOfferingId, List filteredDomainIds, List existingDomainIds) { + if (filteredDomainIds.equals(existingDomainIds)) { + return; + } + + sc.setParameters("detailName", ApiConstants.DOMAIN_ID); + diskOfferingDetailsDao.remove(sc); + for (Long domainId : filteredDomainIds) { + detailsVO.add(new DiskOfferingDetailVO(diskOfferingId, ApiConstants.DOMAIN_ID, String.valueOf(domainId), false)); + } + } + + protected void updateDiskOfferingDetailsZoneIds(List detailsVO, SearchCriteria sc, Long diskOfferingId, List filteredZoneIds, List existingZoneIds) { + if (filteredZoneIds.equals(existingZoneIds)) { + return; + } + + sc.setParameters("detailName", ApiConstants.ZONE_ID); + diskOfferingDetailsDao.remove(sc); + for (Long zoneId : filteredZoneIds) { + detailsVO.add(new DiskOfferingDetailVO(diskOfferingId, ApiConstants.ZONE_ID, String.valueOf(zoneId), false)); + } + } + + protected void checkDomainAdminUpdateOfferingRestrictions(DiskOffering diskOffering, User user, List filteredZoneIds, List existingZoneIds, + List existingDomainIds, List filteredDomainIds) { + if (!filteredZoneIds.equals(existingZoneIds)) { + throw new InvalidParameterValueException(String.format("Unable to update zone(s) for disk offering [%s] by admin [%s] as it is domain-admin.", diskOffering.getUuid(), user.getUuid())); + } + if (existingDomainIds.isEmpty()) { + throw new InvalidParameterValueException(String.format("Unable to update public disk offering [%s] by user [%s] because it is domain-admin.", diskOffering.getUuid(), user.getUuid())); + } + if (filteredDomainIds.isEmpty()) { + throw new InvalidParameterValueException(String.format("Unable to update disk offering [%s] to a public offering by user [%s] because it is domain-admin.", diskOffering.getUuid(), user.getUuid())); + } + } + + protected List getAccountNonChildDomains(DiskOffering diskOffering, Account account, User user, + UpdateDiskOfferingCmd cmd, List existingDomainIds) { + List nonChildDomains = new ArrayList<>(); + String name = cmd.getDiskOfferingName(); + String displayText = cmd.getDisplayText(); + Integer sortKey = cmd.getSortKey(); + for (Long domainId : existingDomainIds) { + if (_domainDao.isChildDomain(account.getDomainId(), domainId)) { + continue; + } + + if (ObjectUtils.anyNotNull(name, displayText, sortKey)) { + throw new InvalidParameterValueException(String.format("Unable to update disk offering [%s] as it has linked domain(s) which are not child domain for domain-admin [%s].", diskOffering.getUuid(), user.getUuid())); + } + nonChildDomains.add(domainId); + } + return nonChildDomains; + } + + protected void checkIfDomainIsChildDomain(DiskOffering diskOffering, Account account, User user, List filteredDomainIds) { + for (Long domainId : filteredDomainIds) { + if (_domainDao.isChildDomain(account.getDomainId(), domainId)) { + continue; + } + + Domain domain = _entityMgr.findById(Domain.class, domainId); + throw new InvalidParameterValueException(String.format("Unable to update disk offering [%s] by domain-admin [%s] with domain [%3$s] which is not a child domain.", diskOffering.getUuid(), user.getUuid(), domain.getUuid())); + } + } + /** * Check the tags parameters to the disk/service offering *
    diff --git a/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java index 38189313a52..958a39be410 100644 --- a/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java +++ b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java @@ -21,6 +21,18 @@ import com.cloud.storage.StorageManager; import com.cloud.utils.net.NetUtils; import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.domain.Domain; +import com.cloud.domain.dao.DomainDao; +import com.cloud.offering.DiskOffering; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.user.Account; +import com.cloud.user.User; +import com.cloud.utils.db.EntityManager; +import com.cloud.utils.db.SearchCriteria; +import org.apache.cloudstack.api.command.admin.offering.UpdateDiskOfferingCmd; +import org.apache.cloudstack.resourcedetail.DiskOfferingDetailVO; +import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -29,7 +41,10 @@ import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import java.util.ArrayList; import java.util.List; @@ -37,7 +52,40 @@ import java.util.List; public class ConfigurationManagerImplTest { @Mock ConfigDepot configDepot; + @InjectMocks ConfigurationManagerImpl configurationManagerImplSpy = Mockito.spy(new ConfigurationManagerImpl()); + @Mock + SearchCriteria searchCriteriaDiskOfferingDetailMock; + @Mock + DiskOffering diskOfferingMock; + @Mock + Account accountMock; + @Mock + User userMock; + @Mock + Domain domainMock; + @Mock + DataCenterDao zoneDaoMock; + @Mock + DomainDao domainDaoMock; + @Mock + EntityManager entityManagerMock; + @Mock + DiskOfferingDetailsDao diskOfferingDetailsDao; + @Spy + DiskOfferingVO diskOfferingVOSpy; + @Mock + UpdateDiskOfferingCmd updateDiskOfferingCmdMock; + + Long validId = 1L; + Long invalidId = 100L; + List filteredZoneIds = List.of(1L, 2L, 3L); + List existingZoneIds = List.of(1L, 2L, 3L); + List filteredDomainIds = List.of(1L, 2L, 3L); + List existingDomainIds = List.of(1L, 2L, 3L); + List emptyExistingZoneIds = new ArrayList<>(); + List emptyExistingDomainIds = new ArrayList<>(); + List emptyFilteredDomainIds = new ArrayList<>(); @Before public void setUp() throws Exception { @@ -50,6 +98,7 @@ public class ConfigurationManagerImplTest { Assert.assertNull(testVariable); } + @Test public void validateIfIntValueIsInRangeTestInvalidValueReturnString() { String testVariable = configurationManagerImplSpy.validateIfIntValueIsInRange("String name", "9", "1-5"); @@ -250,4 +299,112 @@ public class ConfigurationManagerImplTest { Mockito.doReturn(key).when(configurationManagerImplSpy._configDepot).get("config.iprange"); configurationManagerImplSpy.validateIpAddressRelatedConfigValues("config.iprange", "192.168.1.1-192.168.1.100"); } + + @Test + public void validateDomainTestInvalidIdThrowException() { + Mockito.doReturn(null).when(domainDaoMock).findById(invalidId); + Assert.assertThrows(InvalidParameterValueException.class, () -> configurationManagerImplSpy.validateDomain(List.of(invalidId))); + } + + @Test + public void validateZoneTestInvalidIdThrowException() { + Mockito.doReturn(null).when(zoneDaoMock).findById(invalidId); + Assert.assertThrows(InvalidParameterValueException.class, () -> configurationManagerImplSpy.validateZone(List.of(invalidId))); + } + + @Test + public void updateDiskOfferingIfCmdAttributeNotNullTestNotNullValueUpdateOfferingAttribute() { + Mockito.doReturn("DiskOfferingName").when(updateDiskOfferingCmdMock).getDiskOfferingName(); + Mockito.doReturn("DisplayText").when(updateDiskOfferingCmdMock).getDisplayText(); + Mockito.doReturn(1).when(updateDiskOfferingCmdMock).getSortKey(); + Mockito.doReturn(false).when(updateDiskOfferingCmdMock).getDisplayOffering(); + + configurationManagerImplSpy.updateDiskOfferingIfCmdAttributeNotNull(diskOfferingVOSpy, updateDiskOfferingCmdMock); + + Assert.assertEquals(updateDiskOfferingCmdMock.getDiskOfferingName(), diskOfferingVOSpy.getName()); + Assert.assertEquals(updateDiskOfferingCmdMock.getDisplayText(), diskOfferingVOSpy.getDisplayText()); + Assert.assertEquals(updateDiskOfferingCmdMock.getSortKey(), (Integer) diskOfferingVOSpy.getSortKey()); + Assert.assertEquals(updateDiskOfferingCmdMock.getDisplayOffering(), diskOfferingVOSpy.getDisplayOffering()); + } + + @Test + public void updateDiskOfferingIfCmdAttributeNotNullTestNullValueDoesntUpdateOfferingAttribute() { + Mockito.doReturn("Name").when(diskOfferingVOSpy).getName(); + Mockito.doReturn("DisplayText").when(diskOfferingVOSpy).getDisplayText(); + Mockito.doReturn(1).when(diskOfferingVOSpy).getSortKey(); + Mockito.doReturn(true).when(diskOfferingVOSpy).getDisplayOffering(); + + configurationManagerImplSpy.updateDiskOfferingIfCmdAttributeNotNull(diskOfferingVOSpy, updateDiskOfferingCmdMock); + + Assert.assertNotEquals(updateDiskOfferingCmdMock.getDiskOfferingName(), diskOfferingVOSpy.getName()); + Assert.assertNotEquals(updateDiskOfferingCmdMock.getDisplayText(), diskOfferingVOSpy.getDisplayText()); + Assert.assertNotEquals(updateDiskOfferingCmdMock.getSortKey(), (Integer) diskOfferingVOSpy.getSortKey()); + Assert.assertNotEquals(updateDiskOfferingCmdMock.getDisplayOffering(), diskOfferingVOSpy.getDisplayOffering()); + } + + @Test + public void updateDiskOfferingDetailsDomainIdsTestDifferentDomainIdsDiskOfferingDetailsAddDomainIds() { + List detailsVO = new ArrayList<>(); + Long diskOfferingId = validId; + + configurationManagerImplSpy.updateDiskOfferingDetailsDomainIds(detailsVO, searchCriteriaDiskOfferingDetailMock, diskOfferingId, filteredDomainIds, existingDomainIds); + + for (int i = 0; i < detailsVO.size(); i++) { + Assert.assertEquals(filteredDomainIds.get(i), (Long) Long.parseLong(detailsVO.get(i).getValue())); + } + } + + @Test + public void checkDomainAdminUpdateOfferingRestrictionsTestDifferentZoneIdsThrowException() { + Assert.assertThrows(InvalidParameterValueException.class, + () -> configurationManagerImplSpy.checkDomainAdminUpdateOfferingRestrictions(diskOfferingMock, userMock, filteredZoneIds, emptyExistingZoneIds, existingDomainIds, filteredDomainIds)); + } + + @Test + public void checkDomainAdminUpdateOfferingRestrictionsTestEmptyExistingDomainIdsThrowException() { + Assert.assertThrows(InvalidParameterValueException.class, + () -> configurationManagerImplSpy.checkDomainAdminUpdateOfferingRestrictions(diskOfferingMock, userMock, filteredZoneIds, existingZoneIds, emptyExistingDomainIds, filteredDomainIds)); + } + + @Test + public void checkDomainAdminUpdateOfferingRestrictionsTestEmptyFilteredDomainIdsThrowException() { + Assert.assertThrows(InvalidParameterValueException.class, + () -> configurationManagerImplSpy.checkDomainAdminUpdateOfferingRestrictions(diskOfferingMock, userMock, filteredZoneIds, existingZoneIds, existingDomainIds, emptyFilteredDomainIds)); + } + + @Test + public void getAccountNonChildDomainsTestValidValuesReturnChildDomains() { + Mockito.doReturn(null).when(updateDiskOfferingCmdMock).getSortKey(); + List nonChildDomains = configurationManagerImplSpy.getAccountNonChildDomains(diskOfferingMock, accountMock, userMock, updateDiskOfferingCmdMock, existingDomainIds); + + for (int i = 0; i < existingDomainIds.size(); i++) { + Assert.assertEquals(existingDomainIds.get(i), nonChildDomains.get(i)); + } + } + + @Test + public void getAccountNonChildDomainsTestAllDomainsAreChildDomainsReturnEmptyList() { + for (Long existingDomainId : existingDomainIds) { + Mockito.when(domainDaoMock.isChildDomain(accountMock.getDomainId(), existingDomainId)).thenReturn(true); + } + + List nonChildDomains = configurationManagerImplSpy.getAccountNonChildDomains(diskOfferingMock, accountMock, userMock, updateDiskOfferingCmdMock, existingDomainIds); + + Assert.assertTrue(nonChildDomains.isEmpty()); + } + + @Test + public void getAccountNonChildDomainsTestNotNullCmdAttributeThrowException() { + Mockito.doReturn("name").when(updateDiskOfferingCmdMock).getDiskOfferingName(); + + Assert.assertThrows(InvalidParameterValueException.class, () -> configurationManagerImplSpy.getAccountNonChildDomains(diskOfferingMock, accountMock, userMock, updateDiskOfferingCmdMock, existingDomainIds)); + } + + @Test + public void checkIfDomainIsChildDomainTestNonChildDomainThrowException() { + Mockito.doReturn(false).when(domainDaoMock).isChildDomain(Mockito.anyLong(), Mockito.anyLong()); + Mockito.doReturn(domainMock).when(entityManagerMock).findById(Domain.class, 1L); + + Assert.assertThrows(InvalidParameterValueException.class, () -> configurationManagerImplSpy.checkIfDomainIsChildDomain(diskOfferingMock, accountMock, userMock, filteredDomainIds)); + } } From af942e2260f8fa6b183b3da14a41fc355400cb47 Mon Sep 17 00:00:00 2001 From: Phsm Qwerty Date: Mon, 19 Feb 2024 11:07:48 +0100 Subject: [PATCH 5/9] vpc: optimize createMonitorServiceCommand() execution (#8385) * Optimize createMonitorServiceCommand() execution. Avoid an expensive getRouterHealthChecksConfig() execution multiple times during VPC restart. Fixes #8055 * Move getRouterHealthChecksConfig() outside of loop --- .../VirtualNetworkApplianceManagerImpl.java | 15 ++++++++------- .../VpcVirtualNetworkApplianceManagerImpl.java | 7 ++++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index a0e8a2a2f0d..de2d9d80d2b 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1619,7 +1619,7 @@ Configurable, StateListener services, - boolean reconfigure, boolean deleteFromProcessedCache) { + boolean reconfigure, boolean deleteFromProcessedCache, Map routerHealthCheckConfig) { final SetMonitorServiceCommand command = new SetMonitorServiceCommand(services); command.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId())); command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); @@ -1637,7 +1637,7 @@ Configurable, StateListener getRouterHealthChecksConfig(final DomainRouterVO router) { + protected Map getRouterHealthChecksConfig(final DomainRouterVO router) { Map data = new HashMap<>(); List routerJoinVOs = domainRouterJoinDao.searchByIds(router.getId()); StringBuilder vmsData = new StringBuilder(); @@ -2342,6 +2342,7 @@ Configurable, StateListener routerGuestNtwkIds = _routerDao.getRouterNetworks(router.getId()); + Map routerHealthChecksConfig = getRouterHealthChecksConfig(router); for (final Long guestNetworkId : routerGuestNtwkIds) { final AggregationControlCommand startCmd = new AggregationControlCommand(Action.Start, router.getInstanceName(), controlNic.getIPv4Address(), _routerControlHelper.getRouterIpInNetwork( guestNetworkId, router.getId())); @@ -2350,7 +2351,7 @@ Configurable, StateListener routerHealthCheckConfig) { final NetworkOffering offering = _networkOfferingDao.findById(_networkDao.findById(networkId).getNetworkOfferingId()); if (offering.isRedundantRouter()) { // service monitoring is currently not added in RVR @@ -2414,7 +2415,7 @@ Configurable, StateListener routerHealthCheckConfig = getRouterHealthChecksConfig(domainRouterVO); if (reprogramGuestNtwks && publicNics.size() > 0) { - finalizeMonitorService(cmds, profile, domainRouterVO, provider, publicNics.get(0).second().getId(), true); + finalizeMonitorService(cmds, profile, domainRouterVO, provider, publicNics.get(0).second().getId(), true, routerHealthCheckConfig); } for (final Pair nicNtwk : guestNics) { @@ -512,7 +513,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian if (reprogramGuestNtwks) { finalizeIpAssocForNetwork(cmds, domainRouterVO, provider, guestNetworkId, vlanMacAddress); finalizeNetworkRulesForNetwork(cmds, domainRouterVO, provider, guestNetworkId); - finalizeMonitorService(cmds, profile, domainRouterVO, provider, guestNetworkId, true); + finalizeMonitorService(cmds, profile, domainRouterVO, provider, guestNetworkId, true, routerHealthCheckConfig); } finalizeUserDataAndDhcpOnStart(cmds, domainRouterVO, provider, guestNetworkId); @@ -571,7 +572,7 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian finalizeNetworkRulesForNetwork(cmds, router, provider, networkId); } - finalizeMonitorService(cmds, getVirtualMachineProfile(router), router, provider, networkId, false); + finalizeMonitorService(cmds, getVirtualMachineProfile(router), router, provider, networkId, false, getRouterHealthChecksConfig(router)); return _nwHelper.sendCommandsToRouter(router, cmds); } From 1a1131154ef27e0f5491ceb249eded7fd810c021 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Mon, 19 Feb 2024 18:26:21 +0530 Subject: [PATCH 6/9] Fixup vm powerstate update (#8545) Co-authored-by: Suresh Kumar Anaparti --- .../cloud/vm/VirtualMachineManagerImpl.java | 7 +- .../com/cloud/vm/dao/VMInstanceDaoImpl.java | 23 ++- .../cloud/vm/dao/VMInstanceDaoImplTest.java | 152 ++++++++++++++++-- 3 files changed, 161 insertions(+), 21 deletions(-) diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 29c60698398..59d129bc065 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -213,8 +213,8 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.ScopeType; -import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateVO; @@ -2208,9 +2208,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac boolean result = stateTransitTo(vm, Event.OperationSucceeded, null); if (result) { + vm.setPowerState(PowerState.PowerOff); + _vmDao.update(vm.getId(), vm); if (VirtualMachine.Type.User.equals(vm.type) && ResourceCountRunningVMsonly.value()) { ServiceOfferingVO offering = _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()); - resourceCountDecrement(vm.getAccountId(),new Long(offering.getCpu()), new Long(offering.getRamSize())); + resourceCountDecrement(vm.getAccountId(), offering.getCpu().longValue(), offering.getRamSize().longValue()); } } else { throw new CloudRuntimeException("unable to stop " + vm); @@ -2761,6 +2763,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } vm.setLastHostId(srcHostId); + _vmDao.resetVmPowerStateTracking(vm.getId()); try { if (vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) { _networkMgr.rollbackNicForMigration(vmSrc, profile); diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index 916687baeb4..322895f0ec5 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -66,7 +66,7 @@ import com.cloud.vm.VirtualMachine.Type; public class VMInstanceDaoImpl extends GenericDaoBase implements VMInstanceDao { public static final Logger s_logger = Logger.getLogger(VMInstanceDaoImpl.class); - private static final int MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT = 3; + static final int MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT = 3; protected SearchBuilder VMClusterSearch; protected SearchBuilder LHVMClusterSearch; @@ -897,17 +897,19 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem @Override public boolean updatePowerState(final long instanceId, final long powerHostId, final VirtualMachine.PowerState powerState, Date wisdomEra) { - return Transaction.execute(new TransactionCallback() { + return Transaction.execute(new TransactionCallback<>() { @Override public Boolean doInTransaction(TransactionStatus status) { boolean needToUpdate = false; VMInstanceVO instance = findById(instanceId); if (instance != null - && (null == instance.getPowerStateUpdateTime() + && (null == instance.getPowerStateUpdateTime() || instance.getPowerStateUpdateTime().before(wisdomEra))) { Long savedPowerHostId = instance.getPowerHostId(); - if (instance.getPowerState() != powerState || savedPowerHostId == null - || savedPowerHostId.longValue() != powerHostId) { + if (instance.getPowerState() != powerState + || savedPowerHostId == null + || savedPowerHostId != powerHostId + || !isPowerStateInSyncWithInstanceState(powerState, powerHostId, instance)) { instance.setPowerState(powerState); instance.setPowerHostId(powerHostId); instance.setPowerStateUpdateCount(1); @@ -929,6 +931,17 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem }); } + private boolean isPowerStateInSyncWithInstanceState(final VirtualMachine.PowerState powerState, final long powerHostId, final VMInstanceVO instance) { + State instanceState = instance.getState(); + if ((powerState == VirtualMachine.PowerState.PowerOff && instanceState == State.Running) + || (powerState == VirtualMachine.PowerState.PowerOn && instanceState == State.Stopped)) { + s_logger.debug(String.format("VM id: %d on host id: %d and power host id: %d is in %s state, but power state is %s", + instance.getId(), instance.getHostId(), powerHostId, instanceState, powerState)); + return false; + } + return true; + } + @Override public boolean isPowerStateUpToDate(final long instanceId) { VMInstanceVO instance = findById(instanceId); diff --git a/engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDaoImplTest.java b/engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDaoImplTest.java index 767b41420b7..9dc773cd7d6 100644 --- a/engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDaoImplTest.java +++ b/engine/schema/src/test/java/com/cloud/vm/dao/VMInstanceDaoImplTest.java @@ -17,22 +17,32 @@ package com.cloud.vm.dao; -import com.cloud.utils.Pair; -import com.cloud.vm.VirtualMachine; +import static com.cloud.vm.VirtualMachine.State.Running; +import static com.cloud.vm.VirtualMachine.State.Stopped; +import static com.cloud.vm.dao.VMInstanceDaoImpl.MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Date; + import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; -import org.junit.Assert; import org.mockito.Mock; - -import static com.cloud.vm.VirtualMachine.State.Running; -import static com.cloud.vm.VirtualMachine.State.Stopped; - -import static org.mockito.Mockito.when; -import com.cloud.vm.VMInstanceVO; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import com.cloud.utils.Pair; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; + /** * Created by sudharma_jain on 3/2/17. */ @@ -55,16 +65,130 @@ public class VMInstanceDaoImplTest { } @Test - public void testUpdateState() throws Exception { + public void testUpdateState() { Long destHostId = null; - Pair opaqueMock = new Pair(new Long(1), destHostId); + Pair opaqueMock = new Pair<>(1L, destHostId); vmInstanceDao.updateState(Stopped, VirtualMachine.Event.FollowAgentPowerOffReport, Stopped, vm , opaqueMock); } @Test - public void testIfStateAndHostUnchanged() throws Exception { - Assert.assertEquals(vmInstanceDao.ifStateUnchanged(Stopped, Stopped, null, null), true); - Assert.assertEquals(vmInstanceDao.ifStateUnchanged(Stopped, Running, null, null), false); + public void testIfStateAndHostUnchanged() { + assertTrue(vmInstanceDao.ifStateUnchanged(Stopped, Stopped, null, null)); + assertFalse(vmInstanceDao.ifStateUnchanged(Stopped, Running, null, null)); } + @Test + public void testUpdatePowerStateDifferentPowerState() { + when(vm.getPowerStateUpdateTime()).thenReturn(null); + when(vm.getPowerHostId()).thenReturn(1L); + when(vm.getPowerState()).thenReturn(VirtualMachine.PowerState.PowerOn); + doReturn(vm).when(vmInstanceDao).findById(anyLong()); + doReturn(true).when(vmInstanceDao).update(anyLong(), any()); + + boolean result = vmInstanceDao.updatePowerState(1L, 1L, VirtualMachine.PowerState.PowerOff, new Date()); + + verify(vm, times(1)).setPowerState(VirtualMachine.PowerState.PowerOff); + verify(vm, times(1)).setPowerHostId(1L); + verify(vm, times(1)).setPowerStateUpdateCount(1); + verify(vm, times(1)).setPowerStateUpdateTime(any(Date.class)); + + assertTrue(result); + } + + @Test + public void testUpdatePowerStateVmNotFound() { + when(vm.getPowerStateUpdateTime()).thenReturn(null); + when(vm.getPowerHostId()).thenReturn(1L); + when(vm.getPowerState()).thenReturn(VirtualMachine.PowerState.PowerOn); + doReturn(null).when(vmInstanceDao).findById(anyLong()); + + boolean result = vmInstanceDao.updatePowerState(1L, 1L, VirtualMachine.PowerState.PowerOff, new Date()); + + verify(vm, never()).setPowerState(any()); + verify(vm, never()).setPowerHostId(anyLong()); + verify(vm, never()).setPowerStateUpdateCount(any(Integer.class)); + verify(vm, never()).setPowerStateUpdateTime(any(Date.class)); + + assertFalse(result); + } + + @Test + public void testUpdatePowerStateNoChangeFirstUpdate() { + when(vm.getPowerStateUpdateTime()).thenReturn(null); + when(vm.getPowerHostId()).thenReturn(1L); + when(vm.getPowerState()).thenReturn(VirtualMachine.PowerState.PowerOn); + when(vm.getState()).thenReturn(Running); + when(vm.getPowerStateUpdateCount()).thenReturn(1); + doReturn(vm).when(vmInstanceDao).findById(anyLong()); + doReturn(true).when(vmInstanceDao).update(anyLong(), any()); + + boolean result = vmInstanceDao.updatePowerState(1L, 1L, VirtualMachine.PowerState.PowerOn, new Date()); + + verify(vm, never()).setPowerState(any()); + verify(vm, never()).setPowerHostId(anyLong()); + verify(vm, times(1)).setPowerStateUpdateCount(2); + verify(vm, times(1)).setPowerStateUpdateTime(any(Date.class)); + + assertTrue(result); + } + + @Test + public void testUpdatePowerStateNoChangeMaxUpdatesValidState() { + when(vm.getPowerStateUpdateTime()).thenReturn(null); + when(vm.getPowerHostId()).thenReturn(1L); + when(vm.getPowerState()).thenReturn(VirtualMachine.PowerState.PowerOn); + when(vm.getPowerStateUpdateCount()).thenReturn(MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT); + when(vm.getState()).thenReturn(Running); + doReturn(vm).when(vmInstanceDao).findById(anyLong()); + doReturn(true).when(vmInstanceDao).update(anyLong(), any()); + + boolean result = vmInstanceDao.updatePowerState(1L, 1L, VirtualMachine.PowerState.PowerOn, new Date()); + + verify(vm, never()).setPowerState(any()); + verify(vm, never()).setPowerHostId(anyLong()); + verify(vm, never()).setPowerStateUpdateCount(any(Integer.class)); + verify(vm, never()).setPowerStateUpdateTime(any(Date.class)); + + assertFalse(result); + } + + @Test + public void testUpdatePowerStateNoChangeMaxUpdatesInvalidStateVmStopped() { + when(vm.getPowerStateUpdateTime()).thenReturn(null); + when(vm.getPowerHostId()).thenReturn(1L); + when(vm.getPowerState()).thenReturn(VirtualMachine.PowerState.PowerOn); + when(vm.getPowerStateUpdateCount()).thenReturn(MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT); + when(vm.getState()).thenReturn(Stopped); + doReturn(vm).when(vmInstanceDao).findById(anyLong()); + doReturn(true).when(vmInstanceDao).update(anyLong(), any()); + + boolean result = vmInstanceDao.updatePowerState(1L, 1L, VirtualMachine.PowerState.PowerOn, new Date()); + + verify(vm, times(1)).setPowerState(any()); + verify(vm, times(1)).setPowerHostId(anyLong()); + verify(vm, times(1)).setPowerStateUpdateCount(1); + verify(vm, times(1)).setPowerStateUpdateTime(any(Date.class)); + + assertTrue(result); + } + + @Test + public void testUpdatePowerStateNoChangeMaxUpdatesInvalidStateVmRunning() { + when(vm.getPowerStateUpdateTime()).thenReturn(null); + when(vm.getPowerHostId()).thenReturn(1L); + when(vm.getPowerState()).thenReturn(VirtualMachine.PowerState.PowerOff); + when(vm.getPowerStateUpdateCount()).thenReturn(MAX_CONSECUTIVE_SAME_STATE_UPDATE_COUNT); + when(vm.getState()).thenReturn(Running); + doReturn(vm).when(vmInstanceDao).findById(anyLong()); + doReturn(true).when(vmInstanceDao).update(anyLong(), any()); + + boolean result = vmInstanceDao.updatePowerState(1L, 1L, VirtualMachine.PowerState.PowerOff, new Date()); + + verify(vm, times(1)).setPowerState(any()); + verify(vm, times(1)).setPowerHostId(anyLong()); + verify(vm, times(1)).setPowerStateUpdateCount(1); + verify(vm, times(1)).setPowerStateUpdateTime(any(Date.class)); + + assertTrue(result); + } } From e09fd2e26b9910f95a87cc739aaee7ed54bd66bd Mon Sep 17 00:00:00 2001 From: Vishesh Date: Wed, 21 Feb 2024 13:54:11 +0530 Subject: [PATCH 7/9] Fixup: Optimize getRouterHealthChecksConfig method (#8677) --- .../network/router/VirtualNetworkApplianceManagerImpl.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index de2d9d80d2b..d208021e833 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1791,16 +1791,14 @@ Configurable, StateListener sbvm = userVmJoinDao.createSearchBuilder(); sbvm.and("networkId", sbvm.entity().getNetworkId(), SearchCriteria.Op.EQ); + sbvm.and("state", sbvm.entity().getState(), SearchCriteria.Op.EQ); SearchCriteria scvm = sbvm.create(); scvm.setParameters("networkId", routerJoinVO.getNetworkId()); + scvm.setParameters("state", VirtualMachine.State.Running); List vms = userVmJoinDao.search(scvm, null); boolean isDhcpSupported = _ntwkSrvcDao.areServicesSupportedInNetwork(routerJoinVO.getNetworkId(), Service.Dhcp); boolean isDnsSupported = _ntwkSrvcDao.areServicesSupportedInNetwork(routerJoinVO.getNetworkId(), Service.Dns); for (UserVmJoinVO vm : vms) { - if (vm.getState() != VirtualMachine.State.Running) { - continue; - } - vmsData.append("vmName=").append(vm.getName()) .append(",macAddress=").append(vm.getMacAddress()) .append(",ip=").append(vm.getIpAddress()) From ed579bfeca523c919064a6c9b113784e865bc209 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 23 Feb 2024 09:00:52 +0100 Subject: [PATCH 8/9] UI: remove duplicated section for backup (#8678) --- ui/src/config/section/storage.js | 54 -------------------------------- 1 file changed, 54 deletions(-) diff --git a/ui/src/config/section/storage.js b/ui/src/config/section/storage.js index 3493232da45..ff0fd99242d 100644 --- a/ui/src/config/section/storage.js +++ b/ui/src/config/section/storage.js @@ -459,60 +459,6 @@ export default { } ] }, - { - name: 'backup', - title: 'label.backup', - icon: 'cloud-upload-outlined', - permission: ['listBackups'], - columns: [{ name: (record) => { return record.virtualmachinename } }, 'virtualmachinename', 'status', 'type', 'created', 'account', 'zone'], - details: ['virtualmachinename', 'id', 'type', 'externalid', 'size', 'virtualsize', 'volumes', 'backupofferingname', 'zone', 'account', 'domain', 'created'], - actions: [ - { - api: 'restoreBackup', - icon: 'sync-outlined', - docHelp: 'adminguide/virtual_machines.html#restoring-vm-backups', - label: 'label.backup.restore', - message: 'message.backup.restore', - dataView: true, - show: (record) => { return record.state !== 'Destroyed' } - }, - { - api: 'restoreVolumeFromBackupAndAttachToVM', - icon: 'paper-clip-outlined', - label: 'label.backup.attach.restore', - message: 'message.backup.attach.restore', - dataView: true, - show: (record) => { return record.state !== 'Destroyed' }, - popup: true, - component: shallowRef(defineAsyncComponent(() => import('@/views/storage/RestoreAttachBackupVolume.vue'))) - }, - { - api: 'removeVirtualMachineFromBackupOffering', - icon: 'scissor-outlined', - label: 'label.backup.offering.remove', - message: 'message.backup.offering.remove', - dataView: true, - show: (record) => { return record.state !== 'Destroyed' }, - args: ['forced', 'virtualmachineid'], - mapping: { - forced: { - value: (record) => { return true } - }, - virtualmachineid: { - value: (record) => { return record.virtualmachineid } - } - } - }, - { - api: 'deleteBackup', - icon: 'delete-outlined', - label: 'label.delete.backup', - message: 'message.delete.backup', - dataView: true, - show: (record) => { return record.state !== 'Destroyed' } - } - ] - }, { name: 'buckets', title: 'label.buckets', From 3aafb286b9dbae67c679149c54749bb18c7b343b Mon Sep 17 00:00:00 2001 From: Oleg Chuev <91337563+OlegChuev@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:30:14 +0200 Subject: [PATCH 9/9] Fixed deleteVlanIpRange API description (#8700) Updates deleteVlanIpRange API description --- .../cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java index 15f0bde37a1..390759c2c06 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java @@ -29,7 +29,7 @@ import org.apache.cloudstack.api.response.VlanIpRangeResponse; import com.cloud.user.Account; -@APICommand(name = "deleteVlanIpRange", description = "Creates a VLAN IP range.", responseObject = SuccessResponse.class, +@APICommand(name = "deleteVlanIpRange", description = "Deletes a VLAN IP range.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVlanIpRangeCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteVlanIpRangeCmd.class.getName());