Merge lp:~blake-rouse/maas/add-osystem-to-node-migration into lp:~maas-committers/maas/trunk

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 2320
Proposed branch: lp:~blake-rouse/maas/add-osystem-to-node-migration
Merge into: lp:~maas-committers/maas/trunk
Prerequisite: lp:~blake-rouse/maas/osystem-registry
Diff against target: 383 lines (+285/-8)
8 files modified
src/maasserver/migrations/0076_add_osystem_to_bootimage.py (+2/-2)
src/maasserver/migrations/0077_remove_null_for_bootsourceselection_release.py (+2/-2)
src/maasserver/migrations/0078_add_osystem_to_node.py (+270/-0)
src/maasserver/models/node.py (+8/-2)
src/maasserver/testing/factory.py (+0/-1)
src/maasserver/testing/osystems.py (+1/-1)
src/provisioningserver/boot/tftppath.py (+1/-0)
src/provisioningserver/driver/tests/test_os_ubuntu.py (+1/-0)
To merge this branch: bzr merge lp:~blake-rouse/maas/add-osystem-to-node-migration
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Jason Hobbs (community) Approve
Review via email: mp+219514@code.launchpad.net

Commit message

Add osystem field to the node model.

Description of the change

This replaces the large merge of add-osystem-to-node, and separates it into 3 different mergers. This is the first one. It contains only the migration of adding osystem to the node model.

Note: osystem was used throughout the code instead of os, as the python os module would conflict throughout the code base.

To post a comment you must log in.
Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

Looks good, just a few comments.

[1]

Be sure to run 'make format',
src/maasserver/migrations/0077_add_osystem_to_node.py gets cleaned up a
bit by it.

[2]

=== added file 'src/maasserver/migrations/0077_add_osystem_to_node.py'
--- src/maasserver/migrations/0077_add_osystem_to_node.py 1970-01-01 00:00:00 +0000
+++ src/maasserver/migrations/0077_add_osystem_to_node.py 2014-05-14 12:45:06 +0000

There is already another 0077 migration, so you'll have to merge and
regenerate this.

[3]

+ def forwards(self, orm):
+ # Adding field 'Node.osystem'
+ db.add_column(u'maasserver_node', 'osystem',
+ self.gf('django.db.models.fields.CharField')(default=u'', max_length=20, null=True, blank=True),
+ keep_default=False)

The max_length for Node's osystem field (20) doesn't match the max
length for BootImage's osystem field (255). If they're holding the
same set of values they should have the same types.

Also, Is there a set of osystem values a Node's osystem value should be
constrained to? Should a node always have an osystem that some BootImage
has, or is there some set they should both be constrained to?

[4]

There should be at least some basic test involving the osystem field.

review: Needs Fixing
Revision history for this message
Blake Rouse (blake-rouse) wrote :

[1,2] Fixed

[3] Using 20 as that was what was chosen by the core team for the release field in BootImages, whether that is the correct thing, idk.

[4] At this current state in the branch the field is not used for testing. This merge requests uses the field and provides test for it. If you would like to review that, :)

https://code.launchpad.net/~blake-rouse/maas/add-osystem-to-node-form-api

Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

[3] Still seems broken to me, but I get now that you're following the same pattern of fields being size 20 in Node and size 255 in BootImages that was there already. I guess this can be fixed later if it turns out to be an issue.

[4] I think we should in general add tests when we add code, but this was a retroactive breakdown, so makes sense.

Thanks!

review: Approve
Revision history for this message
Raphaël Badin (rvb) wrote :

[0]

As Jason pointed out, it's always best to land tests with the code they test. For new models, a basic test is enough. You also might want to add a make_<my_model> utility in the test factory (src/maasserver/testing/factory.py)

[1]

See my inline comment about using null=True on Charfields.

[2]

As Jason pointed out, don't forget to run:
$ ./utilities/format-new-and-modified-imports
and
$ make lint
before you submit a branch.

[3]

Please update the Node's docstring.

review: Approve
Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 15/05/14 00:23, Jason Hobbs wrote:
> Be sure to run 'make format',
> src/maasserver/migrations/0077_add_osystem_to_node.py gets cleaned up a
> bit by it.

My personal thought on these is that since they are autogenerated, it
really doesn't matter about formatting.

Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

On Wed, May 14, 2014 at 7:06 PM, Julian Edwards <
<email address hidden>> wrote:

> On 15/05/14 00:23, Jason Hobbs wrote:
> > Be sure to run 'make format',
> > src/maasserver/migrations/0077_add_osystem_to_node.py gets cleaned up a
> > bit by it.
>
> My personal thought on these is that since they are autogenerated, it
> really doesn't matter about formatting.

They'll get reformatted the next time someone else runs 'make format',
which can be annoying. If we don't care about formatting on them, 'make
format' should ignore them I suppose.

Jason

Revision history for this message
Julian Edwards (julian-edwards) wrote :

On 15/05/14 10:57, Jason Hobbs wrote:
> On Wed, May 14, 2014 at 7:06 PM, Julian Edwards <
> <email address hidden>> wrote:
>
>> On 15/05/14 00:23, Jason Hobbs wrote:
>>> Be sure to run 'make format',
>>> src/maasserver/migrations/0077_add_osystem_to_node.py gets cleaned up a
>>> bit by it.
>>
>> My personal thought on these is that since they are autogenerated, it
>> really doesn't matter about formatting.
>
>
> They'll get reformatted the next time someone else runs 'make format',
> which can be annoying. If we don't care about formatting on them, 'make
> format' should ignore them I suppose.
>
> Jason
>

Yes, that's what I was intimating. But someone needs to be bothered to
make that tool ignore migrations.... :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/maasserver/migrations/0076_add_osystem_to_bootimage.py'
--- src/maasserver/migrations/0076_add_osystem_to_bootimage.py 2014-05-02 19:21:43 +0000
+++ src/maasserver/migrations/0076_add_osystem_to_bootimage.py 2014-05-14 15:21:48 +0000
@@ -1,8 +1,8 @@
1from django.db import models
2from south.db import db
1# -*- coding: utf-8 -*-3# -*- coding: utf-8 -*-
2from south.utils import datetime_utils as datetime4from south.utils import datetime_utils as datetime
3from south.db import db
4from south.v2 import SchemaMigration5from south.v2 import SchemaMigration
5from django.db import models
66
77
8class Migration(SchemaMigration):8class Migration(SchemaMigration):
99
=== modified file 'src/maasserver/migrations/0077_remove_null_for_bootsourceselection_release.py'
--- src/maasserver/migrations/0077_remove_null_for_bootsourceselection_release.py 2014-05-14 08:32:13 +0000
+++ src/maasserver/migrations/0077_remove_null_for_bootsourceselection_release.py 2014-05-14 15:21:48 +0000
@@ -1,8 +1,8 @@
1from django.db import models
2from south.db import db
1# -*- coding: utf-8 -*-3# -*- coding: utf-8 -*-
2from south.utils import datetime_utils as datetime4from south.utils import datetime_utils as datetime
3from south.db import db
4from south.v2 import SchemaMigration5from south.v2 import SchemaMigration
5from django.db import models
66
77
8class Migration(SchemaMigration):8class Migration(SchemaMigration):
99
=== added file 'src/maasserver/migrations/0078_add_osystem_to_node.py'
--- src/maasserver/migrations/0078_add_osystem_to_node.py 1970-01-01 00:00:00 +0000
+++ src/maasserver/migrations/0078_add_osystem_to_node.py 2014-05-14 15:21:48 +0000
@@ -0,0 +1,270 @@
1from django.db import models
2from south.db import db
3# -*- coding: utf-8 -*-
4from south.utils import datetime_utils as datetime
5from south.v2 import SchemaMigration
6
7
8class Migration(SchemaMigration):
9
10 def forwards(self, orm):
11 # Adding field 'Node.osystem'
12 db.add_column(u'maasserver_node', 'osystem',
13 self.gf('django.db.models.fields.CharField')(default=u'', max_length=20, blank=True),
14 keep_default=False)
15
16
17 # Changing field 'Node.distro_series'
18 db.alter_column(u'maasserver_node', 'distro_series', self.gf('django.db.models.fields.CharField')(max_length=20))
19
20 def backwards(self, orm):
21 # Deleting field 'Node.osystem'
22 db.delete_column(u'maasserver_node', 'osystem')
23
24
25 # Changing field 'Node.distro_series'
26 db.alter_column(u'maasserver_node', 'distro_series', self.gf('django.db.models.fields.CharField')(max_length=20, null=True))
27
28 models = {
29 u'auth.group': {
30 'Meta': {'object_name': 'Group'},
31 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
32 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
33 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
34 },
35 u'auth.permission': {
36 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
37 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
38 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
39 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
40 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
41 },
42 u'auth.user': {
43 'Meta': {'object_name': 'User'},
44 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
45 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
46 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
47 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
48 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
49 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
50 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
51 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
52 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
53 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
54 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
55 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
56 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
57 },
58 u'contenttypes.contenttype': {
59 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
60 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
61 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
62 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
63 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
64 },
65 u'maasserver.bootimage': {
66 'Meta': {'unique_together': "((u'nodegroup', u'osystem', u'architecture', u'subarchitecture', u'release', u'purpose', u'label'),)", 'object_name': 'BootImage'},
67 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
68 'created': ('django.db.models.fields.DateTimeField', [], {}),
69 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
70 'label': ('django.db.models.fields.CharField', [], {'default': "u'release'", 'max_length': '255'}),
71 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
72 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
73 'purpose': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
74 'release': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
75 'subarchitecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
76 'updated': ('django.db.models.fields.DateTimeField', [], {})
77 },
78 u'maasserver.bootsource': {
79 'Meta': {'object_name': 'BootSource'},
80 'cluster': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
81 'created': ('django.db.models.fields.DateTimeField', [], {}),
82 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
83 'keyring_data': ('django.db.models.fields.BinaryField', [], {'blank': 'True'}),
84 'keyring_filename': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}),
85 'updated': ('django.db.models.fields.DateTimeField', [], {}),
86 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
87 },
88 u'maasserver.bootsourceselection': {
89 'Meta': {'object_name': 'BootSourceSelection'},
90 'arches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
91 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}),
92 'created': ('django.db.models.fields.DateTimeField', [], {}),
93 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
94 'labels': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
95 'release': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
96 'subarches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
97 'updated': ('django.db.models.fields.DateTimeField', [], {})
98 },
99 u'maasserver.componenterror': {
100 'Meta': {'object_name': 'ComponentError'},
101 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
102 'created': ('django.db.models.fields.DateTimeField', [], {}),
103 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
104 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
105 'updated': ('django.db.models.fields.DateTimeField', [], {})
106 },
107 u'maasserver.config': {
108 'Meta': {'object_name': 'Config'},
109 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
110 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
111 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'})
112 },
113 u'maasserver.dhcplease': {
114 'Meta': {'object_name': 'DHCPLease'},
115 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
116 'ip': ('django.db.models.fields.IPAddressField', [], {'unique': 'True', 'max_length': '15'}),
117 'mac': ('maasserver.fields.MACAddressField', [], {}),
118 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"})
119 },
120 u'maasserver.downloadprogress': {
121 'Meta': {'object_name': 'DownloadProgress'},
122 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
123 'created': ('django.db.models.fields.DateTimeField', [], {}),
124 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}),
125 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
126 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
127 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
128 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
129 'updated': ('django.db.models.fields.DateTimeField', [], {})
130 },
131 u'maasserver.filestorage': {
132 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'},
133 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}),
134 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
135 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
136 'key': ('django.db.models.fields.CharField', [], {'default': "u'ab43bb24-db7a-11e3-81cc-bcee7b78dc5b'", 'unique': 'True', 'max_length': '36'}),
137 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
138 },
139 u'maasserver.macaddress': {
140 'Meta': {'object_name': 'MACAddress'},
141 'created': ('django.db.models.fields.DateTimeField', [], {}),
142 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
143 'mac_address': ('maasserver.fields.MACAddressField', [], {'unique': 'True'}),
144 'networks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Network']", 'symmetrical': 'False', 'blank': 'True'}),
145 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
146 'updated': ('django.db.models.fields.DateTimeField', [], {})
147 },
148 u'maasserver.network': {
149 'Meta': {'object_name': 'Network'},
150 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
151 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
152 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
153 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
154 'netmask': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
155 'vlan_tag': ('django.db.models.fields.PositiveSmallIntegerField', [], {'unique': 'True', 'null': 'True', 'blank': 'True'})
156 },
157 u'maasserver.node': {
158 'Meta': {'object_name': 'Node'},
159 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
160 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '31'}),
161 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
162 'created': ('django.db.models.fields.DateTimeField', [], {}),
163 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
164 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
165 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}),
166 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
167 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
168 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
169 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
170 'osystem': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
171 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
172 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
173 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}),
174 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}),
175 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}),
176 'storage': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
177 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-ab42b030-db7a-11e3-81cc-bcee7b78dc5b'", 'unique': 'True', 'max_length': '41'}),
178 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}),
179 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}),
180 'updated': ('django.db.models.fields.DateTimeField', [], {}),
181 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'})
182 },
183 u'maasserver.nodegroup': {
184 'Meta': {'object_name': 'NodeGroup'},
185 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
186 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}),
187 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}),
188 'created': ('django.db.models.fields.DateTimeField', [], {}),
189 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
190 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
191 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
192 'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
193 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
194 'updated': ('django.db.models.fields.DateTimeField', [], {}),
195 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
196 },
197 u'maasserver.nodegroupinterface': {
198 'Meta': {'unique_together': "((u'nodegroup', u'interface'),)", 'object_name': 'NodeGroupInterface'},
199 'broadcast_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
200 'created': ('django.db.models.fields.DateTimeField', [], {}),
201 'foreign_dhcp_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
202 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
203 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
204 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
205 'ip_range_high': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
206 'ip_range_low': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
207 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
208 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
209 'router_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
210 'subnet_mask': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
211 'updated': ('django.db.models.fields.DateTimeField', [], {})
212 },
213 u'maasserver.sshkey': {
214 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'},
215 'created': ('django.db.models.fields.DateTimeField', [], {}),
216 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
217 'key': ('django.db.models.fields.TextField', [], {}),
218 'updated': ('django.db.models.fields.DateTimeField', [], {}),
219 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
220 },
221 u'maasserver.tag': {
222 'Meta': {'object_name': 'Tag'},
223 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
224 'created': ('django.db.models.fields.DateTimeField', [], {}),
225 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
226 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
227 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
228 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
229 'updated': ('django.db.models.fields.DateTimeField', [], {})
230 },
231 u'maasserver.userprofile': {
232 'Meta': {'object_name': 'UserProfile'},
233 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
234 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
235 },
236 u'maasserver.zone': {
237 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'},
238 'created': ('django.db.models.fields.DateTimeField', [], {}),
239 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
240 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
241 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
242 'updated': ('django.db.models.fields.DateTimeField', [], {})
243 },
244 u'piston.consumer': {
245 'Meta': {'object_name': 'Consumer'},
246 'description': ('django.db.models.fields.TextField', [], {}),
247 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
248 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
249 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
250 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
251 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}),
252 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"})
253 },
254 u'piston.token': {
255 'Meta': {'object_name': 'Token'},
256 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
257 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
258 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}),
259 u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
260 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
261 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
262 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
263 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1400080565L'}),
264 'token_type': ('django.db.models.fields.IntegerField', [], {}),
265 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}),
266 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'})
267 }
268 }
269
270 complete_apps = ['maasserver']
0271
=== modified file 'src/maasserver/models/node.py'
--- src/maasserver/models/node.py 2014-05-09 06:04:54 +0000
+++ src/maasserver/models/node.py 2014-05-14 15:21:48 +0000
@@ -450,6 +450,10 @@
450 :ivar status: This `Node`'s status. See the vocabulary450 :ivar status: This `Node`'s status. See the vocabulary
451 :class:`NODE_STATUS`.451 :class:`NODE_STATUS`.
452 :ivar owner: This `Node`'s owner if it's in use, None otherwise.452 :ivar owner: This `Node`'s owner if it's in use, None otherwise.
453 :ivar osystem: This `Node`'s booting operating system, if it's blank then
454 the default_osystem will be used.
455 :ivar distro_series: This `Node`'s booting distro series, if
456 it's blank then the default_distro_series will be used.
453 :ivar power_type: The power type that determines how this457 :ivar power_type: The power type that determines how this
454 node will be powered on. Its value must match a power driver template458 node will be powered on. Its value must match a power driver template
455 name.459 name.
@@ -477,9 +481,11 @@
477 owner = ForeignKey(481 owner = ForeignKey(
478 User, default=None, blank=True, null=True, editable=False)482 User, default=None, blank=True, null=True, editable=False)
479483
484 osystem = CharField(
485 max_length=20, blank=True, default='')
486
480 distro_series = CharField(487 distro_series = CharField(
481 max_length=20, choices=DISTRO_SERIES_CHOICES, null=True,488 max_length=20, choices=DISTRO_SERIES_CHOICES, blank=True, default='')
482 blank=True, default='')
483489
484 architecture = CharField(max_length=31, blank=False)490 architecture = CharField(max_length=31, blank=False)
485491
486492
=== modified file 'src/maasserver/testing/factory.py'
--- src/maasserver/testing/factory.py 2014-05-13 18:55:36 +0000
+++ src/maasserver/testing/factory.py 2014-05-14 15:21:48 +0000
@@ -59,7 +59,6 @@
59 NodeCommissionResult,59 NodeCommissionResult,
60 )60 )
61from netaddr import IPAddress61from netaddr import IPAddress
62
63# XXX 2014-05-13 blake-rouse bug=131914362# XXX 2014-05-13 blake-rouse bug=1319143
64# Need to not import directly, use RPC to info from cluster.63# Need to not import directly, use RPC to info from cluster.
65from provisioningserver.driver import OperatingSystemRegistry64from provisioningserver.driver import OperatingSystemRegistry
6665
=== modified file 'src/maasserver/testing/osystems.py'
--- src/maasserver/testing/osystems.py 2014-05-01 19:25:38 +0000
+++ src/maasserver/testing/osystems.py 2014-05-14 15:21:48 +0000
@@ -21,8 +21,8 @@
2121
22from maasserver import forms22from maasserver import forms
23from maasserver.testing.factory import factory23from maasserver.testing.factory import factory
24from provisioningserver.boot.tests.test_tftppath import make_osystem
24from provisioningserver.driver import BOOT_IMAGE_PURPOSE25from provisioningserver.driver import BOOT_IMAGE_PURPOSE
25from provisioningserver.boot.tests.test_tftppath import make_osystem
2626
2727
28def make_osystem_with_releases(testcase, osystem_name=None, releases=None):28def make_osystem_with_releases(testcase, osystem_name=None, releases=None):
2929
=== modified file 'src/provisioningserver/boot/tftppath.py'
--- src/provisioningserver/boot/tftppath.py 2014-05-01 18:54:22 +0000
+++ src/provisioningserver/boot/tftppath.py 2014-05-14 15:21:48 +0000
@@ -27,6 +27,7 @@
2727
28from provisioningserver.driver import OperatingSystemRegistry28from provisioningserver.driver import OperatingSystemRegistry
2929
30
30logger = getLogger(__name__)31logger = getLogger(__name__)
3132
3233
3334
=== modified file 'src/provisioningserver/driver/tests/test_os_ubuntu.py'
--- src/provisioningserver/driver/tests/test_os_ubuntu.py 2014-05-01 19:25:38 +0000
+++ src/provisioningserver/driver/tests/test_os_ubuntu.py 2014-05-14 15:21:48 +0000
@@ -15,6 +15,7 @@
15__all__ = []15__all__ = []
1616
17from itertools import product17from itertools import product
18
18from maastesting.factory import factory19from maastesting.factory import factory
19from maastesting.testcase import MAASTestCase20from maastesting.testcase import MAASTestCase
20from provisioningserver.driver import BOOT_IMAGE_PURPOSE21from provisioningserver.driver import BOOT_IMAGE_PURPOSE