mirror of
https://github.com/apache/cloudstack
synced 2026-08-02 05:26:35 +00:00
Some checks failed
Build / build (push) Has been cancelled
Simulator CI / build (push) Has been cancelled
CodeQL Analysis / CodeQL (actions) (push) Has been cancelled
Docker Image Build / build (push) Has been cancelled
Sonar Quality Check (Main) / Sonar JaCoCo Coverage (push) Has been cancelled
License Check / build (push) Has been cancelled
UI Build / build (push) Has been cancelled
Simulator CI / test (component/find_hosts_for_migration component/test_acl_isolatednetwork component/test_acl_isolatednetwork_delete component/test_acl_listsnapshot) (push) Has been cancelled
Simulator CI / test (component/test_acl_listvm component/test_acl_listvolume) (push) Has been cancelled
Simulator CI / test (component/test_acl_sharednetwork component/test_acl_sharednetwork_deployVM-impersonation component/test_user_private_gateway component/test_user_shared_network) (push) Has been cancelled
Simulator CI / test (component/test_affinity_groups_projects component/test_allocation_states component/test_assign_vm) (push) Has been cancelled
Simulator CI / test (component/test_concurrent_snapshots_limit component/test_cpu_domain_limits component/test_cpu_limits component/test_cpu_max_limits component/test_cpu_project_limits component/test_deploy_vm_userdata_multi_nic component/test_deploy_vm_lease) (push) Has been cancelled
Simulator CI / test (component/test_egress_fw_rules component/test_invalid_gw_nm component/test_ip_reservation) (push) Has been cancelled
Simulator CI / test (component/test_lb_secondary_ip component/test_list_nics component/test_list_pod component/test_memory_limits) (push) Has been cancelled
Simulator CI / test (component/test_mm_domain_limits component/test_mm_max_limits component/test_mm_project_limits component/test_network_offering component/test_non_contiguous_vlan) (push) Has been cancelled
Simulator CI / test (component/test_persistent_networks component/test_project_configs component/test_project_limits component/test_project_resources) (push) Has been cancelled
Simulator CI / test (component/test_project_usage component/test_protocol_number_security_group component/test_public_ip component/test_resource_limits component/test_resource_limit_tags) (push) Has been cancelled
Simulator CI / test (component/test_regions_accounts component/test_routers component/test_snapshots component/test_stopped_vm component/test_tags component/test_templates component/test_updateResourceCount component/test_update_vm) (push) Has been cancelled
Simulator CI / test (component/test_volumes component/test_vpc component/test_vpc_distributed_routing_offering component/test_vpc_network component/test_vpc_offerings component/test_vpc_routers component/test_vpn_users component/test_vpc_network_lbrules) (push) Has been cancelled
Simulator CI / test (smoke/test_accounts smoke/test_account_access smoke/test_affinity_groups smoke/test_affinity_groups_projects smoke/test_annotations smoke/test_async_job smoke/test_attach_multiple_volumes smoke/test_backup_recovery_dummy smoke/test_certauthority_… (push) Has been cancelled
Simulator CI / test (smoke/test_cluster_drs smoke/test_dynamicroles smoke/test_enable_account_settings_for_domain smoke/test_enable_role_based_users_in_projects smoke/test_events_resource smoke/test_global_settings smoke/test_guest_vlan_range smoke/test_host_maintena… (push) Has been cancelled
Simulator CI / test (smoke/test_list_accounts smoke/test_list_disk_offerings smoke/test_list_domains smoke/test_list_hosts smoke/test_list_service_offerings smoke/test_list_storage_pools smoke/test_list_volumes) (push) Has been cancelled
Simulator CI / test (smoke/test_network smoke/test_network_acl smoke/test_network_ipv6 smoke/test_network_permissions smoke/test_nic smoke/test_nic_adapter_type smoke/test_non_contigiousvlan smoke/test_object_stores smoke/test_outofbandmanagement smoke/test_outofband… (push) Has been cancelled
Simulator CI / test (smoke/test_router_dhcphosts smoke/test_router_dns smoke/test_router_dnsservice smoke/test_routers smoke/test_routers_iptables_default_policy smoke/test_routers_network_ops smoke/test_scale_vm smoke/test_secondary_storage smoke/test_service_offeri… (push) Has been cancelled
* refactor vmschedule to make it more generic and add new commands for it * fixup * update marvin tests to use the new APIs * Update UI to use new APIs * minor fixups * Add support scheduling min & max for autoscaling groups * Add marvin test for ASG * fixup * fixup * fixup * Fixup
638 lines
22 KiB
Python
638 lines
22 KiB
Python
# 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.
|
|
""" P1 tests for VM Schedule
|
|
"""
|
|
from marvin.cloudstackTestCase import cloudstackTestCase
|
|
from marvin.lib.base import Account, ServiceOffering, VirtualMachine, ResourceSchedule
|
|
from marvin.lib.common import get_domain, get_zone, get_template
|
|
from marvin.lib.utils import cleanup_resources
|
|
|
|
# Import Local Modules
|
|
from nose.plugins.attrib import attr
|
|
|
|
import datetime
|
|
import time
|
|
|
|
|
|
RESOURCE_TYPE = "VirtualMachine"
|
|
|
|
class Services:
|
|
"""Test Snapshots Services"""
|
|
|
|
def __init__(self):
|
|
self.services = {
|
|
"account": {
|
|
"email": "test@test.com",
|
|
"firstname": "Test",
|
|
"lastname": "User",
|
|
"username": "test",
|
|
# Random characters are appended for unique
|
|
# username
|
|
"password": "password",
|
|
},
|
|
"service_offering": {
|
|
"name": "Tiny Instance",
|
|
"displaytext": "Tiny Instance",
|
|
"cpunumber": 1,
|
|
"cpuspeed": 200, # in MHz
|
|
"memory": 256, # In MBs
|
|
},
|
|
"disk_offering": {
|
|
"displaytext": "Small Disk",
|
|
"name": "Small Disk",
|
|
"disksize": 1,
|
|
},
|
|
"server": {
|
|
"displayname": "TestVM",
|
|
"username": "root",
|
|
"password": "password",
|
|
"ssh_port": 22,
|
|
"privateport": 22,
|
|
"publicport": 22,
|
|
"protocol": "TCP",
|
|
},
|
|
"mgmt_server": {
|
|
"ipaddress": "192.168.100.21",
|
|
"username": "root",
|
|
"password": "password",
|
|
"port": 22,
|
|
},
|
|
"templates": {
|
|
"displaytext": "Template",
|
|
"name": "Template",
|
|
"ostype": "CentOS 5.3 (64-bit)",
|
|
"templatefilter": "self",
|
|
},
|
|
"ostype": "CentOS 5.3 (64-bit)",
|
|
}
|
|
|
|
|
|
class TestVMSchedule(cloudstackTestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.testClient = super(TestVMSchedule, cls).getClsTestClient()
|
|
cls.api_client = cls.testClient.getApiClient()
|
|
|
|
cls._cleanup = []
|
|
|
|
cls.hypervisor = cls.testClient.getHypervisorInfo()
|
|
|
|
cls.services = Services().services
|
|
# Get Zone, Domain and templates
|
|
cls.domain = get_domain(cls.api_client)
|
|
cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
|
|
cls.services["mode"] = cls.zone.networktype
|
|
template = get_template(cls.api_client, cls.zone.id, cls.services["ostype"])
|
|
|
|
cls.services["domainid"] = cls.domain.id
|
|
cls.services["server"]["zoneid"] = cls.zone.id
|
|
|
|
cls.services["templates"]["ostypeid"] = template.ostypeid
|
|
cls.services["zoneid"] = cls.zone.id
|
|
|
|
# Create VMs, NAT Rules etc
|
|
cls.account = Account.create(
|
|
cls.api_client, cls.services["account"], domainid=cls.domain.id
|
|
)
|
|
cls._cleanup.append(cls.account)
|
|
|
|
cls.services["account"] = cls.account.name
|
|
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client, cls.services["service_offering"]
|
|
)
|
|
cls._cleanup.append(cls.service_offering)
|
|
cls.virtual_machine = VirtualMachine.create(
|
|
cls.api_client,
|
|
cls.services["server"],
|
|
templateid=template.id,
|
|
accountid=cls.account.name,
|
|
domainid=cls.account.domainid,
|
|
serviceofferingid=cls.service_offering.id,
|
|
)
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
super(TestVMSchedule, cls).tearDownClass()
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.dbclient = self.testClient.getDbConnection()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
super(TestVMSchedule, self).tearDown()
|
|
|
|
@attr(tags=["advanced", "basic"], required_hardware="false")
|
|
def test_01_vmschedule_create(self):
|
|
"""Test VM Schedule Creation in cron format and validate responses"""
|
|
|
|
# Validate the following
|
|
# 1. Create VM Schedule in cron format
|
|
# 2. List VM Schedule and verify the response
|
|
# 3. Delete VM Schedule and verify the response
|
|
|
|
# Create VM Schedule
|
|
schedule = "0 0 1 * *"
|
|
vmschedule = ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"start",
|
|
schedule,
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
enabled=True,
|
|
)
|
|
|
|
self.cleanup.append(vmschedule)
|
|
|
|
self.debug("Created VM Schedule with ID: %s" % vmschedule.id)
|
|
|
|
# List VM Schedule
|
|
vmschedules = ResourceSchedule.list(
|
|
self.apiclient, RESOURCE_TYPE, self.virtual_machine.id, id=vmschedule.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(vmschedules, list),
|
|
True,
|
|
"Check list response returns a valid list",
|
|
)
|
|
|
|
self.assertNotEqual(len(vmschedules), 0, "Check VM Schedule list")
|
|
|
|
self.debug("List VM Schedule response: %s" % vmschedules[0].__dict__)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].id,
|
|
vmschedule.id,
|
|
"Check VM Schedule ID in list resources call",
|
|
)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].resourceid,
|
|
self.virtual_machine.id,
|
|
"Check resource ID in list resources call",
|
|
)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].resourcetype,
|
|
RESOURCE_TYPE,
|
|
"Check resource type in list resources call",
|
|
)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].schedule,
|
|
schedule,
|
|
"Check VM Schedule in list resources call",
|
|
)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].timezone,
|
|
str(datetime.datetime.now().astimezone().tzinfo),
|
|
"Check VM Schedule timezone in list resources call",
|
|
)
|
|
|
|
# Check for entry in resource_scheduled_job in db
|
|
vmscheduled_job = self.dbclient.execute(
|
|
"select * from resource_scheduled_job where schedule_id IN (SELECT id FROM resource_schedule WHERE uuid = '%s')"
|
|
% vmschedule.id,
|
|
db="cloud",
|
|
)
|
|
|
|
self.assertIsInstance(
|
|
vmscheduled_job,
|
|
list,
|
|
"Check if VM Schedule exists in resource_scheduled_job table",
|
|
)
|
|
|
|
self.assertGreater(
|
|
len(vmscheduled_job),
|
|
0,
|
|
"Check if VM Schedule exists in resource_scheduled_job table",
|
|
)
|
|
return
|
|
|
|
@attr(tags=["advanced", "basic"], required_hardware="false")
|
|
def test_02_vmschedule_create_parameter_exceptions(self):
|
|
"""Test VM Schedule Creation exceptions with invalid parameters"""
|
|
|
|
# Validate the following
|
|
# 1. Create VM Schedule with invalid virtual machine ID
|
|
# 2. Create VM Schedule with invalid schedule
|
|
# 3. Create VM Schedule with invalid start date
|
|
# 5. Create VM Schedule with invalid action
|
|
# 6. Create VM Schedule with invalid end date
|
|
|
|
# Create VM Schedule with invalid virtual machine ID
|
|
with self.assertRaises(Exception):
|
|
ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
"invalid",
|
|
"start",
|
|
"0 0 1 * *",
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
)
|
|
|
|
# Create VM Schedule with invalid schedule
|
|
with self.assertRaises(Exception):
|
|
ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"start",
|
|
"invalid",
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
)
|
|
|
|
# Create VM Schedule with invalid start date
|
|
with self.assertRaises(Exception):
|
|
ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"start",
|
|
"0 0 1 * *",
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
"invalid",
|
|
)
|
|
|
|
# Create VM Schedule with invalid action
|
|
with self.assertRaises(Exception):
|
|
ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"invalid",
|
|
"0 0 1 * *",
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
)
|
|
|
|
# test invalid end date
|
|
with self.assertRaises(Exception):
|
|
ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"start",
|
|
"0 0 1 * *",
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
enddate="invalid",
|
|
)
|
|
return
|
|
|
|
@attr(tags=["advanced", "basic"], required_hardware="false")
|
|
def test_03_vmschedule_update(self):
|
|
"""Test VM Schedule Update in cron format and validate responses"""
|
|
|
|
# Validate the following
|
|
# 1. Create VM Schedule in cron format
|
|
# 2. Update VM Schedule and verify the response
|
|
|
|
# Create VM Schedule
|
|
schedule = "0 0 1 * *"
|
|
vmschedule = ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"start",
|
|
schedule,
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
)
|
|
|
|
self.cleanup.append(vmschedule)
|
|
|
|
self.debug("Created VM Schedule with ID: %s" % vmschedule.id)
|
|
|
|
# Update VM Schedule
|
|
new_schedule = "0 0 2 * *"
|
|
vmschedule.update(
|
|
self.apiclient,
|
|
id=vmschedule.id,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
description="TestVM",
|
|
schedule=new_schedule,
|
|
timezone=datetime.datetime.now().astimezone().tzinfo,
|
|
startdate=(
|
|
datetime.datetime.now() + datetime.timedelta(minutes=10)
|
|
).strftime("%Y-%m-%d %H:%M:%S"),
|
|
enddate=(datetime.datetime.now() + datetime.timedelta(hours=10)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
)
|
|
|
|
self.debug("Updated VM Schedule with ID: %s" % vmschedule.id)
|
|
|
|
# List VM Schedule
|
|
vmschedules = ResourceSchedule.list(
|
|
self.apiclient, RESOURCE_TYPE, self.virtual_machine.id, id=vmschedule.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(vmschedules, list),
|
|
True,
|
|
"Check list response returns a valid list",
|
|
)
|
|
|
|
self.assertNotEqual(len(vmschedules), 0, "Check VM Schedule list")
|
|
|
|
self.debug("List VM Schedule response: %s" % vmschedules[0].__dict__)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].id,
|
|
vmschedule.id,
|
|
"Check VM Schedule ID in list resources call",
|
|
)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].resourceid,
|
|
self.virtual_machine.id,
|
|
"Check VM ID in list resources call",
|
|
)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].resourcetype,
|
|
RESOURCE_TYPE,
|
|
"Check VM ID in list resources call",
|
|
)
|
|
|
|
self.assertEqual(
|
|
vmschedules[0].schedule,
|
|
new_schedule,
|
|
"Check VM Schedule in list resources call",
|
|
)
|
|
return
|
|
|
|
@attr(tags=["advanced", "basic"], required_hardware="false")
|
|
def test_04_vmschedule_update_parameter_exceptions(self):
|
|
"""Test VM Schedule Update exceptions with invalid parameters"""
|
|
|
|
# Validate the following
|
|
# 1. Update VM Schedule with invalid schedule
|
|
# 2. Update VM Schedule with invalid start date
|
|
# 3. Update VM Schedule with invalid ID
|
|
# 4. Update VM Schedule with invalid end date
|
|
|
|
# Create VM Schedule
|
|
schedule = "0 0 1 * *"
|
|
vmschedule = ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"start",
|
|
schedule,
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(minutes=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
)
|
|
|
|
self.cleanup.append(vmschedule)
|
|
|
|
self.debug("Created VM Schedule with ID: %s" % vmschedule.id)
|
|
|
|
# Update VM Schedule with invalid schedule
|
|
with self.assertRaises(Exception):
|
|
vmschedule.update(
|
|
self.apiclient,
|
|
id=vmschedule.id,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
description="TestVM",
|
|
schedule="invalid",
|
|
timezone=datetime.datetime.now().astimezone().tzinfo,
|
|
startdate=(
|
|
datetime.datetime.now() + datetime.timedelta(minutes=5)
|
|
).strftime("%Y-%m-%d %H:%M:%S"),
|
|
)
|
|
|
|
# Update VM Schedule with invalid start date
|
|
with self.assertRaises(Exception):
|
|
vmschedule.update(
|
|
self.apiclient,
|
|
id=vmschedule.id,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
description="TestVM",
|
|
schedule=schedule,
|
|
timezone=datetime.datetime.now().astimezone().tzinfo,
|
|
startdate=(
|
|
datetime.datetime.now() - datetime.timedelta(days=1)
|
|
).strftime("%Y-%m-%d %H:%M:%S"),
|
|
)
|
|
|
|
# Update VM Schedule with invalid ID
|
|
with self.assertRaises(Exception):
|
|
vmschedule.update(
|
|
self.apiclient,
|
|
id="invalid",
|
|
virtualmachineid=self.virtual_machine.id,
|
|
description="TestVM",
|
|
schedule=schedule,
|
|
timezone=datetime.datetime.now().astimezone().tzinfo,
|
|
startdate=(
|
|
datetime.datetime.now() + datetime.timedelta(minutes=5)
|
|
).strftime("%Y-%m-%d %H:%M:%S"),
|
|
)
|
|
|
|
# Update VM Schedule with invalid end date
|
|
with self.assertRaises(Exception):
|
|
vmschedule.update(
|
|
self.apiclient,
|
|
id=vmschedule.id,
|
|
virtualmachineid=self.virtual_machine.id,
|
|
description="TestVM",
|
|
schedule=schedule,
|
|
timezone=datetime.datetime.now().astimezone().tzinfo,
|
|
startdate=(
|
|
datetime.datetime.now() + datetime.timedelta(minutes=5)
|
|
).strftime("%Y-%m-%d %H:%M:%S"),
|
|
enddate=(
|
|
datetime.datetime.now() - datetime.timedelta(minutes=5)
|
|
).strftime("%Y-%m-%d %H:%M:%S"),
|
|
)
|
|
|
|
return
|
|
|
|
@attr(tags=["advanced", "basic"], required_hardware="false")
|
|
def test_05_vmschedule_test_e2e(self):
|
|
# Validate the following
|
|
# 1. Create 2 VM Schedules - start and stop
|
|
# 2. Verify VM Schedule is created
|
|
# 3. Verify VM is stopped after schedule time
|
|
# 4. Verify VM is started after schedule time
|
|
# 5. Delete VM Schedule
|
|
# 6. Verify VM Schedule is deleted
|
|
# 7. Verify VM is not stopped after schedule time
|
|
# 8. Verify VM is not started after schedule time
|
|
|
|
# Create VM Schedule - start
|
|
start_schedule = "*/2 * * * *"
|
|
start_vmschedule = ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"start",
|
|
start_schedule,
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(seconds=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
enabled=True,
|
|
)
|
|
|
|
self.debug("Created VM Schedule with ID: %s" % start_vmschedule.id)
|
|
|
|
# Create VM Schedule - stop
|
|
stop_schedule = "*/1 * * * *"
|
|
stop_vmschedule = ResourceSchedule.create(
|
|
self.apiclient,
|
|
RESOURCE_TYPE,
|
|
self.virtual_machine.id,
|
|
"stop",
|
|
stop_schedule,
|
|
datetime.datetime.now().astimezone().tzinfo,
|
|
# Current date minutes in format "2014-01-01 00:00:00"
|
|
(datetime.datetime.now() + datetime.timedelta(seconds=5)).strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
),
|
|
enabled=True,
|
|
)
|
|
|
|
self.debug("Created VM Schedule with ID: %s" % stop_vmschedule.id)
|
|
|
|
# Verify VM Schedule is created
|
|
vmschedules = ResourceSchedule.list(
|
|
self.apiclient, RESOURCE_TYPE, self.virtual_machine.id, id=start_vmschedule.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(vmschedules, list),
|
|
True,
|
|
"Check list response returns a valid list",
|
|
)
|
|
self.assertNotEqual(len(vmschedules), 0, "Check VM Schedule is created")
|
|
|
|
# poll every 10 seconds (max waiting time is 6 minutes) and check VM's state for changes
|
|
previous_state = self.virtual_machine.state
|
|
self.debug("VM state: %s" % self.virtual_machine.state)
|
|
is_stop_schedule_working = False
|
|
is_start_schedule_working = False
|
|
for i in range(0, 36):
|
|
time.sleep(10)
|
|
current_state = self.virtual_machine.update(self.apiclient).state
|
|
self.debug("Polling VM state: %s" % current_state)
|
|
if previous_state in ("Running", "Starting") and current_state in (
|
|
"Stopped",
|
|
"Stopping",
|
|
):
|
|
is_stop_schedule_working = True
|
|
elif previous_state in ("Stopped", "Stopping") and current_state in (
|
|
"Running",
|
|
"Starting",
|
|
):
|
|
is_start_schedule_working = True
|
|
if is_start_schedule_working and is_stop_schedule_working:
|
|
break
|
|
previous_state = current_state
|
|
|
|
self.debug("Is stop schedule working: %s" % is_stop_schedule_working)
|
|
self.debug("Is start schedule working: %s" % is_start_schedule_working)
|
|
|
|
self.assertTrue(
|
|
is_stop_schedule_working,
|
|
"VM switched states from Running to Stopped at least once",
|
|
)
|
|
|
|
self.assertTrue(
|
|
is_start_schedule_working,
|
|
"VM switched states from Stopped to Running at least once",
|
|
)
|
|
|
|
# Delete VM Schedule
|
|
start_vmschedule.delete(self.apiclient)
|
|
stop_vmschedule.delete(self.apiclient)
|
|
|
|
# To ensure that all vm schedules have been deleted and all of their jobs have been completed
|
|
time.sleep(60)
|
|
|
|
# Verify VM Schedule is deleted
|
|
self.assertEqual(
|
|
ResourceSchedule.list(
|
|
self.apiclient, RESOURCE_TYPE, self.virtual_machine.id, id=start_vmschedule.id
|
|
),
|
|
None,
|
|
"Check VM Schedule is deleted",
|
|
)
|
|
self.assertEqual(
|
|
ResourceSchedule.list(
|
|
self.apiclient, RESOURCE_TYPE, self.virtual_machine.id, id=stop_vmschedule.id
|
|
),
|
|
None,
|
|
"Check VM Schedule is deleted",
|
|
)
|
|
|
|
# Verify VM does not switch states after deleting schedules at least for 2 minutes
|
|
previous_state = self.virtual_machine.update(self.apiclient).state
|
|
state_changed = False
|
|
for i in range(0, 4):
|
|
time.sleep(30)
|
|
current_state = self.virtual_machine.update(self.apiclient).state
|
|
if previous_state != current_state:
|
|
# Add these checks because VMs can take some time to start or stop
|
|
if (previous_state == 'Starting' and current_state in ('Starting', 'Running')) or (
|
|
previous_state == 'Stopping' and current_state in ('Stopping', 'Stopped')):
|
|
continue
|
|
self.debug(
|
|
"VM changed state from %s to %s" % (previous_state, current_state)
|
|
)
|
|
state_changed = True
|
|
break
|
|
|
|
self.assertFalse(
|
|
state_changed,
|
|
"VM did not switch states after schedule time",
|
|
)
|
|
return
|