Skip to content
This repository was archived by the owner on Apr 7, 2022. It is now read-only.

Commit 658ed4f

Browse files
author
dgaikwad
committed
Schedule Task event test
1 parent 4bd536d commit 658ed4f

File tree

6 files changed

+159
-59
lines changed

6 files changed

+159
-59
lines changed

cfme/configure/configuration/system_schedules.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from cfme.utils.appliance.implementations.ui import navigator
1717
from cfme.utils.pretty import Pretty
1818
from cfme.utils.update import Updateable
19+
from widgetastic_manageiq import AttributeValueForm
1920
from widgetastic_manageiq import Calendar
2021
from widgetastic_manageiq import Checkbox
2122
from widgetastic_manageiq import Dropdown
@@ -59,6 +60,7 @@ class ScheduleAddEditEntities(View):
5960
request = Input(name='object_request')
6061
object_type = BootstrapSelect('target_class')
6162
object_selection = BootstrapSelect('target_id')
63+
attribute_value_pairs = AttributeValueForm("attribute_", "value_")
6264

6365

6466
class ScheduleAllView(ConfigurationView):
@@ -196,6 +198,9 @@ class SystemSchedule(BaseEntity, Updateable, Pretty):
196198
# Samba backup config
197199
samba_username = attr.ib(default=None)
198200
samba_password = attr.ib(default=None)
201+
# Automation Task
202+
request = attr.ib(default=None)
203+
attribute_value_pairs = attr.ib(default=None)
199204

200205
def update(self, updates, reset=False, cancel=False):
201206
""" Modify an existing schedule with informations from this instance.
@@ -309,7 +314,8 @@ class SystemSchedulesCollection(BaseCollection):
309314
def create(self, name, description, active=True, action_type=None, run_type=None,
310315
run_every=None, time_zone=None, start_date=None, start_hour=None, start_minute=None,
311316
filter_level1=None, filter_level2=None, backup_type=None, depot_name=None, uri=None,
312-
samba_username=None, samba_password=None, cancel=False):
317+
samba_username=None, samba_password=None, cancel=False, request=None,
318+
attribute_value_pairs=None):
313319
""" Create a new schedule from the informations stored in the object.
314320
315321
Args:
@@ -343,6 +349,8 @@ def create(self, name, description, active=True, action_type=None, run_type=None
343349
'samba_password': samba_password,
344350
'samba_password_verify': samba_password
345351
})
352+
elif action_type == "Automation Tasks":
353+
details.update({"request": request, "attribute_value_pairs": attribute_value_pairs})
346354
else:
347355
details.update({
348356
'items_analysis': {
@@ -364,7 +372,8 @@ def create(self, name, description, active=True, action_type=None, run_type=None
364372
start_minute=start_minute, filter_level1=filter_level1,
365373
filter_level2=filter_level2, backup_type=backup_type,
366374
depot_name=depot_name, uri=uri, samba_username=samba_username,
367-
samba_password=samba_password)
375+
samba_password=samba_password, request=request,
376+
attribute_value_pairs=attribute_value_pairs)
368377
return schedule
369378

370379

cfme/fixtures/automate.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import fauxfactory
44
import pytest
5+
import pytz
6+
from dateutil import parser
57

68
from cfme.utils.conf import cfme_data
79
from cfme.utils.ftp import FTPClientWrapper
@@ -108,3 +110,20 @@ def test_foo(import_datastore, import_data):
108110
domain.enabled = True
109111
yield domain
110112
domain.delete_if_exists()
113+
114+
115+
@pytest.fixture
116+
def current_server_time(appliance):
117+
current_time = parser.parse(appliance.ssh_client.run_command('date').output)
118+
tz_list = appliance.ssh_client.run_command("timedatectl | grep 'Time zone'") \
119+
.output.strip().split(' ')
120+
121+
tz_name = tz_list[2]
122+
tz_num = tz_list[-1][:-1]
123+
date = current_time.replace(tzinfo=pytz.timezone(tz_name))
124+
return date, tz_num
125+
126+
127+
def round_min(value, base=5):
128+
round_value = int(base * round(float(value) / base))
129+
return 0 if round_value == 60 else round_value

cfme/tests/automate/test_automate_manual.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -287,42 +287,6 @@ def test_git_refresh_with_rapid_updates():
287287
pass
288288

289289

290-
@pytest.mark.tier(2)
291-
@pytest.mark.meta(coverage=[1713072, 1745197])
292-
def test_automate_task_schedule():
293-
"""
294-
Polarion:
295-
assignee: dgaikwad
296-
initialEstimate: 1/8h
297-
caseposneg: positive
298-
casecomponent: Automate
299-
setup:
300-
1. Create domain, namespace, class and instance
301-
2. Also create automate method with below ruby code:
302-
>> $evm.log(:info, "Hello World")
303-
testSteps:
304-
1. Go to Configuration > Settings > Zones > Schedules
305-
2. Create schedule with required fields:
306-
>> Action - Automation Tasks
307-
>> Object Details(Request) - Call_Instance
308-
>> Attribute/Value Pairs
309-
>> domain - domain_name
310-
>> namespace - namespace_name
311-
>> class - class_name
312-
>> instance - instance_name
313-
>> Timer Options
314-
3. Check automation logs
315-
expectedResults:
316-
1.
317-
2.
318-
3. Automate method should be executed on scheduled time.
319-
320-
Bugzilla:
321-
1713072
322-
"""
323-
pass
324-
325-
326290
@pytest.mark.tier(2)
327291
@pytest.mark.meta(coverage=[1743227])
328292
def test_queue_up_schedule_run_now():

cfme/tests/automate/test_method.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
import fauxfactory
44
import pytest
5+
from dateutil import relativedelta
56

67
from . import tag_delete_from_category
78
from cfme import test_requirements
89
from cfme.automate.explorer.klass import ClassDetailsView
910
from cfme.automate.simulation import simulate
11+
from cfme.fixtures.automate import round_min
1012
from cfme.rest.gen_data import users as _users
1113
from cfme.services.service_catalogs import ServiceCatalogs
1214
from cfme.utils.appliance.implementations.rest import ViaREST
@@ -21,6 +23,34 @@
2123
pytestmark = [test_requirements.automate, pytest.mark.tier(2)]
2224

2325

26+
@pytest.fixture
27+
def custom_automate_setup(domain, namespace):
28+
auto_class = namespace.classes.create(
29+
name=fauxfactory.gen_alphanumeric(15, start="class_"),
30+
display_name=fauxfactory.gen_alpha(),
31+
description=fauxfactory.gen_alpha(),
32+
)
33+
34+
method = auto_class.methods.create(
35+
name=fauxfactory.gen_alphanumeric(15, start="method_"),
36+
location="inline",
37+
script='$evm.log(:info, "Hello World")',
38+
)
39+
schema_field = {
40+
"name": fauxfactory.gen_alphanumeric(15, start="schema_"),
41+
"type": "Method",
42+
"data_type": "String",
43+
}
44+
auto_class.schema.add_fields(schema_field)
45+
46+
instance = auto_class.instances.create(
47+
name=fauxfactory.gen_alphanumeric(15, start="instance_"),
48+
fields={schema_field["name"]: {"value": method.name}},
49+
)
50+
yield domain, namespace, auto_class, instance
51+
auto_class.delete()
52+
53+
2454
@pytest.fixture(scope='function')
2555
def original_class(domain):
2656
# Take the 'Request' class and copy it for own purpose.
@@ -797,3 +827,90 @@ def test_delete_tag_from_category(custom_instance):
797827
"instance": instance.name,
798828
},
799829
)
830+
831+
832+
@pytest.mark.customer_scenario
833+
@pytest.mark.meta(automate=[1713072, 1745197])
834+
def test_automate_task_schedule(appliance, custom_automate_setup, current_server_time, request):
835+
"""
836+
Polarion:
837+
assignee: dgaikwad
838+
initialEstimate: 1/8h
839+
caseposneg: positive
840+
casecomponent: Automate
841+
setup:
842+
1. Create domain, namespace, class and instance
843+
2. Also create automate method with below ruby code:
844+
>> $evm.log(:info, "Hello World")
845+
testSteps:
846+
1. Go to Configuration > Settings > Zones > Schedules
847+
2. Create schedule with required fields:
848+
>> Action - Automation Tasks
849+
>> Object Details(Request) - Call_Instance
850+
>> Attribute/Value Pairs
851+
>> domain - domain_name
852+
>> namespace - namespace_name
853+
>> class - class_name
854+
>> instance - instance_name
855+
>> Timer Options
856+
3. Check automation logs more than 1 times
857+
expectedResults:
858+
1.
859+
2.
860+
3. Automate method should be executed on scheduled time.
861+
862+
Bugzilla:
863+
1713072
864+
"""
865+
domain, namespace, auto_class, instance = custom_automate_setup
866+
current_time, tz_num = current_server_time
867+
start_date = current_time + relativedelta.relativedelta(minutes=5)
868+
view = navigate_to(appliance.collections.system_schedules, 'Add')
869+
available_list = view.form.time_zone.all_options
870+
tz_select = next(tz.text for tz in available_list if f'{tz_num[0:3]}:00'in tz.text)
871+
if round_min(start_date.minute) == 0:
872+
start_date = start_date + relativedelta.relativedelta(minutes=60 - start_date.minute)
873+
start_date_minute = str(start_date.minute)
874+
else:
875+
start_date_minute = str(round_min(start_date.minute))
876+
877+
attribute_value_pairs = {
878+
"domain": domain.name,
879+
"namespace": namespace.name,
880+
"class": auto_class.name,
881+
"instance": instance.name,
882+
}
883+
884+
schedule = appliance.collections.system_schedules.create(
885+
name=fauxfactory.gen_alphanumeric(),
886+
description=fauxfactory.gen_alphanumeric(),
887+
action_type="Automation Tasks",
888+
request="Call_Instance",
889+
attribute_value_pairs=attribute_value_pairs,
890+
run_type="Hourly",
891+
time_zone=tz_select,
892+
start_hour=str(start_date.hour),
893+
start_minute=start_date_minute,
894+
)
895+
896+
@request.addfinalizer
897+
def _finalize():
898+
try:
899+
schedule.delete_if_exists()
900+
except TypeError:
901+
# Delete failing only on PRT with type error
902+
pass
903+
904+
matched_pattern = ".*INFO.* : Q-task_id.* Hello World"
905+
906+
def _check_automation_log():
907+
log = LogValidator("/var/www/miq/vmdb/log/automation.log",
908+
matched_patterns=[matched_pattern]
909+
)
910+
log.start_monitoring()
911+
log.validate(wait="15m")
912+
913+
_check_automation_log()
914+
next_run_date = start_date + relativedelta.relativedelta(minutes=-5, hours=1)
915+
appliance.ssh_client.run_command(f"date {next_run_date.strftime('%m%d%H%M%Y')}")
916+
_check_automation_log()

cfme/tests/configure/test_schedule_operations.py

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import fauxfactory
22
import pytest
3-
import pytz
43
from dateutil import parser
54
from dateutil import relativedelta
65

76
from cfme import test_requirements
87
from cfme.base.ui import BaseLoggedInPage
8+
from cfme.fixtures.automate import round_min
99
from cfme.infrastructure.provider.virtualcenter import VMwareProvider
1010
from cfme.markers.env_markers.provider import ONE
1111
from cfme.utils.appliance.implementations.ui import navigate_to
@@ -37,23 +37,6 @@ def host_with_credentials(appliance, provider):
3737
host.remove_credentials_rest()
3838

3939

40-
@pytest.fixture
41-
def current_server_time(appliance):
42-
current_time = parser.parse(appliance.ssh_client.run_command('date').output)
43-
tz_list = appliance.ssh_client.run_command("timedatectl | grep 'Time zone'") \
44-
.output.strip().split(' ')
45-
46-
tz_name = tz_list[2]
47-
tz_num = tz_list[-1][:-1]
48-
date = current_time.replace(tzinfo=pytz.timezone(tz_name))
49-
return date, tz_num
50-
51-
52-
def round_min(value, base=5):
53-
return (0 if int(base * round(float(value) / base)) == 60
54-
else int(base * round(float(value) / base)))
55-
56-
5740
def test_schedule_crud(appliance, current_server_time):
5841
"""
5942
Polarion:

widgetastic_manageiq/__init__.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3155,10 +3155,16 @@ class fields(ParametrizedView): # noqa
31553155
PARAMETERS = ("id",)
31563156

31573157
attribute = Input(
3158-
locator=ParametrizedLocator(".//input[@id=concat({@attr_prefix|quote}, {id|quote})]")
3158+
locator=ParametrizedLocator(
3159+
"(.//input[@id=concat({@attr_prefix|quote}, {id|quote})])|"
3160+
"(.//div[./label[contains((.),{id|quote})]]//input[contains(@ng-model,'0')])"
3161+
)
31593162
)
31603163
value = Input(
3161-
locator=ParametrizedLocator(".//input[@id=concat({@val_prefix|quote}, {id|quote})]")
3164+
locator=ParametrizedLocator(
3165+
"(.//input[@id=concat({@val_prefix|quote}, {id|quote})])|"
3166+
"(.//div[./label[contains((.),{id|quote})]]//input[contains(@ng-model,'1')])"
3167+
)
31623168
)
31633169

31643170
@property
@@ -3172,7 +3178,9 @@ def val_prefix(self):
31723178
# TODO: Figure out how to smuggle some extra data to the all classmethod
31733179
# TODO: since it is now impossible to pass the attr_prefix to it.
31743180

3175-
ATTRIBUTES = ParametrizedLocator(".//input[starts-with(@id, {@attr_prefix|quote})]")
3181+
ATTRIBUTES = ParametrizedLocator(
3182+
"(.//input[starts-with(@id, {@attr_prefix|quote})])|(.//input[contains(@ng-model, '0')])"
3183+
)
31763184

31773185
def __init__(self, parent, attr_prefix, val_prefix, start=1, end=5, logger=None):
31783186
View.__init__(self, parent, logger=logger)

0 commit comments

Comments
 (0)