blob: 79a6dcc0e02c6654629c7cd7a30b113af5e10c1d [file] [log] [blame]
jamesrenc3940222010-02-19 21:57:37 +00001import common
2import os
3from autotest_lib.frontend.afe import models as afe_models, model_logic
jamesren3e9f6092010-03-11 21:32:10 +00004from autotest_lib.frontend.planner import models, model_attributes
jamesrenc3940222010-02-19 21:57:37 +00005from autotest_lib.client.common_lib import global_config, utils
6
7
8PLANNER_LABEL_PREFIX = 'planner_'
9PLANNER_ATOMIC_GROUP_NAME = 'planner_global_atomic_group'
10SERVER = global_config.global_config.get_config_value('SERVER', 'hostname')
11LAZY_LOADED_FILES = {}
12
13
14def create_plan_label(plan):
15 """
16 Creates the host label to apply on the plan hosts
17 """
18 group, _ = afe_models.AtomicGroup.objects.get_or_create(
19 name=PLANNER_ATOMIC_GROUP_NAME)
20 if group.invalid:
21 group.invalid = False
22 group.save()
23
24 name = PLANNER_LABEL_PREFIX + plan.name
25 if bool(afe_models.Label.valid_objects.filter(name=name)):
26 raise model_logic.ValidationError('Label %s already exists, '
27 'cannot start plan' % name)
28 label = afe_models.Label(name=name, atomic_group=group)
29 label.save()
30
31 return label
32
33
34def start_plan(plan, label):
35 """
36 Takes the necessary steps to start a test plan in Autotest
37 """
jamesrenc3940222010-02-19 21:57:37 +000038 keyvals = {'server': SERVER,
39 'plan_id': plan.id,
40 'label_name': label.name}
jamesren3e9f6092010-03-11 21:32:10 +000041 options = {'name': plan.name + '_execution_engine',
42 'priority': afe_models.Job.Priority.MEDIUM,
43 'control_file': _get_execution_engine_control(),
44 'control_type': afe_models.Job.ControlType.SERVER,
45 'synch_count': None,
46 'run_verify': False,
47 'reboot_before': False,
48 'reboot_after': False,
49 'dependencies': (),
jamesrenc3940222010-02-19 21:57:37 +000050 'keyvals': keyvals}
jamesren3e9f6092010-03-11 21:32:10 +000051 job = afe_models.Job.create(owner=afe_models.User.current_user().login,
52 options=options, hosts=())
53 job.queue(hosts=())
jamesrenc3940222010-02-19 21:57:37 +000054
55
56def _get_execution_engine_control():
57 """
58 Gets the control file to run the execution engine
59 """
60 return lazy_load(os.path.join(os.path.dirname(__file__),
61 'execution_engine_control.srv'))
62
63
64def lazy_load(path):
65 """
66 Lazily loads the file indicated by the path given, and caches the result
67 """
68 if path not in LAZY_LOADED_FILES:
69 LAZY_LOADED_FILES[path] = utils.read_file(path)
70
71 return LAZY_LOADED_FILES[path]
jamesren3e9f6092010-03-11 21:32:10 +000072
73
74def update_hosts_table(plan):
75 """
76 Resolves the host labels into host objects
77
78 Adds or removes hosts from the planner Hosts model based on changes to the
79 host label
80 """
81 label_hosts = set()
82
83 for label in plan.host_labels.all():
84 for afe_host in label.host_set.all():
85 host, created = models.Host.objects.get_or_create(plan=plan,
86 host=afe_host)
87 if created:
88 host.added_by_label = True
89 host.save()
90
91 label_hosts.add(host.host.id)
92
93 deleted_hosts = models.Host.objects.filter(
94 plan=plan, added_by_label=True).exclude(host__id__in=label_hosts)
95 deleted_hosts.delete()
96
97
98def compute_next_test_config(plan, host):
99 """
100 Gets the next test config that should be run for this plan and host
101
102 Returns None if the host is already running a job. Also sets the host's
103 complete bit if the host is finished running tests.
104 """
105 if host.blocked:
106 return None
107
108 test_configs = plan.testconfig_set.order_by('execution_order')
109 for test_config in test_configs:
110 afe_jobs = plan.job_set.filter(test_config=test_config)
111 afe_job_ids = afe_jobs.values_list('afe_job', flat=True)
112 hqes = afe_models.HostQueueEntry.objects.filter(job__id__in=afe_job_ids,
113 host=host.host)
114 if not hqes:
115 return test_config.id
116 for hqe in hqes:
117 if not hqe.complete:
118 # HostQueueEntry still active for this host,
119 # should not run another test
120 return None
121
122 # All HQEs related to this host are complete
123 host.complete = True
124 host.save()
125 return None
126
127
128def check_for_completion(plan):
129 """
130 Checks if a plan is actually complete. Sets complete=True if so
131 """
132 if not models.Host.objects.filter(plan=plan, complete=False):
133 plan.complete = True
134 plan.save()
135
136
137def compute_test_run_status(status):
138 """
139 Converts a TKO test status to a Planner test run status
140 """
141 Status = model_attributes.TestRunStatus
142 if status == 'GOOD':
143 return Status.PASSED
144 if status == 'RUNNING':
145 return Status.ACTIVE
146 return Status.FAILED
147
148
149def add_test_run(plan, planner_job, tko_test, hostname, status):
150 """
151 Adds a TKO test to the Planner Test Run tables
152 """
153 host = afe_models.Host.objects.get(hostname=hostname)
154
155 planner_host = models.Host.objects.get(plan=plan, host=host)
156 test_run, _ = models.TestRun.objects.get_or_create(plan=plan,
157 test_job=planner_job,
158 tko_test=tko_test,
159 host=planner_host)
160 test_run.status = status
161 test_run.save()