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 7f583fe225a..7ab0b053004 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 @@ -28,7 +28,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 { 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 b5fc2e7c3a9..f3ec3dd4761 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -212,8 +212,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; @@ -2206,6 +2206,8 @@ 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()); VMTemplateVO template = _templateDao.findByIdIncludingRemoved(vm.getTemplateId()); @@ -2760,6 +2762,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 cc82813b412..b7b787b0045 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 @@ -64,7 +64,7 @@ import com.cloud.vm.VirtualMachine.Type; @Component public class VMInstanceDaoImpl extends GenericDaoBase implements VMInstanceDao { - 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; @@ -895,17 +895,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); @@ -927,6 +929,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)) { + 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/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_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.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`; 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 00eae3b78d4..4a32dc08359 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,23 +17,33 @@ 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.After; 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. */ @@ -63,16 +73,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); + } } 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 diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index d5e0d013d30..6ae92f892cf 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -3917,22 +3917,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) { @@ -3955,35 +3942,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())); @@ -3999,22 +3967,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); @@ -4037,26 +3990,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) { @@ -4067,6 +4001,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/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 8467e6a3d4c..a5c5c8a3e08 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1585,7 +1585,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()); @@ -1603,7 +1603,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(); @@ -1757,16 +1757,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()) @@ -2308,6 +2306,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())); @@ -2316,7 +2315,7 @@ Configurable, StateListener routerHealthCheckConfig) { final NetworkOffering offering = _networkOfferingDao.findById(_networkDao.findById(networkId).getNetworkOfferingId()); if (offering.isRedundantRouter()) { // service monitoring is currently not added in RVR @@ -2380,7 +2379,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) { @@ -508,7 +509,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); @@ -567,7 +568,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); } 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)); + } } 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" 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',