19
19
from django.core.exceptions import PermissionDenied
20
20
from django.http import HttpResponse
21
from maasserver.api import extract_oauth_key
21
from maasserver.api import (
22
27
from maasserver.exceptions import (
26
from maasserver.models import SSHKey
33
from maasserver.models import (
35
NODE_STATUS_CHOICES_DICT,
27
38
from metadataserver.models import (
31
42
from piston.handler import BaseHandler
43
from piston.utils import rc
34
46
class UnknownMetadataVersion(MAASAPINotFound):
82
94
fields = ('latest', '2012-03-01')
85
98
class VersionIndexHandler(MetadataViewHandler):
86
99
"""Listing for a given metadata version."""
100
allowed_methods = ('GET', 'POST')
88
101
fields = ('meta-data', 'user-data')
103
# States in which a node is allowed to signal commissioning status.
104
# (Only in Commissioning state, however, will it have any effect.)
105
signalable_states = [
106
NODE_STATUS.COMMISSIONING,
108
NODE_STATUS.FAILED_TESTS,
111
# Statuses that a commissioning node may signal, and the respective
112
# state transitions that they trigger on the node.
113
signaling_statuses = {
114
'OK': NODE_STATUS.READY,
115
'FAILED': NODE_STATUS.FAILED_TESTS,
90
119
def read(self, request, version):
120
"""Read the metadata index for this version."""
91
121
check_version(version)
92
122
if NodeUserData.objects.has_user_data(get_node_for_request(request)):
93
123
shown_fields = self.fields
96
126
shown_fields.remove('user-data')
97
127
return make_list_response(sorted(shown_fields))
129
@api_exported('signal', 'POST')
130
def signal(self, request, version=None):
131
"""Signal commissioning status.
133
A commissioning node can call this to report progress of the
134
commissioning process to the metadata server.
136
Calling this from a node that is not Commissioning, Ready, or
137
Failed Tests is an error. Signaling completion more than once is not
138
an error; all but the first successful call are ignored.
140
:param status: A commissioning status code. This can be "OK" (to
141
signal that commissioning has completed successfully), or "FAILED"
142
(to signal failure), or "WORKING" (for progress reports).
143
:param error: An optional error string. If given, this will be stored
144
(overwriting any previous error string), and displayed in the MAAS
145
UI. If not given, any previous error string will be cleared.
147
node = get_node_for_request(request)
148
status = request.POST.get('status', None)
150
status = get_mandatory_param(request.POST, 'status')
151
if node.status not in self.signalable_states:
152
raise NodeStateViolation(
153
"Node wasn't commissioning (status is %s)"
154
% NODE_STATUS_CHOICES_DICT[node.status])
156
if status not in self.signaling_statuses:
157
raise MAASAPIBadRequest(
158
"Unknown commissioning status: '%s'" % status)
160
if node.status != NODE_STATUS.COMMISSIONING:
161
# Already registered. Nothing to be done.
164
target_status = self.signaling_statuses.get(status)
165
if target_status in (None, node.status):
166
# No status change. Nothing to be done.
169
node.status = target_status
170
node.error = request.POST.get('error', '')
100
176
class MetaDataHandler(VersionIndexHandler):
101
177
"""Meta-data listing for a given version."""