Merge lp:~rvb/maas/add-network-node-rel into lp:~maas-committers/maas/trunk
- add-network-node-rel
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Raphaël Badin |
Proposed branch: | lp:~rvb/maas/add-network-node-rel |
Merge into: | lp:~maas-committers/maas/trunk |
Prerequisite: | lp:~jtv/maas/vlan-to-network |
Diff against target: |
314 lines (+282/-0) (has conflicts) 3 files modified
src/maasserver/migrations/0066_rename_vlan_add_link_node_network.py (+268/-0) src/maasserver/models/node.py (+3/-0) src/maasserver/models/tests/test_node.py (+11/-0) Contents conflict in src/maasserver/migrations/0066_replace_vlan_with_network.py |
To merge this branch: | bzr merge lp:~rvb/maas/add-network-node-rel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julian Edwards (community) | Approve | ||
Review via email: mp+204506@code.launchpad.net |
Commit message
Add a relation between nodes and networks.
Description of the change
By using a ManyToManyField field, we let Django take care of the creation of the intermediate table.
- 1881. By Raphaël Badin
-
Fold two migrations into one.
Raphaël Badin (rvb) wrote : | # |
> Ok but a small gripe: the number of migrations we have is ridiculous. Can you
> merge this with the previous one of jtv's please? It's not been released to
> Trusty yet so is safe to do so.
Well okay… although this is not buying us much: one migration out of more than 60.
Raphaël Badin (rvb) wrote : | # |
Hum, the MP says it has a conflict and the diff doesn't show one. I'm guessing this is because the pre-req has been merged or something. I'm sick of fighting with bzr so I'll just abandon this MP and start afresh.
Raphaël Badin (rvb) wrote : | # |
This is the new MP: https:/
Julian Edwards (julian-edwards) wrote : | # |
On Tuesday 04 Feb 2014 09:01:05 you wrote:
> > Ok but a small gripe: the number of migrations we have is ridiculous. Can
> > you merge this with the previous one of jtv's please? It's not been
> > released to Trusty yet so is safe to do so.
>
> Well okay… although this is not buying us much: one migration out of more
> than 60.
It's the principle as much as anything. Installing a package from new results
in a huge set of migrations. I'd really like some sort of normalisation for
this case as well.
Gavin Panella (allenap) wrote : | # |
I feel we could buy ourselves a world of pain by trying to consolidate migrations. It's not really something that improves MAAS over the longer run. Let's live with it and wait to see if South or something else comes up with a decent "skip to the end" solution that we can use without having to maintain it too.
Julian Edwards (julian-edwards) wrote : | # |
On Tuesday 04 Feb 2014 11:40:17 you wrote:
> I feel we could buy ourselves a world of pain by trying to consolidate
> migrations. It's not really something that improves MAAS over the longer
> run. Let's live with it and wait to see if South or something else comes up
> with a decent "skip to the end" solution that we can use without having to
> maintain it too.
This was more of a "let's be a bit more thoughtful about how we do this".
Landing two separate branches that incrementally change a new model isn't too
smart.
Otherwise I agree that messing around trying to force things could be painful.
Unmerged revisions
- 1881. By Raphaël Badin
-
Fold two migrations into one.
- 1880. By Raphaël Badin
-
Add link node <-> network.
Preview Diff
1 | === added file 'src/maasserver/migrations/0066_rename_vlan_add_link_node_network.py' |
2 | --- src/maasserver/migrations/0066_rename_vlan_add_link_node_network.py 1970-01-01 00:00:00 +0000 |
3 | +++ src/maasserver/migrations/0066_rename_vlan_add_link_node_network.py 2014-02-04 09:00:58 +0000 |
4 | @@ -0,0 +1,268 @@ |
5 | +# -*- coding: utf-8 -*- |
6 | +import datetime |
7 | + |
8 | +from django.db import models |
9 | +from south.db import db |
10 | +from south.v2 import SchemaMigration |
11 | + |
12 | + |
13 | +class Migration(SchemaMigration): |
14 | + |
15 | + def forwards(self, orm): |
16 | + # Deleting model 'Vlan' |
17 | + db.delete_table(u'maasserver_vlan') |
18 | + |
19 | + # Adding model 'Network' |
20 | + db.create_table(u'maasserver_network', ( |
21 | + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
22 | + ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), |
23 | + ('ip', self.gf('django.db.models.fields.GenericIPAddressField')(unique=True, max_length=39)), |
24 | + ('netmask', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)), |
25 | + ('vlan_tag', self.gf('django.db.models.fields.PositiveSmallIntegerField')(unique=True)), |
26 | + ('description', self.gf('django.db.models.fields.CharField')(default=u'', max_length=255, blank=True)), |
27 | + )) |
28 | + db.send_create_signal(u'maasserver', ['Network']) |
29 | + |
30 | + # Adding M2M table for field networks on 'Node' |
31 | + db.create_table(u'maasserver_node_networks', ( |
32 | + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), |
33 | + ('node', models.ForeignKey(orm[u'maasserver.node'], null=False)), |
34 | + ('network', models.ForeignKey(orm[u'maasserver.network'], null=False)) |
35 | + )) |
36 | + db.create_unique(u'maasserver_node_networks', ['node_id', 'network_id']) |
37 | + |
38 | + |
39 | + def backwards(self, orm): |
40 | + # Adding model 'Vlan' |
41 | + db.create_table(u'maasserver_vlan', ( |
42 | + ('tag', self.gf('django.db.models.fields.PositiveSmallIntegerField')(unique=True)), |
43 | + ('description', self.gf('django.db.models.fields.CharField')(default=u'', max_length=255, blank=True)), |
44 | + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
45 | + )) |
46 | + db.send_create_signal(u'maasserver', ['Vlan']) |
47 | + |
48 | + # Deleting model 'Network' |
49 | + db.delete_table(u'maasserver_network') |
50 | + |
51 | + # Removing M2M table for field networks on 'Node' |
52 | + db.delete_table('maasserver_node_networks') |
53 | + |
54 | + |
55 | + models = { |
56 | + u'auth.group': { |
57 | + 'Meta': {'object_name': 'Group'}, |
58 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
59 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
60 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
61 | + }, |
62 | + u'auth.permission': { |
63 | + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, |
64 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
65 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), |
66 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
67 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
68 | + }, |
69 | + u'auth.user': { |
70 | + 'Meta': {'object_name': 'User'}, |
71 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
72 | + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}), |
73 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
74 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), |
75 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
76 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
77 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
78 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
79 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
80 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
81 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
82 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), |
83 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
84 | + }, |
85 | + u'contenttypes.contenttype': { |
86 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
87 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
88 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
89 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
90 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
91 | + }, |
92 | + u'maasserver.bootimage': { |
93 | + 'Meta': {'unique_together': "((u'nodegroup', u'architecture', u'subarchitecture', u'release', u'purpose'),)", 'object_name': 'BootImage'}, |
94 | + 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
95 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
96 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), |
97 | + 'purpose': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
98 | + 'release': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
99 | + 'subarchitecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}) |
100 | + }, |
101 | + u'maasserver.componenterror': { |
102 | + 'Meta': {'object_name': 'ComponentError'}, |
103 | + 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}), |
104 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
105 | + 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), |
106 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
107 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
108 | + }, |
109 | + u'maasserver.config': { |
110 | + 'Meta': {'object_name': 'Config'}, |
111 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
112 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
113 | + 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'}) |
114 | + }, |
115 | + u'maasserver.dhcplease': { |
116 | + 'Meta': {'object_name': 'DHCPLease'}, |
117 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
118 | + 'ip': ('django.db.models.fields.IPAddressField', [], {'unique': 'True', 'max_length': '15'}), |
119 | + 'mac': ('maasserver.fields.MACAddressField', [], {}), |
120 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}) |
121 | + }, |
122 | + u'maasserver.downloadprogress': { |
123 | + 'Meta': {'object_name': 'DownloadProgress'}, |
124 | + 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
125 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
126 | + 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}), |
127 | + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
128 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
129 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), |
130 | + 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
131 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
132 | + }, |
133 | + u'maasserver.filestorage': { |
134 | + 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'}, |
135 | + 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}), |
136 | + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
137 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
138 | + 'key': ('django.db.models.fields.CharField', [], {'default': "u'6b10b1a2-8d77-11e3-a34b-9c4e363b1c94'", 'unique': 'True', 'max_length': '36'}), |
139 | + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) |
140 | + }, |
141 | + u'maasserver.macaddress': { |
142 | + 'Meta': {'object_name': 'MACAddress'}, |
143 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
144 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
145 | + 'mac_address': ('maasserver.fields.MACAddressField', [], {'unique': 'True'}), |
146 | + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}), |
147 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
148 | + }, |
149 | + u'maasserver.network': { |
150 | + 'Meta': {'object_name': 'Network'}, |
151 | + 'description': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
152 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
153 | + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}), |
154 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
155 | + 'netmask': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), |
156 | + 'vlan_tag': ('django.db.models.fields.PositiveSmallIntegerField', [], {'unique': 'True'}) |
157 | + }, |
158 | + u'maasserver.node': { |
159 | + 'Meta': {'object_name': 'Node'}, |
160 | + 'after_commissioning_action': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
161 | + 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}), |
162 | + 'architecture': ('django.db.models.fields.CharField', [], {'default': "u'i386/generic'", 'max_length': '31'}), |
163 | + 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
164 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
165 | + 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'null': 'True', 'blank': 'True'}), |
166 | + 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
167 | + 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}), |
168 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
169 | + 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
170 | + 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
171 | + 'networks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Network']", 'symmetrical': 'False', 'blank': 'True'}), |
172 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}), |
173 | + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}), |
174 | + 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), |
175 | + 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}), |
176 | + 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}), |
177 | + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}), |
178 | + 'storage': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
179 | + 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-6b0eab46-8d77-11e3-a34b-9c4e363b1c94'", 'unique': 'True', 'max_length': '41'}), |
180 | + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}), |
181 | + 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}), |
182 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
183 | + 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'}) |
184 | + }, |
185 | + u'maasserver.nodegroup': { |
186 | + 'Meta': {'object_name': 'NodeGroup'}, |
187 | + 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}), |
188 | + 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}), |
189 | + 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}), |
190 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
191 | + 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
192 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
193 | + 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
194 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}), |
195 | + 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
196 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
197 | + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) |
198 | + }, |
199 | + u'maasserver.nodegroupinterface': { |
200 | + 'Meta': {'unique_together': "((u'nodegroup', u'interface'),)", 'object_name': 'NodeGroupInterface'}, |
201 | + 'broadcast_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
202 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
203 | + 'foreign_dhcp_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
204 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
205 | + 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), |
206 | + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), |
207 | + 'ip_range_high': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
208 | + 'ip_range_low': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
209 | + 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
210 | + 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), |
211 | + 'router_ip': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
212 | + 'subnet_mask': ('django.db.models.fields.GenericIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), |
213 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
214 | + }, |
215 | + u'maasserver.sshkey': { |
216 | + 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'}, |
217 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
218 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
219 | + 'key': ('django.db.models.fields.TextField', [], {}), |
220 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}), |
221 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) |
222 | + }, |
223 | + u'maasserver.tag': { |
224 | + 'Meta': {'object_name': 'Tag'}, |
225 | + 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
226 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
227 | + 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
228 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
229 | + 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), |
230 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), |
231 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
232 | + }, |
233 | + u'maasserver.userprofile': { |
234 | + 'Meta': {'object_name': 'UserProfile'}, |
235 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
236 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'}) |
237 | + }, |
238 | + u'maasserver.zone': { |
239 | + 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'}, |
240 | + 'created': ('django.db.models.fields.DateTimeField', [], {}), |
241 | + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), |
242 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
243 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), |
244 | + 'updated': ('django.db.models.fields.DateTimeField', [], {}) |
245 | + }, |
246 | + u'piston.consumer': { |
247 | + 'Meta': {'object_name': 'Consumer'}, |
248 | + 'description': ('django.db.models.fields.TextField', [], {}), |
249 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
250 | + 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), |
251 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
252 | + 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), |
253 | + 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}), |
254 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"}) |
255 | + }, |
256 | + u'piston.token': { |
257 | + 'Meta': {'object_name': 'Token'}, |
258 | + 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
259 | + 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
260 | + 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}), |
261 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
262 | + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
263 | + 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), |
264 | + 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), |
265 | + 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1391502978L'}), |
266 | + 'token_type': ('django.db.models.fields.IntegerField', [], {}), |
267 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}), |
268 | + 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) |
269 | + } |
270 | + } |
271 | + |
272 | + complete_apps = ['maasserver'] |
273 | \ No newline at end of file |
274 | |
275 | === renamed file 'src/maasserver/migrations/0066_replace_vlan_with_network.py' => 'src/maasserver/migrations/0066_replace_vlan_with_network.py.THIS' |
276 | === modified file 'src/maasserver/models/node.py' |
277 | --- src/maasserver/models/node.py 2014-01-31 15:12:20 +0000 |
278 | +++ src/maasserver/models/node.py 2014-02-04 09:00:58 +0000 |
279 | @@ -64,6 +64,7 @@ |
280 | JSONObjectField, |
281 | MAC, |
282 | ) |
283 | +from maasserver.models import Network |
284 | from maasserver.models.cleansave import CleanSave |
285 | from maasserver.models.config import Config |
286 | from maasserver.models.dhcplease import DHCPLease |
287 | @@ -488,6 +489,8 @@ |
288 | |
289 | netboot = BooleanField(default=True) |
290 | |
291 | + networks = ManyToManyField(Network, blank=True) |
292 | + |
293 | # This field can't be null, but we can't enforce that in the |
294 | # database schema because we can only create the default value from |
295 | # a complete schema, after schema migration. We can't use custom |
296 | |
297 | === modified file 'src/maasserver/models/tests/test_node.py' |
298 | --- src/maasserver/models/tests/test_node.py 2014-02-01 05:54:22 +0000 |
299 | +++ src/maasserver/models/tests/test_node.py 2014-02-04 09:00:58 +0000 |
300 | @@ -1166,3 +1166,14 @@ |
301 | node = factory.make_node(netboot=True) |
302 | node.set_netboot(False) |
303 | self.assertFalse(node.netboot) |
304 | + |
305 | + def test_node_not_in_any_network_by_default(self): |
306 | + node = factory.make_node() |
307 | + self.assertItemsEqual([], node.networks.all()) |
308 | + |
309 | + def test_node_can_be_multiple_networks(self): |
310 | + node = factory.make_node() |
311 | + networks = [ |
312 | + factory.make_network() for i in range(3)] |
313 | + node.networks.add(*networks) |
314 | + self.assertItemsEqual(networks, reload_object(node).networks.all()) |
Ok but a small gripe: the number of migrations we have is ridiculous. Can you merge this with the previous one of jtv's please? It's not been released to Trusty yet so is safe to do so.