Merge lp:~andreserl/maas/lp1460193 into lp:~maas-committers/maas/trunk
- lp1460193
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Andres Rodriguez |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4262 |
Proposed branch: | lp:~andreserl/maas/lp1460193 |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
770 lines (+617/-2) 10 files modified
etc/maas/templates/commissioning-user-data/user_data.template (+7/-0) src/maasserver/api/nodes.py (+19/-0) src/maasserver/migrations/0176_add_enable_ssh_and_block_poweroff_commissioning_attributes.py (+495/-0) src/maasserver/models/node.py (+28/-0) src/maasserver/models/tests/test_node.py (+37/-0) src/maasserver/tests/test_preseed.py (+1/-1) src/maasserver/websockets/handlers/device.py (+2/-0) src/maasserver/websockets/handlers/node.py (+2/-0) src/metadataserver/api.py (+4/-1) src/metadataserver/tests/test_api.py (+22/-0) |
To merge this branch: | bzr merge lp:~andreserl/maas/lp1460193 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andres Rodriguez (community) | Approve | ||
Blake Rouse (community) | Approve | ||
Review via email: mp+269965@code.launchpad.net |
Commit message
Set the user as the owner during commissioning, which allows the import of the user's SSH key into the commissioning environment. However, only import SSH keys if the 'enable_ssh' parameters is enabled. Additionally, allow blocking the power off the machine after commissioning, by enabling 'block_poweroff'.
Description of the change
Blake Rouse (blake-rouse) wrote : | # |
Looks good. Just two comments about coding style.
Andres Rodriguez (andreserl) : | # |
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~andreserl/maas/lp1460193 into lp:maas failed. Below is the output from the failed tests.
Ign http://
Hit http://
Hit http://
Ign http://
Ign http://
Hit http://
Get:1 http://
Hit http://
Get:2 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:3 http://
Get:4 http://
Get:5 http://
Get:6 http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,365 kB in 3s (443 kB/s)
Reading package lists...
sudo DEBIAN_
--
Andres Rodriguez (andreserl) : | # |
Preview Diff
1 | === modified file 'etc/maas/templates/commissioning-user-data/user_data.template' |
2 | --- etc/maas/templates/commissioning-user-data/user_data.template 2015-03-26 22:43:10 +0000 |
3 | +++ etc/maas/templates/commissioning-user-data/user_data.template 2015-09-15 14:12:24 +0000 |
4 | @@ -142,7 +142,14 @@ |
5 | fi |
6 | } |
7 | |
8 | +write_block_poweroff() { |
9 | + touch /tmp/block-poweroff |
10 | +} |
11 | + |
12 | main() { |
13 | + {{if node.block_poweroff}} |
14 | + write_block_poweroff |
15 | + {{endif}} |
16 | write_poweroff_job |
17 | write_systemd_poweroff_job |
18 | |
19 | |
20 | === modified file 'src/maasserver/api/nodes.py' |
21 | --- src/maasserver/api/nodes.py 2015-09-09 18:38:34 +0000 |
22 | +++ src/maasserver/api/nodes.py 2015-09-15 14:12:24 +0000 |
23 | @@ -35,6 +35,7 @@ |
24 | OperationsHandler, |
25 | ) |
26 | from maasserver.api.utils import ( |
27 | + extract_bool, |
28 | get_mandatory_param, |
29 | get_oauth_token, |
30 | get_optional_list, |
31 | @@ -508,6 +509,13 @@ |
32 | def commission(self, request, system_id): |
33 | """Begin commissioning process for a node. |
34 | |
35 | + :param enable_ssh: Whether to enable SSH for the commissioning |
36 | + environment using the user's SSH key(s). |
37 | + :type enable_ssh: bool ('0' for False, '1' for True) |
38 | + :param block_poweroff: Whether to prevent the power off the node |
39 | + after the commissioning has completed. |
40 | + :type block_poweroff: bool ('0' for False, '1' for True) |
41 | + |
42 | A node in the 'ready', 'declared' or 'failed test' state may |
43 | initiate a commissioning cycle where it is checked out and tested |
44 | in preparation for transitioning to the 'ready' state. If it is |
45 | @@ -517,7 +525,18 @@ |
46 | |
47 | Returns 404 if the node is not found. |
48 | """ |
49 | + enable_ssh = get_optional_param(request.data, 'enable_ssh', 0) |
50 | + block_poweroff = get_optional_param(request.data, 'block_poweroff', 0) |
51 | + |
52 | node = get_object_or_404(Node, system_id=system_id) |
53 | + |
54 | + if enable_ssh: |
55 | + enable_ssh = extract_bool(enable_ssh) |
56 | + if block_poweroff: |
57 | + block_poweroff = extract_bool(block_poweroff) |
58 | + node.set_commissioning_parameters( |
59 | + enable_ssh=enable_ssh, block_poweroff=block_poweroff) |
60 | + |
61 | form_class = get_action_form(user=request.user) |
62 | form = form_class( |
63 | node, data={NodeActionForm.input_name: Commission.name}) |
64 | |
65 | === added file 'src/maasserver/migrations/0176_add_enable_ssh_and_block_poweroff_commissioning_attributes.py' |
66 | --- src/maasserver/migrations/0176_add_enable_ssh_and_block_poweroff_commissioning_attributes.py 1970-01-01 00:00:00 +0000 |
67 | +++ src/maasserver/migrations/0176_add_enable_ssh_and_block_poweroff_commissioning_attributes.py 2015-09-15 14:12:24 +0000 |
68 | @@ -0,0 +1,495 @@ |
69 | +from django.db import models |
70 | +from south.db import db |
71 | +# -*- coding: utf-8 -*- |
72 | +from south.utils import datetime_utils as datetime |
73 | +from south.v2 import SchemaMigration |
74 | + |
75 | + |
76 | +class Migration(SchemaMigration): |
77 | + |
78 | + def forwards(self, orm): |
79 | + # Adding field 'Node.enable_ssh' |
80 | + db.add_column(u'maasserver_node', 'enable_ssh', |
81 | + self.gf('django.db.models.fields.BooleanField')(default=False), |
82 | + keep_default=False) |
83 | + |
84 | + # Adding field 'Node.block_poweroff' |
85 | + db.add_column(u'maasserver_node', 'block_poweroff', |
86 | + self.gf('django.db.models.fields.BooleanField')(default=False), |
87 | + keep_default=False) |
88 | + |
89 | + |
90 | + def backwards(self, orm): |
91 | + # Deleting field 'Node.enable_ssh' |
92 | + db.delete_column(u'maasserver_node', 'enable_ssh') |
93 | + |
94 | + # Deleting field 'Node.block_poweroff' |
95 | + db.delete_column(u'maasserver_node', 'block_poweroff') |
96 | + |
97 | + |
98 | + models = { |
99 | + u'auth.group': { |
100 | + 'Meta': {'object_name': 'Group'}, |
101 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
102 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
103 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
104 | + }, |
105 | + u'auth.permission': { |
106 | + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, |
107 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
108 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), |
109 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
110 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
111 | + }, |
112 | + u'auth.user': { |
113 | + 'Meta': {'object_name': 'User'}, |
114 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
115 | + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}), |
116 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
117 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), |
118 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
119 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
120 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
121 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
122 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
123 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
124 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
125 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), |
126 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
127 | + }, |
128 | + u'contenttypes.contenttype': { |
129 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
130 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
131 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
132 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
133 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
134 | + }, |
135 | + u'maasserver.blockdevice': { |
136 | + 'Meta': {'ordering': "[u'id']", 'unique_together': "((u'node', u'name'),)", 'object_name': 'BlockDevice'}, |
137 | + 'block_size': ('django.db.models.fields.IntegerField', [], {}), |
138 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
139 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
140 | + 'id_path': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), |
141 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
142 | + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}), |
143 | + 'size': ('django.db.models.fields.BigIntegerField', [], {}), |
144 | + 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}), |
145 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
146 | + }, |
147 | + u'maasserver.bootresource': { |
148 | + 'Meta': {'unique_together': "((u'name', u'architecture'),)", 'object_name': 'BootResource'}, |
149 | + 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
150 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
151 | + 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), |
152 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
153 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
154 | + 'rtype': ('django.db.models.fields.IntegerField', [], {'max_length': '10'}), |
155 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
156 | + }, |
157 | + u'maasserver.bootresourcefile': { |
158 | + 'Meta': {'unique_together': "((u'resource_set', u'filetype'),)", 'object_name': 'BootResourceFile'}, |
159 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
160 | + 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), |
161 | + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
162 | + 'filetype': ('django.db.models.fields.CharField', [], {'default': "u'root-tgz'", 'max_length': '20'}), |
163 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
164 | + 'largefile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.LargeFile']"}), |
165 | + 'resource_set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'files'", 'to': u"orm['maasserver.BootResourceSet']"}), |
166 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
167 | + }, |
168 | + u'maasserver.bootresourceset': { |
169 | + 'Meta': {'unique_together': "((u'resource', u'version'),)", 'object_name': 'BootResourceSet'}, |
170 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
171 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
172 | + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
173 | + 'resource': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'sets'", 'to': u"orm['maasserver.BootResource']"}), |
174 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
175 | + 'version': ('django.db.models.fields.CharField', [], {'max_length': '255'}) |
176 | + }, |
177 | + u'maasserver.bootsource': { |
178 | + 'Meta': {'object_name': 'BootSource'}, |
179 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
180 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
181 | + 'keyring_data': ('maasserver.fields.EditableBinaryField', [], {'blank': 'True'}), |
182 | + 'keyring_filename': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}), |
183 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
184 | + 'url': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '200'}) |
185 | + }, |
186 | + u'maasserver.bootsourcecache': { |
187 | + 'Meta': {'object_name': 'BootSourceCache'}, |
188 | + 'arch': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
189 | + 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}), |
190 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
191 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
192 | + 'label': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
193 | + 'os': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
194 | + 'release': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
195 | + 'subarch': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
196 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
197 | + }, |
198 | + u'maasserver.bootsourceselection': { |
199 | + 'Meta': {'unique_together': "((u'boot_source', u'os', u'release'),)", 'object_name': 'BootSourceSelection'}, |
200 | + 'arches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), |
201 | + 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}), |
202 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
203 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
204 | + 'labels': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), |
205 | + 'os': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), |
206 | + 'release': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), |
207 | + 'subarches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), |
208 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
209 | + }, |
210 | + u'maasserver.cacheset': { |
211 | + 'Meta': {'object_name': 'CacheSet'}, |
212 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
213 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
214 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
215 | + }, |
216 | + u'maasserver.candidatename': { |
217 | + 'Meta': {'unique_together': "((u'name', u'position'),)", 'object_name': 'CandidateName'}, |
218 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
219 | + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), |
220 | + 'position': ('django.db.models.fields.IntegerField', [], {}) |
221 | + }, |
222 | + u'maasserver.componenterror': { |
223 | + 'Meta': {'object_name': 'ComponentError'}, |
224 | + 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}), |
225 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
226 | + 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), |
227 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
228 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
229 | + }, |
230 | + u'maasserver.config': { |
231 | + 'Meta': {'object_name': 'Config'}, |
232 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
233 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), |
234 | + 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'}) |
235 | + }, |
236 | + u'maasserver.downloadprogress': { |
237 | + 'Meta': {'object_name': 'DownloadProgress'}, |
238 | + 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
239 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
240 | + 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}), |
241 | + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
242 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
243 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), |
244 | + 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
245 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
246 | + }, |
247 | + u'maasserver.event': { |
248 | + 'Meta': {'object_name': 'Event'}, |
249 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
250 | + 'description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}), |
251 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
252 | + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}), |
253 | + 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.EventType']"}), |
254 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
255 | + }, |
256 | + u'maasserver.eventtype': { |
257 | + 'Meta': {'object_name': 'EventType'}, |
258 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
259 | + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
260 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
261 | + 'level': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), |
262 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), |
263 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
264 | + }, |
265 | + u'maasserver.fabric': { |
266 | + 'Meta': {'object_name': 'Fabric'}, |
267 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
268 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
269 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), |
270 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
271 | + }, |
272 | + u'maasserver.filestorage': { |
273 | + 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'}, |
274 | + 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}), |
275 | + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
276 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
277 | + 'key': ('django.db.models.fields.CharField', [], {'default': "u'3ba44986-5bb3-11e5-9f58-7c7a9140484f'", 'unique': 'True', 'max_length': '36'}), |
278 | + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) |
279 | + }, |
280 | + u'maasserver.filesystem': { |
281 | + 'Meta': {'object_name': 'Filesystem'}, |
282 | + 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'null': 'True', 'blank': 'True'}), |
283 | + 'cache_set': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.CacheSet']"}), |
284 | + 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
285 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
286 | + 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.FilesystemGroup']"}), |
287 | + 'fstype': ('django.db.models.fields.CharField', [], {'default': "u'ext4'", 'max_length': '20'}), |
288 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
289 | + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
290 | + 'mount_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
291 | + 'mount_point': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
292 | + 'partition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Partition']", 'unique': 'True', 'null': 'True', 'blank': 'True'}), |
293 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
294 | + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) |
295 | + }, |
296 | + u'maasserver.filesystemgroup': { |
297 | + 'Meta': {'object_name': 'FilesystemGroup'}, |
298 | + 'cache_mode': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), |
299 | + 'cache_set': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.CacheSet']", 'null': 'True', 'blank': 'True'}), |
300 | + 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
301 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
302 | + 'group_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
303 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
304 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
305 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
306 | + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) |
307 | + }, |
308 | + u'maasserver.interface': { |
309 | + 'Meta': {'ordering': "(u'created',)", 'object_name': 'Interface'}, |
310 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
311 | + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
312 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
313 | + 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.StaticIPAddress']", 'null': 'True', 'blank': 'True'}), |
314 | + 'ipv4_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), |
315 | + 'ipv6_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), |
316 | + 'mac_address': ('maasserver.fields.MACAddressField', [], {'null': 'True', 'blank': 'True'}), |
317 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
318 | + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'null': 'True', 'blank': 'True'}), |
319 | + 'params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), |
320 | + 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.Interface']", 'null': 'True', 'through': u"orm['maasserver.InterfaceRelationship']", 'blank': 'True'}), |
321 | + 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}), |
322 | + 'type': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
323 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
324 | + 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'}) |
325 | + }, |
326 | + u'maasserver.interfacerelationship': { |
327 | + 'Meta': {'object_name': 'InterfaceRelationship'}, |
328 | + 'child': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'parent_relationships'", 'to': u"orm['maasserver.Interface']"}), |
329 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
330 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
331 | + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'children_relationships'", 'to': u"orm['maasserver.Interface']"}), |
332 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
333 | + }, |
334 | + u'maasserver.largefile': { |
335 | + 'Meta': {'object_name': 'LargeFile'}, |
336 | + 'content': ('maasserver.fields.LargeObjectField', [], {}), |
337 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
338 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
339 | + 'sha256': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), |
340 | + 'total_size': ('django.db.models.fields.BigIntegerField', [], {}), |
341 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
342 | + }, |
343 | + u'maasserver.licensekey': { |
344 | + 'Meta': {'unique_together': "((u'osystem', u'distro_series'),)", 'object_name': 'LicenseKey'}, |
345 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
346 | + 'distro_series': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
347 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
348 | + 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
349 | + 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
350 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
351 | + }, |
352 | + u'maasserver.node': { |
353 | + 'Meta': {'object_name': 'Node'}, |
354 | + 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}), |
355 | + 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), |
356 | + 'bios_boot_method': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), |
357 | + 'block_poweroff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
358 | + 'boot_cluster_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
359 | + 'boot_disk': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.PhysicalBlockDevice']", 'blank': 'True', 'null': 'True'}), |
360 | + 'boot_interface': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.Interface']", 'blank': 'True', 'null': 'True'}), |
361 | + 'boot_type': ('django.db.models.fields.CharField', [], {'default': "u'fastpath'", 'max_length': '20'}), |
362 | + 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
363 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
364 | + 'disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
365 | + 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), |
366 | + 'enable_ssh': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
367 | + 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
368 | + 'error_description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}), |
369 | + 'gateway_link_ipv4': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.StaticIPAddress']", 'blank': 'True', 'null': 'True'}), |
370 | + 'gateway_link_ipv6': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.StaticIPAddress']", 'blank': 'True', 'null': 'True'}), |
371 | + 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}), |
372 | + 'hwe_kernel': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), |
373 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
374 | + 'installable': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), |
375 | + 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), |
376 | + 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
377 | + 'min_hwe_kernel': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), |
378 | + 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
379 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}), |
380 | + 'osystem': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), |
381 | + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}), |
382 | + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "u'children'", 'null': 'True', 'blank': 'True', 'to': u"orm['maasserver.Node']"}), |
383 | + 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'max_length': '32768', 'blank': 'True'}), |
384 | + 'power_state': ('django.db.models.fields.CharField', [], {'default': "u'unknown'", 'max_length': '10'}), |
385 | + 'power_state_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), |
386 | + 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}), |
387 | + 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}), |
388 | + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}), |
389 | + 'swap_size': ('django.db.models.fields.BigIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), |
390 | + 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-3ba0c5fe-5bb3-11e5-9f58-7c7a9140484f'", 'unique': 'True', 'max_length': '41'}), |
391 | + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}), |
392 | + 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}), |
393 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
394 | + 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'}) |
395 | + }, |
396 | + u'maasserver.nodegroup': { |
397 | + 'Meta': {'object_name': 'NodeGroup'}, |
398 | + 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}), |
399 | + 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}), |
400 | + 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}), |
401 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
402 | + 'default_disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
403 | + 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
404 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
405 | + 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
406 | + 'name': ('maasserver.models.nodegroup.DomainNameField', [], {'max_length': '80', 'blank': 'True'}), |
407 | + 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), |
408 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
409 | + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) |
410 | + }, |
411 | + u'maasserver.nodegroupinterface': { |
412 | + 'Meta': {'unique_together': "((u'nodegroup', u'name'),)", 'object_name': 'NodeGroupInterface'}, |
413 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
414 | + 'foreign_dhcp_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
415 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
416 | + 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
417 | + 'ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}), |
418 | + 'ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
419 | + 'ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
420 | + 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
421 | + 'name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
422 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), |
423 | + 'static_ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
424 | + 'static_ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
425 | + 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'}), |
426 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
427 | + 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'}) |
428 | + }, |
429 | + u'maasserver.partition': { |
430 | + 'Meta': {'object_name': 'Partition'}, |
431 | + 'bootable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
432 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
433 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
434 | + 'partition_table': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'partitions'", 'to': u"orm['maasserver.PartitionTable']"}), |
435 | + 'size': ('django.db.models.fields.BigIntegerField', [], {}), |
436 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
437 | + 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '36', 'unique': 'True', 'null': 'True', 'blank': 'True'}) |
438 | + }, |
439 | + u'maasserver.partitiontable': { |
440 | + 'Meta': {'object_name': 'PartitionTable'}, |
441 | + 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']"}), |
442 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
443 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
444 | + 'table_type': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '20'}), |
445 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
446 | + }, |
447 | + u'maasserver.physicalblockdevice': { |
448 | + 'Meta': {'ordering': "[u'id']", 'object_name': 'PhysicalBlockDevice', '_ormbases': [u'maasserver.BlockDevice']}, |
449 | + u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}), |
450 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
451 | + 'serial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) |
452 | + }, |
453 | + u'maasserver.space': { |
454 | + 'Meta': {'object_name': 'Space'}, |
455 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
456 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
457 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), |
458 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
459 | + }, |
460 | + u'maasserver.sshkey': { |
461 | + 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'}, |
462 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
463 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
464 | + 'key': ('django.db.models.fields.TextField', [], {}), |
465 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
466 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) |
467 | + }, |
468 | + u'maasserver.sslkey': { |
469 | + 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSLKey'}, |
470 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
471 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
472 | + 'key': ('django.db.models.fields.TextField', [], {}), |
473 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
474 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) |
475 | + }, |
476 | + u'maasserver.staticipaddress': { |
477 | + 'Meta': {'object_name': 'StaticIPAddress'}, |
478 | + 'alloc_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
479 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
480 | + 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}), |
481 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
482 | + 'ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}), |
483 | + 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'blank': 'True'}), |
484 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
485 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) |
486 | + }, |
487 | + u'maasserver.subnet': { |
488 | + 'Meta': {'unique_together': "((u'name', u'space'),)", 'object_name': 'Subnet'}, |
489 | + 'cidr': ('maasserver.fields.CIDRField', [], {'unique': 'True'}), |
490 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
491 | + 'dns_servers': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), |
492 | + 'gateway_ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), |
493 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
494 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
495 | + 'space': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Space']", 'on_delete': 'models.PROTECT'}), |
496 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
497 | + 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'}) |
498 | + }, |
499 | + u'maasserver.tag': { |
500 | + 'Meta': {'object_name': 'Tag'}, |
501 | + 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
502 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
503 | + 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
504 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
505 | + 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), |
506 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), |
507 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
508 | + }, |
509 | + u'maasserver.userprofile': { |
510 | + 'Meta': {'object_name': 'UserProfile'}, |
511 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
512 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'}) |
513 | + }, |
514 | + u'maasserver.virtualblockdevice': { |
515 | + 'Meta': {'ordering': "[u'id']", 'object_name': 'VirtualBlockDevice', '_ormbases': [u'maasserver.BlockDevice']}, |
516 | + u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}), |
517 | + 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'virtual_devices'", 'to': u"orm['maasserver.FilesystemGroup']"}), |
518 | + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) |
519 | + }, |
520 | + u'maasserver.vlan': { |
521 | + 'Meta': {'unique_together': "((u'vid', u'fabric'), (u'name', u'fabric'))", 'object_name': 'VLAN'}, |
522 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
523 | + 'fabric': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Fabric']"}), |
524 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
525 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}), |
526 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
527 | + 'vid': ('django.db.models.fields.IntegerField', [], {}) |
528 | + }, |
529 | + u'maasserver.zone': { |
530 | + 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'}, |
531 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
532 | + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
533 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
534 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), |
535 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
536 | + }, |
537 | + u'piston.consumer': { |
538 | + 'Meta': {'object_name': 'Consumer'}, |
539 | + 'description': ('django.db.models.fields.TextField', [], {}), |
540 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
541 | + 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), |
542 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
543 | + 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), |
544 | + 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}), |
545 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"}) |
546 | + }, |
547 | + u'piston.token': { |
548 | + 'Meta': {'object_name': 'Token'}, |
549 | + 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
550 | + 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
551 | + 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}), |
552 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
553 | + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
554 | + 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), |
555 | + 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), |
556 | + 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1442326105L'}), |
557 | + 'token_type': ('django.db.models.fields.IntegerField', [], {}), |
558 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}), |
559 | + 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) |
560 | + } |
561 | + } |
562 | + |
563 | + complete_apps = ['maasserver'] |
564 | \ No newline at end of file |
565 | |
566 | === modified file 'src/maasserver/models/node.py' |
567 | --- src/maasserver/models/node.py 2015-09-14 19:31:45 +0000 |
568 | +++ src/maasserver/models/node.py 2015-09-15 14:12:24 +0000 |
569 | @@ -407,6 +407,12 @@ |
570 | :ivar nodegroup: The `NodeGroup` this `Node` belongs to. |
571 | :ivar tags: The list of :class:`Tag`s associated with this `Node`. |
572 | :ivar objects: The :class:`NodeManager`. |
573 | + :ivar enable_ssh: An optional flag to indicate if this node can have |
574 | + ssh enabled during commissioning, allowing the user to ssh into the |
575 | + machine's commissioning environment using the user's SSH key. |
576 | + :ivar block_poweroff: An optional flag to indicate if this node needs to |
577 | + can be prevented from being powered off automatically after the |
578 | + commissioning has finished. |
579 | |
580 | """ |
581 | |
582 | @@ -572,6 +578,12 @@ |
583 | # 'devices' are all the non-installable nodes. |
584 | devices = DeviceManager() |
585 | |
586 | + # Used to determine whether to: |
587 | + # 1. Import the SSH Key during commissioning. |
588 | + # 2. Block the automatic power off during commissioning. |
589 | + enable_ssh = BooleanField(default=False) |
590 | + block_poweroff = BooleanField(default=False) |
591 | + |
592 | def __unicode__(self): |
593 | if self.hostname: |
594 | return "%s (%s)" % (self.system_id, self.fqdn) |
595 | @@ -900,6 +912,18 @@ |
596 | self.start_commissioning(user) |
597 | return self |
598 | |
599 | + def set_commissioning_parameters(self, enable_ssh=False, |
600 | + block_poweroff=False): |
601 | + """Set the commissioning parameters. |
602 | + |
603 | + This sets the parameters to: |
604 | + enable_ssh - Enable SSH during commissioning. |
605 | + block_poweroff - Blocks the automatic poweroff after commisioning. |
606 | + """ |
607 | + self.enable_ssh = enable_ssh |
608 | + self.block_poweroff = block_poweroff |
609 | + self.save() |
610 | + |
611 | @transactional |
612 | def start_commissioning(self, user): |
613 | """Install OS and self-test a new node. |
614 | @@ -925,6 +949,7 @@ |
615 | # case the power action fails. |
616 | old_status = self.status |
617 | self.status = NODE_STATUS.COMMISSIONING |
618 | + self.owner = user |
619 | self.save() |
620 | |
621 | # Prepare a transition monitor for later. |
622 | @@ -1038,6 +1063,9 @@ |
623 | # exceptions arising synchronously, and chain callbacks to the |
624 | # Deferred it returns for the asynchronous (post-commit) bits. |
625 | stopping = self.stop(user) |
626 | + if self.owner is not None: |
627 | + self.owner = None |
628 | + self.save() |
629 | except Exception as error: |
630 | maaslog.error( |
631 | "%s: Error when aborting commissioning: %s", |
632 | |
633 | === modified file 'src/maasserver/models/tests/test_node.py' |
634 | --- src/maasserver/models/tests/test_node.py 2015-09-14 19:31:45 +0000 |
635 | +++ src/maasserver/models/tests/test_node.py 2015-09-15 14:12:24 +0000 |
636 | @@ -1574,6 +1574,43 @@ |
637 | NodeStateViolation, node.abort_commissioning, |
638 | factory.make_admin()) |
639 | |
640 | + def test_start_commissioning_sets_owner(self): |
641 | + node = factory.make_Node( |
642 | + status=NODE_STATUS.NEW, power_type='ether_wake', |
643 | + enable_ssh=True) |
644 | + node_start = self.patch(node, 'start') |
645 | + # Return a post-commit hook from Node.start(). |
646 | + node_start.side_effect = lambda user, user_data: post_commit() |
647 | + admin = factory.make_admin() |
648 | + node.start_commissioning(admin) |
649 | + post_commit_hooks.reset() # Ignore these for now. |
650 | + node = reload_object(node) |
651 | + expected_attrs = { |
652 | + 'status': NODE_STATUS.COMMISSIONING, |
653 | + 'owner': admin, |
654 | + } |
655 | + self.expectThat(node.owner, Equals(admin)) |
656 | + self.assertAttributes(node, expected_attrs) |
657 | + |
658 | + def test_abort_commissioning_unsets_owner(self): |
659 | + node = factory.make_Node( |
660 | + status=NODE_STATUS.COMMISSIONING, power_type='virsh', |
661 | + enable_ssh=True) |
662 | + admin = factory.make_admin() |
663 | + |
664 | + node_stop = self.patch(node, 'stop') |
665 | + # Return a post-commit hook from Node.stop(). |
666 | + node_stop.side_effect = lambda user: post_commit() |
667 | + self.patch(Node, "_set_status") |
668 | + |
669 | + with post_commit_hooks: |
670 | + node.abort_commissioning(admin) |
671 | + |
672 | + self.assertThat(node_stop, MockCalledOnceWith(admin)) |
673 | + self.assertThat(node._set_status, MockCalledOnceWith( |
674 | + node.system_id, status=NODE_STATUS.NEW)) |
675 | + self.assertThat(node.owner, Is(None)) |
676 | + |
677 | def test_full_clean_logs_node_status_transition(self): |
678 | node = factory.make_Node( |
679 | status=NODE_STATUS.DEPLOYING, owner=factory.make_User()) |
680 | |
681 | === modified file 'src/maasserver/tests/test_preseed.py' |
682 | --- src/maasserver/tests/test_preseed.py 2015-09-10 23:27:25 +0000 |
683 | +++ src/maasserver/tests/test_preseed.py 2015-09-15 14:12:24 +0000 |
684 | @@ -673,7 +673,7 @@ |
685 | reporter = self.load_reporter(preseeds) |
686 | self.assertIsInstance(reporter, dict) |
687 | if curtin_supports_webhook_events(): |
688 | - self.assertEqual(['reporting'], list(reporter.keys())) |
689 | + self.assertEqual(['reporting', 'install'], list(reporter.keys())) |
690 | else: |
691 | self.assertEqual(['reporter'], list(reporter.keys())) |
692 | |
693 | |
694 | === modified file 'src/maasserver/websockets/handlers/device.py' |
695 | --- src/maasserver/websockets/handlers/device.py 2015-09-14 01:43:41 +0000 |
696 | +++ src/maasserver/websockets/handlers/device.py 2015-09-15 14:12:24 +0000 |
697 | @@ -151,6 +151,8 @@ |
698 | "hwe_kernel", |
699 | "gateway_link_ipv4", |
700 | "gateway_link_ipv6", |
701 | + "block_poweroff", |
702 | + "enable_ssh", |
703 | ] |
704 | list_fields = [ |
705 | "system_id", |
706 | |
707 | === modified file 'src/maasserver/websockets/handlers/node.py' |
708 | --- src/maasserver/websockets/handlers/node.py 2015-09-14 01:43:41 +0000 |
709 | +++ src/maasserver/websockets/handlers/node.py 2015-09-15 14:12:24 +0000 |
710 | @@ -109,6 +109,8 @@ |
711 | "power_state_updated", |
712 | "gateway_link_ipv4", |
713 | "gateway_link_ipv6", |
714 | + "block_poweroff", |
715 | + "enable_ssh", |
716 | ] |
717 | list_fields = [ |
718 | "system_id", |
719 | |
720 | === modified file 'src/metadataserver/api.py' |
721 | --- src/metadataserver/api.py 2015-09-09 18:52:24 +0000 |
722 | +++ src/metadataserver/api.py 2015-09-15 14:12:24 +0000 |
723 | @@ -599,10 +599,13 @@ |
724 | # attribute. |
725 | if item is None or len(item) == 0: |
726 | fields = list(self.fields) |
727 | + commissioning_without_ssh = ( |
728 | + node.status == NODE_STATUS.COMMISSIONING and |
729 | + not node.enable_ssh) |
730 | # Add public-keys to the list of attributes, if the |
731 | # node has registered SSH keys. |
732 | keys = SSHKey.objects.get_keys_for_user(user=node.owner) |
733 | - if not keys: |
734 | + if not keys or commissioning_without_ssh: |
735 | fields.remove('public-keys') |
736 | return make_list_response(sorted(fields)) |
737 | |
738 | |
739 | === modified file 'src/metadataserver/tests/test_api.py' |
740 | --- src/metadataserver/tests/test_api.py 2015-09-10 00:22:26 +0000 |
741 | +++ src/metadataserver/tests/test_api.py 2015-09-15 14:12:24 +0000 |
742 | @@ -332,6 +332,28 @@ |
743 | self.assertNotIn( |
744 | 'public-keys', response.content.decode('ascii').split('\n')) |
745 | |
746 | + def test_public_keys_not_listed_for_comm_node_with_ssh_disabled(self): |
747 | + user, _ = factory.make_user_with_keys(n_keys=2, username='my-user') |
748 | + node = factory.make_Node( |
749 | + owner=user, status=NODE_STATUS.COMMISSIONING, enable_ssh=False) |
750 | + view_name = self.get_metadata_name('-meta-data') |
751 | + url = reverse(view_name, args=['latest', '']) |
752 | + client = make_node_client(node=node) |
753 | + response = client.get(url) |
754 | + self.assertNotIn( |
755 | + 'public-keys', response.content.decode('ascii').split('\n')) |
756 | + |
757 | + def test_public_keys_listed_for_comm_node_with_ssh_enabled(self): |
758 | + user, _ = factory.make_user_with_keys(n_keys=2, username='my-user') |
759 | + node = factory.make_Node( |
760 | + owner=user, status=NODE_STATUS.COMMISSIONING, enable_ssh=True) |
761 | + view_name = self.get_metadata_name('-meta-data') |
762 | + url = reverse(view_name, args=['latest', '']) |
763 | + client = make_node_client(node=node) |
764 | + response = client.get(url) |
765 | + self.assertIn( |
766 | + 'public-keys', response.content.decode('ascii').split('\n')) |
767 | + |
768 | def test_public_keys_listed_for_node_with_public_keys(self): |
769 | user, _ = factory.make_user_with_keys(n_keys=2, username='my-user') |
770 | node = factory.make_Node(owner=user) |
This is still needs more work.