8
8
from django.core.exceptions import ObjectDoesNotExist
9
9
from django.db.models import (
19
from maasserver.enum import (
23
from maasserver.exceptions import NoScriptsFound
24
from maasserver.models import Config
17
25
from maasserver.models.cleansave import CleanSave
18
26
from maasserver.preseed import CURTIN_INSTALL_LOG
19
27
from metadataserver import DefaultMeta
30
38
class ScriptSetManager(Manager):
32
def create_commissioning_script_set(self, node):
40
def _clean_old(self, node, result_type, new_script_set):
41
# Gather the list of existing script results of the given type for this
43
script_sets = self.filter(node=node, result_type=result_type)
44
# Exclude the newly created script_set so we don't try to remove it.
45
# This can happen when multiple script_sets have last_ping = None.
46
script_sets = script_sets.exclude(id=new_script_set.id)
47
# Sort by last_ping in reverse order so we only remove older entrees.
48
script_sets = script_sets.order_by('last_ping').reverse()
50
RESULT_TYPE.COMMISSIONING: 'max_node_commissioning_results',
51
RESULT_TYPE.TESTING: 'max_node_testing_results',
52
RESULT_TYPE.INSTALLATION: 'max_node_installation_results',
54
script_set_limit = Config.objects.get_config(config_var[result_type])
55
# Remove one from the script_set_limit to account for the newly created
58
if script_sets.count() > script_set_limit:
59
for script_set in script_sets[script_set_limit:]:
62
def create_commissioning_script_set(self, node, scripts=[]):
33
63
"""Create a new commissioning ScriptSet with ScriptResults
35
ScriptResults will be created for all builtin commissioning scripts
36
and custom commissioning scripts if the node is not a controller.
65
ScriptResults will be created for all builtin commissioning scripts.
66
Optionally a list of user scripts and tags can be given to create
67
ScriptResults for. If None all user scripts will be assumed.
38
69
# Avoid circular dependencies.
39
70
from metadataserver.models import ScriptResult
41
72
script_set = self.create(
42
node=node, result_type=RESULT_TYPE.COMMISSIONING)
73
node=node, result_type=RESULT_TYPE.COMMISSIONING,
74
power_state_before_transition=node.power_state)
75
self._clean_old(node, RESULT_TYPE.COMMISSIONING, script_set)
44
77
for script_name, data in NODE_INFO_SCRIPTS.items():
45
78
if node.is_controller and not data['run_on_controller']:
53
86
if node.is_controller:
56
for script in Script.objects.filter(
57
script_type=SCRIPT_TYPE.COMMISSIONING):
90
qs = Script.objects.filter(
91
script_type=SCRIPT_TYPE.COMMISSIONING)
93
qs = Script.objects.filter(
94
Q(name__in=scripts) | Q(tags__overlap=scripts),
95
script_type=SCRIPT_TYPE.COMMISSIONING)
58
97
ScriptResult.objects.create(
59
98
script_set=script_set, status=SCRIPT_STATUS.PENDING,
60
script=script, script_version=script.script)
64
def create_testing_script_set(self, node):
65
"""Create a new testing ScriptSet with ScriptResults."""
103
def create_testing_script_set(self, node, scripts=[]):
104
"""Create a new testing ScriptSet with ScriptResults.
106
Optionally a list of user scripts and tags can be given to create
107
ScriptResults for. If None all Scripts tagged 'commissioning' will be
66
109
# Avoid circular dependencies.
67
110
from metadataserver.models import ScriptResult
69
script_set = self.create(node=node, result_type=RESULT_TYPE.TESTING)
71
for script in Script.objects.filter(script_type=SCRIPT_TYPE.TESTING):
113
scripts.append('commissioning')
115
qs = Script.objects.filter(
116
Q(name__in=scripts) | Q(tags__overlap=scripts),
117
script_type=SCRIPT_TYPE.TESTING)
119
# A ScriptSet should never be empty. If an empty script set is set as a
120
# node's current_testing_script_set the UI will show an empty table and
121
# the node-results API will not output any test results.
123
raise NoScriptsFound()
125
script_set = self.create(
126
node=node, result_type=RESULT_TYPE.TESTING,
127
power_state_before_transition=node.power_state)
72
130
ScriptResult.objects.create(
73
131
script_set=script_set, status=SCRIPT_STATUS.PENDING,
74
script=script, script_version=script.script)
134
self._clean_old(node, RESULT_TYPE.TESTING, script_set)
78
137
def create_installation_script_set(self, node):
81
140
from metadataserver.models import ScriptResult
83
142
script_set = self.create(
84
node=node, result_type=RESULT_TYPE.INSTALLATION)
143
node=node, result_type=RESULT_TYPE.INSTALLATION,
144
power_state_before_transition=node.power_state)
85
146
# Curtin uploads the installation log using the full path we specify in
87
148
ScriptResult.objects.create(
88
149
script_set=script_set, status=SCRIPT_STATUS.PENDING,
89
150
script_name=CURTIN_INSTALL_LOG)
152
self._clean_old(node, RESULT_TYPE.INSTALLATION, script_set)
105
168
choices=RESULT_TYPE_CHOICES, editable=False,
106
169
default=RESULT_TYPE.COMMISSIONING)
171
power_state_before_transition = CharField(
172
max_length=10, null=False, blank=False,
173
choices=POWER_STATE_CHOICES, default=POWER_STATE.UNKNOWN,
108
176
def __str__(self):
109
177
return "%s/%s" % (
110
178
self.node.system_id, RESULT_TYPE_CHOICES[self.result_type][1])