Merge lp:~rvb/maas/netboot-allocated into lp:~maas-committers/maas/trunk

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 1621
Proposed branch: lp:~rvb/maas/netboot-allocated
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 227 lines (+223/-0)
1 file modified
src/maasserver/migrations/0056_netboot_off_for_allocated_nodes.py (+223/-0)
To merge this branch: bzr merge lp:~rvb/maas/netboot-allocated
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Gavin Panella (community) Approve
Review via email: mp+185817@code.launchpad.net

Commit message

Set node.netboot to False for allocated nodes.

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

I could have sworn we'd already fixed this! Anyway, cool.

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

On Monday 16 Sep 2013 14:36:29 you wrote:
> + allocated_nodes = orm['maasserver.node'].objects.filter(
> + status=NODE_STATUS.ALLOCATED, netboot=True)
> + # Set netboot=False on these nodes.
> + allocated_nodes.update(netboot=False)

I'm not entirely happy with this because it's possible to have allocated nodes
that need netboot=True if they have not started and finished installing.

Didn't we discuss changing the existing migration so the field defaults to
False? People that have already applied the migration won't care as they
already have a problem that needs fixing in a different way.

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

> On Monday 16 Sep 2013 14:36:29 you wrote:
> > + allocated_nodes = orm['maasserver.node'].objects.filter(
> > + status=NODE_STATUS.ALLOCATED, netboot=True)
> > + # Set netboot=False on these nodes.
> > + allocated_nodes.update(netboot=False)
>
> I'm not entirely happy with this because it's possible to have allocated nodes
> that need netboot=True if they have not started and finished installing.

I think the consensus was that it was better to accidentally set netboot to True (with this migration) to an installing node than to set netboot to False (with migration number 10) on a deployed node. Also, a very good point was made: it's pretty improbable that one would want to upgrade the package while installing a node.

> Didn't we discuss changing the existing migration so the field defaults to
> False? People that have already applied the migration won't care as they
> already have a problem that needs fixing in a different way.

I think changing the default value in the migration would be more dangerous.

We need another migration because, like you said, people who have already applied migration 10 need another migration.

Now, I've got a question for you: do we want to backport this to 1.2? This is a bit tricky because, as you know, migrations must be applied in order so this means we will have to back all the migrations (I think there is 6 or 7 of them). But migrations should be pretty isolated (tiny model change + migration) so it's doable.

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

On 17/09/13 17:21, Raphaël Badin wrote:
>> On Monday 16 Sep 2013 14:36:29 you wrote:
>>> + allocated_nodes = orm['maasserver.node'].objects.filter(
>>> + status=NODE_STATUS.ALLOCATED, netboot=True)
>>> + # Set netboot=False on these nodes.
>>> + allocated_nodes.update(netboot=False)
>>
>> I'm not entirely happy with this because it's possible to have allocated nodes
>> that need netboot=True if they have not started and finished installing.
>
> I think the consensus was that it was better to accidentally set netboot to True (with this migration) to an installing node than to set netboot to False (with migration number 10) on a deployed node. Also, a very good point was made: it's pretty improbable that one would want to upgrade the package while installing a node.

I am confused. This migration is setting allocated nodes to False. Or
is that what you meant?

>
>> Didn't we discuss changing the existing migration so the field defaults to
>> False? People that have already applied the migration won't care as they
>> already have a problem that needs fixing in a different way.
>
> I think changing the default value in the migration would be more dangerous.
>
> We need another migration because, like you said, people who have already applied migration 10 need another migration.

I was actually implying that we don't need to worry about the people who
already applied it, since they will have needed to fix their data already.

For people who have not applied it yet, why do you think it would be
dangerous to do this?

> Now, I've got a question for you: do we want to backport this to 1.2? This is a bit tricky because, as you know, migrations must be applied in order so this means we will have to back all the migrations (I think there is 6 or 7 of them). But migrations should be pretty isolated (tiny model change + migration) so it's doable.

No I don't think so - same reason. Plus, it's tricky as you say.

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

> On 17/09/13 17:21, Raphaël Badin wrote:
> >> On Monday 16 Sep 2013 14:36:29 you wrote:
> >>> + allocated_nodes = orm['maasserver.node'].objects.filter(
> >>> + status=NODE_STATUS.ALLOCATED, netboot=True)
> >>> + # Set netboot=False on these nodes.
> >>> + allocated_nodes.update(netboot=False)
> >>
> >> I'm not entirely happy with this because it's possible to have allocated
> nodes
> >> that need netboot=True if they have not started and finished installing.
> >
> > I think the consensus was that it was better to accidentally set netboot to
> True (with this migration) to an installing node than to set netboot to False
> (with migration number 10) on a deployed node. Also, a very good point was
> made: it's pretty improbable that one would want to upgrade the package while
> installing a node.
>
> I am confused. This migration is setting allocated nodes to False. Or
> is that what you meant?

Sorry, I got mixed up. What I wanted to say is that we thought it would be less problematic to set netboot to False by accident (with this migration) on an installing node rather than to keep it the way it is now (when an installed node can have its netboot set to True by migration #10).

> >
> >> Didn't we discuss changing the existing migration so the field defaults to
> >> False? People that have already applied the migration won't care as they
> >> already have a problem that needs fixing in a different way.
> >
> > I think changing the default value in the migration would be more dangerous.
> >
> > We need another migration because, like you said, people who have already
> applied migration 10 need another migration.
>
> I was actually implying that we don't need to worry about the people who
> already applied it, since they will have needed to fix their data already.
>
> For people who have not applied it yet, why do you think it would be
> dangerous to do this?

For people who have applied the migration, there is little we can do (apart from backporting all the migrations up to the new one).

Like you said, fixing the migration #10 (with code similar to the one in this branch) could help people who haven't applied the migration yet. That fix could be backported to 1.2 and 1.3.

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

On Tuesday 17 Sep 2013 09:07:11 Raphaël Badin wrote:
> > On 17/09/13 17:21, Raphaël Badin wrote:
> > >> On Monday 16 Sep 2013 14:36:29 you wrote:
> > >>> + allocated_nodes = orm['maasserver.node'].objects.filter(
> > >>> + status=NODE_STATUS.ALLOCATED, netboot=True)
> > >>> + # Set netboot=False on these nodes.
> > >>> + allocated_nodes.update(netboot=False)
> > >>
> > >> I'm not entirely happy with this because it's possible to have
> > >> allocated
> >
> > nodes
> >
> > >> that need netboot=True if they have not started and finished
> > >> installing.
> > >
> > > I think the consensus was that it was better to accidentally set netboot
> > > to
> >
> > True (with this migration) to an installing node than to set netboot to
> > False (with migration number 10) on a deployed node. Also, a very good
> > point was made: it's pretty improbable that one would want to upgrade the
> > package while installing a node.
> >
> > I am confused. This migration is setting allocated nodes to False. Or
> > is that what you meant?
>
> Sorry, I got mixed up. What I wanted to say is that we thought it would be
> less problematic to set netboot to False by accident (with this migration)
> on an installing node rather than to keep it the way it is now (when an
> installed node can have its netboot set to True by migration #10).

Right - assuming an upgrade is not done when a node is installing. It's
coming back to me now :) (Sorry, Lyme brain)

> > >> Didn't we discuss changing the existing migration so the field defaults
> > >> to
> > >> False? People that have already applied the migration won't care as
> > >> they
> > >> already have a problem that needs fixing in a different way.
> > >
> > > I think changing the default value in the migration would be more
> > > dangerous.
> > >
> > > We need another migration because, like you said, people who have
> > > already
> >
> > applied migration 10 need another migration.
> >
> > I was actually implying that we don't need to worry about the people who
> > already applied it, since they will have needed to fix their data already.
> >
> > For people who have not applied it yet, why do you think it would be
> > dangerous to do this?
>
> For people who have applied the migration, there is little we can do (apart
> from backporting all the migrations up to the new one).
>
> Like you said, fixing the migration #10 (with code similar to the one in
> this branch) could help people who haven't applied the migration yet. That
> fix could be backported to 1.2 and 1.3.

Right so this is my theory - people who've not applied the migration yet would
benefit from us fixing the migration. People who *have* applied it won't
benefit from anything we do, it needs admin action to re-install the node or
DB surgery.

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

[...]

>
> Right - assuming an upgrade is not done when a node is installing. It's
> coming back to me now :) (Sorry, Lyme brain)
>

[...]

>
> Right so this is my theory - people who've not applied the migration yet would
> benefit from us fixing the migration. People who *have* applied it won't
> benefit from anything we do, it needs admin action to re-install the node or
> DB surgery.

Yes, so the summary is:
- The situation of the people who have run migration #10 but haven't rebooted a node yet will be solved by this migration (migration #56).
- People who have run migration #10 and want to reboot an allocated node need to fix the netboot param themselves.
- The situation of the people who haven't run migration #10 will be solved by the upcoming fix I'll do to migration #10. That fix can be backported to 1.2 and 1.3.

All good Julian? (Your vote "Needs info" is still set.)

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

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

 review: approve
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlI5X2MACgkQWhGlTF8G/HdQ6gCfb6i77MyYhgInoNrO9eBKc+I7
z98AoIXgfkOR8ttQDz56qOT/7RktWGfy
=lQGL
-----END PGP SIGNATURE-----

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'src/maasserver/migrations/0056_netboot_off_for_allocated_nodes.py'
2--- src/maasserver/migrations/0056_netboot_off_for_allocated_nodes.py 1970-01-01 00:00:00 +0000
3+++ src/maasserver/migrations/0056_netboot_off_for_allocated_nodes.py 2013-09-16 14:32:22 +0000
4@@ -0,0 +1,223 @@
5+# -*- coding: utf-8 -*-
6+import datetime
7+
8+from django.db import models
9+from maasserver.enum import NODE_STATUS
10+from south.db import db
11+from south.v2 import DataMigration
12+
13+
14+class Migration(DataMigration):
15+
16+ def forwards(self, orm):
17+ # Fix a side-effect of migration #10 which introduced 'netboot'
18+ # on node with a default value of True without changing it to
19+ # False for the allocated nodes.
20+ # Find all the allocated nodes with netboot=True.
21+ allocated_nodes = orm['maasserver.node'].objects.filter(
22+ status=NODE_STATUS.ALLOCATED, netboot=True)
23+ # Set netboot=False on these nodes.
24+ allocated_nodes.update(netboot=False)
25+
26+ def backwards(self, orm):
27+ "Write your backwards methods here."
28+
29+ models = {
30+ u'auth.group': {
31+ 'Meta': {'object_name': 'Group'},
32+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
33+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
34+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
35+ },
36+ u'auth.permission': {
37+ 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
38+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
39+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
40+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
41+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
42+ },
43+ u'auth.user': {
44+ 'Meta': {'object_name': 'User'},
45+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
46+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
47+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
48+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
49+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
50+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
51+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
52+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
53+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
54+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
55+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
56+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
57+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
58+ },
59+ u'contenttypes.contenttype': {
60+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
61+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
62+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
63+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
64+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
65+ },
66+ u'maasserver.bootimage': {
67+ 'Meta': {'unique_together': "((u'nodegroup', u'architecture', u'subarchitecture', u'release', u'purpose'),)", 'object_name': 'BootImage'},
68+ 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
69+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
70+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
71+ 'purpose': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
72+ 'release': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
73+ 'subarchitecture': ('django.db.models.fields.CharField', [], {'max_length': '255'})
74+ },
75+ u'maasserver.componenterror': {
76+ 'Meta': {'object_name': 'ComponentError'},
77+ 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
78+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
79+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
80+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
81+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
82+ },
83+ u'maasserver.config': {
84+ 'Meta': {'object_name': 'Config'},
85+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
86+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
87+ 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'})
88+ },
89+ u'maasserver.dhcplease': {
90+ 'Meta': {'object_name': 'DHCPLease'},
91+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
92+ 'ip': ('django.db.models.fields.IPAddressField', [], {'unique': 'True', 'max_length': '15'}),
93+ 'mac': ('maasserver.fields.MACAddressField', [], {}),
94+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"})
95+ },
96+ u'maasserver.downloadprogress': {
97+ 'Meta': {'object_name': 'DownloadProgress'},
98+ 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
99+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
100+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}),
101+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
102+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
103+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
104+ 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
105+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
106+ },
107+ u'maasserver.filestorage': {
108+ 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'},
109+ 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}),
110+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
111+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
112+ 'key': ('django.db.models.fields.CharField', [], {'default': "u'3793e3e2-1eca-11e3-864a-9c4e363b1c94'", 'unique': 'True', 'max_length': '36'}),
113+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
114+ },
115+ u'maasserver.macaddress': {
116+ 'Meta': {'object_name': 'MACAddress'},
117+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
118+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
119+ 'mac_address': ('maasserver.fields.MACAddressField', [], {'unique': 'True'}),
120+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
121+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
122+ },
123+ u'maasserver.node': {
124+ 'Meta': {'object_name': 'Node'},
125+ 'after_commissioning_action': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
126+ 'architecture': ('django.db.models.fields.CharField', [], {'default': "u'i386/generic'", 'max_length': '31'}),
127+ 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
128+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
129+ 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'null': 'True', 'blank': 'True'}),
130+ 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
131+ 'hardware_details': ('maasserver.fields.XMLField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
132+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}),
133+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
134+ 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
135+ 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
136+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
137+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
138+ 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
139+ 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}),
140+ 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}),
141+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}),
142+ 'storage': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
143+ 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-3794d392-1eca-11e3-864a-9c4e363b1c94'", 'unique': 'True', 'max_length': '41'}),
144+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}),
145+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}),
146+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
147+ },
148+ u'maasserver.nodegroup': {
149+ 'Meta': {'object_name': 'NodeGroup'},
150+ 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
151+ 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}),
152+ 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}),
153+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
154+ 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
155+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
156+ 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
157+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
158+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
159+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
160+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
161+ },
162+ u'maasserver.nodegroupinterface': {
163+ 'Meta': {'unique_together': "((u'nodegroup', u'interface'),)", 'object_name': 'NodeGroupInterface'},
164+ 'broadcast_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
165+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
166+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
167+ 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
168+ 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
169+ 'ip_range_high': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
170+ 'ip_range_low': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
171+ 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
172+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
173+ 'router_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
174+ 'subnet_mask': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
175+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
176+ },
177+ u'maasserver.sshkey': {
178+ 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'},
179+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
180+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
181+ 'key': ('django.db.models.fields.TextField', [], {}),
182+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
183+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
184+ },
185+ u'maasserver.tag': {
186+ 'Meta': {'object_name': 'Tag'},
187+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
188+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
189+ 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
190+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
191+ 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
192+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
193+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
194+ },
195+ u'maasserver.userprofile': {
196+ 'Meta': {'object_name': 'UserProfile'},
197+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
198+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
199+ },
200+ u'piston.consumer': {
201+ 'Meta': {'object_name': 'Consumer'},
202+ 'description': ('django.db.models.fields.TextField', [], {}),
203+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
204+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
205+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
206+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
207+ 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}),
208+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"})
209+ },
210+ u'piston.token': {
211+ 'Meta': {'object_name': 'Token'},
212+ 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
213+ 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
214+ 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}),
215+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
216+ 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
217+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
218+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
219+ 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1379333961L'}),
220+ 'token_type': ('django.db.models.fields.IntegerField', [], {}),
221+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}),
222+ 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'})
223+ }
224+ }
225+
226+ complete_apps = ['maasserver']
227+ symmetrical = True