Merge lp:~rvb/maas/refactor-ip-addresses 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: 4050
Proposed branch: lp:~rvb/maas/refactor-ip-addresses
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 588 lines (+540/-2)
4 files modified
src/maasserver/enum.py (+3/-0)
src/maasserver/migrations/0147_add_ip_connections.py (+525/-0)
src/maasserver/models/interface.py (+3/-0)
src/maasserver/models/staticipaddress.py (+9/-2)
To merge this branch: bzr merge lp:~rvb/maas/refactor-ip-addresses
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+263219@code.launchpad.net

Commit message

Implement the last bit of the new networking model:
- Add a link: Interface → IP address
- Add a link: IP address → Subnet
- Allow null IP address in the IP address table: this is for yet unknown DHCP-assigned addresses.

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

I have a few questions, but +1 anyway.

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

Thanks for the review. Answers inline…

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/enum.py'
2--- src/maasserver/enum.py 2015-06-11 14:57:49 +0000
3+++ src/maasserver/enum.py 2015-06-29 11:36:56 +0000
4@@ -234,6 +234,9 @@
5 # leases file.
6 USER_RESERVED = 4
7
8+ # Assigned by a MAAS-managed DHCP server.
9+ DHCP = 5
10+
11
12 class POWER_STATE:
13
14
15=== added file 'src/maasserver/migrations/0147_add_ip_connections.py'
16--- src/maasserver/migrations/0147_add_ip_connections.py 1970-01-01 00:00:00 +0000
17+++ src/maasserver/migrations/0147_add_ip_connections.py 2015-06-29 11:36:56 +0000
18@@ -0,0 +1,525 @@
19+from django.db import models
20+from south.db import db
21+# -*- coding: utf-8 -*-
22+from south.utils import datetime_utils as datetime
23+from south.v2 import SchemaMigration
24+
25+
26+class Migration(SchemaMigration):
27+
28+ def forwards(self, orm):
29+ # Adding field 'StaticIPAddress.subnet'
30+ db.add_column(u'maasserver_staticipaddress', 'subnet',
31+ self.gf('django.db.models.fields.related.ForeignKey')(to=orm['maasserver.Subnet'], null=True, blank=True),
32+ keep_default=False)
33+
34+
35+ # Changing field 'StaticIPAddress.ip'
36+ db.alter_column(u'maasserver_staticipaddress', 'ip', self.gf('maasserver.fields.MAASIPAddressField')(max_length=39, unique=True, null=True))
37+ # Adding M2M table for field ip_addresses on 'Interface'
38+ db.create_table(u'maasserver_interface_ip_addresses', (
39+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
40+ ('interface', models.ForeignKey(orm[u'maasserver.interface'], null=False)),
41+ ('staticipaddress', models.ForeignKey(orm[u'maasserver.staticipaddress'], null=False))
42+ ))
43+ db.create_unique(u'maasserver_interface_ip_addresses', ['interface_id', 'staticipaddress_id'])
44+
45+
46+ def backwards(self, orm):
47+ # Deleting field 'StaticIPAddress.subnet'
48+ db.delete_column(u'maasserver_staticipaddress', 'subnet_id')
49+
50+
51+ # User chose to not deal with backwards NULL issues for 'StaticIPAddress.ip'
52+ raise RuntimeError("Cannot reverse this migration. 'StaticIPAddress.ip' and its values cannot be restored.")
53+ # Removing M2M table for field ip_addresses on 'Interface'
54+ db.delete_table('maasserver_interface_ip_addresses')
55+
56+
57+ models = {
58+ u'auth.group': {
59+ 'Meta': {'object_name': 'Group'},
60+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
61+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
62+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
63+ },
64+ u'auth.permission': {
65+ 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
66+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
67+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
68+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
69+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
70+ },
71+ u'auth.user': {
72+ 'Meta': {'object_name': 'User'},
73+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
74+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
75+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
76+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
77+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
78+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
79+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
80+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
81+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
82+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
83+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
84+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
85+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
86+ },
87+ u'contenttypes.contenttype': {
88+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
89+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
90+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
91+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
92+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
93+ },
94+ u'maasserver.blockdevice': {
95+ 'Meta': {'ordering': "[u'id']", 'unique_together': "((u'node', u'path'),)", 'object_name': 'BlockDevice'},
96+ 'block_size': ('django.db.models.fields.IntegerField', [], {}),
97+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
98+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
99+ 'id_path': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
100+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
101+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
102+ 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
103+ 'size': ('django.db.models.fields.BigIntegerField', [], {}),
104+ 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}),
105+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
106+ },
107+ u'maasserver.bootresource': {
108+ 'Meta': {'unique_together': "((u'name', u'architecture'),)", 'object_name': 'BootResource'},
109+ 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
110+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
111+ 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
112+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
113+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
114+ 'rtype': ('django.db.models.fields.IntegerField', [], {'max_length': '10'}),
115+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
116+ },
117+ u'maasserver.bootresourcefile': {
118+ 'Meta': {'unique_together': "((u'resource_set', u'filetype'),)", 'object_name': 'BootResourceFile'},
119+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
120+ 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
121+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
122+ 'filetype': ('django.db.models.fields.CharField', [], {'default': "u'root-tgz'", 'max_length': '20'}),
123+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
124+ 'largefile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.LargeFile']"}),
125+ 'resource_set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'files'", 'to': u"orm['maasserver.BootResourceSet']"}),
126+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
127+ },
128+ u'maasserver.bootresourceset': {
129+ 'Meta': {'unique_together': "((u'resource', u'version'),)", 'object_name': 'BootResourceSet'},
130+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
131+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
132+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
133+ 'resource': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'sets'", 'to': u"orm['maasserver.BootResource']"}),
134+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
135+ 'version': ('django.db.models.fields.CharField', [], {'max_length': '255'})
136+ },
137+ u'maasserver.bootsource': {
138+ 'Meta': {'object_name': 'BootSource'},
139+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
140+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
141+ 'keyring_data': ('maasserver.fields.EditableBinaryField', [], {'blank': 'True'}),
142+ 'keyring_filename': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}),
143+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
144+ 'url': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '200'})
145+ },
146+ u'maasserver.bootsourcecache': {
147+ 'Meta': {'object_name': 'BootSourceCache'},
148+ 'arch': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
149+ 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}),
150+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
151+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
152+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
153+ 'os': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
154+ 'release': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
155+ 'subarch': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
156+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
157+ },
158+ u'maasserver.bootsourceselection': {
159+ 'Meta': {'unique_together': "((u'boot_source', u'os', u'release'),)", 'object_name': 'BootSourceSelection'},
160+ 'arches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
161+ 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}),
162+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
163+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
164+ 'labels': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
165+ 'os': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
166+ 'release': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
167+ 'subarches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
168+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
169+ },
170+ u'maasserver.candidatename': {
171+ 'Meta': {'unique_together': "((u'name', u'position'),)", 'object_name': 'CandidateName'},
172+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
173+ 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
174+ 'position': ('django.db.models.fields.IntegerField', [], {})
175+ },
176+ u'maasserver.componenterror': {
177+ 'Meta': {'object_name': 'ComponentError'},
178+ 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
179+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
180+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
181+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
182+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
183+ },
184+ u'maasserver.config': {
185+ 'Meta': {'object_name': 'Config'},
186+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
187+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
188+ 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'})
189+ },
190+ u'maasserver.dhcplease': {
191+ 'Meta': {'object_name': 'DHCPLease'},
192+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
193+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
194+ 'mac': ('maasserver.fields.MACAddressField', [], {}),
195+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"})
196+ },
197+ u'maasserver.downloadprogress': {
198+ 'Meta': {'object_name': 'DownloadProgress'},
199+ 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
200+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
201+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}),
202+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
203+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
204+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
205+ 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
206+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
207+ },
208+ u'maasserver.event': {
209+ 'Meta': {'object_name': 'Event'},
210+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
211+ 'description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}),
212+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
213+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
214+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.EventType']"}),
215+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
216+ },
217+ u'maasserver.eventtype': {
218+ 'Meta': {'object_name': 'EventType'},
219+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
220+ 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
221+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
222+ 'level': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
223+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
224+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
225+ },
226+ u'maasserver.fabric': {
227+ 'Meta': {'object_name': 'Fabric'},
228+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
229+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
230+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
231+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
232+ },
233+ u'maasserver.filestorage': {
234+ 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'},
235+ 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}),
236+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
237+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
238+ 'key': ('django.db.models.fields.CharField', [], {'default': "u'a6d7ef74-1e3b-11e5-a2ed-3c970e0e56dc'", 'unique': 'True', 'max_length': '36'}),
239+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
240+ },
241+ u'maasserver.filesystem': {
242+ 'Meta': {'object_name': 'Filesystem'},
243+ 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'null': 'True', 'blank': 'True'}),
244+ 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
245+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
246+ 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.FilesystemGroup']"}),
247+ 'fstype': ('django.db.models.fields.CharField', [], {'default': "u'ext4'", 'max_length': '20'}),
248+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
249+ 'mount_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
250+ 'mount_point': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
251+ 'partition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Partition']", 'unique': 'True', 'null': 'True', 'blank': 'True'}),
252+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
253+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
254+ },
255+ u'maasserver.filesystemgroup': {
256+ 'Meta': {'object_name': 'FilesystemGroup'},
257+ 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
258+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
259+ 'group_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
260+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
261+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
262+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
263+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
264+ },
265+ u'maasserver.interface': {
266+ 'Meta': {'ordering': "(u'created',)", 'object_name': 'Interface'},
267+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
268+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
269+ 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.StaticIPAddress']", 'null': 'True', 'blank': 'True'}),
270+ 'ipv4_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
271+ 'ipv6_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
272+ 'mac': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.MACAddress']", 'null': 'True', 'blank': 'True'}),
273+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
274+ 'params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
275+ 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.Interface']", 'null': 'True', 'through': u"orm['maasserver.InterfaceRelationship']", 'blank': 'True'}),
276+ 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}),
277+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
278+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
279+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
280+ },
281+ u'maasserver.interfacerelationship': {
282+ 'Meta': {'object_name': 'InterfaceRelationship'},
283+ 'child': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'parent_relationships'", 'to': u"orm['maasserver.Interface']"}),
284+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
285+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
286+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'children_relationships'", 'to': u"orm['maasserver.Interface']"}),
287+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
288+ },
289+ u'maasserver.largefile': {
290+ 'Meta': {'object_name': 'LargeFile'},
291+ 'content': ('maasserver.fields.LargeObjectField', [], {}),
292+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
293+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
294+ 'sha256': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
295+ 'total_size': ('django.db.models.fields.BigIntegerField', [], {}),
296+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
297+ },
298+ u'maasserver.licensekey': {
299+ 'Meta': {'unique_together': "((u'osystem', u'distro_series'),)", 'object_name': 'LicenseKey'},
300+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
301+ 'distro_series': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
302+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
303+ 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
304+ 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
305+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
306+ },
307+ u'maasserver.macaddress': {
308+ 'Meta': {'ordering': "(u'created',)", 'object_name': 'MACAddress'},
309+ 'cluster_interface': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['maasserver.NodeGroupInterface']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
310+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
311+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
312+ 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.StaticIPAddress']", 'symmetrical': 'False', 'through': u"orm['maasserver.MACStaticIPAddressLink']", 'blank': 'True'}),
313+ 'mac_address': ('maasserver.fields.MACAddressField', [], {'unique': 'True'}),
314+ 'networks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Network']", 'symmetrical': 'False', 'blank': 'True'}),
315+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'null': 'True', 'blank': 'True'}),
316+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
317+ },
318+ u'maasserver.macstaticipaddresslink': {
319+ 'Meta': {'unique_together': "((u'ip_address', u'mac_address'),)", 'object_name': 'MACStaticIPAddressLink'},
320+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
321+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
322+ 'ip_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.StaticIPAddress']", 'unique': 'True'}),
323+ 'mac_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.MACAddress']"}),
324+ 'nic_alias': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
325+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
326+ },
327+ u'maasserver.network': {
328+ 'Meta': {'object_name': 'Network'},
329+ 'default_gateway': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
330+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
331+ 'dns_servers': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
332+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
333+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
334+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
335+ 'netmask': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}),
336+ 'vlan_tag': ('django.db.models.fields.PositiveSmallIntegerField', [], {'unique': 'True', 'null': 'True', 'blank': 'True'})
337+ },
338+ u'maasserver.node': {
339+ 'Meta': {'object_name': 'Node'},
340+ 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
341+ 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}),
342+ 'boot_type': ('django.db.models.fields.CharField', [], {'default': "u'fastpath'", 'max_length': '20'}),
343+ 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
344+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
345+ 'disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
346+ 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
347+ 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
348+ 'error_description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}),
349+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}),
350+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
351+ 'installable': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
352+ 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
353+ 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
354+ 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
355+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
356+ 'osystem': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
357+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
358+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "u'children'", 'null': 'True', 'blank': 'True', 'to': u"orm['maasserver.Node']"}),
359+ 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
360+ 'power_state': ('django.db.models.fields.CharField', [], {'default': "u'unknown'", 'max_length': '10'}),
361+ 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}),
362+ 'pxe_mac': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.MACAddress']", 'blank': 'True', 'null': 'True'}),
363+ 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}),
364+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}),
365+ 'swap_size': ('django.db.models.fields.BigIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
366+ 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-a6d512cc-1e3b-11e5-a2ed-3c970e0e56dc'", 'unique': 'True', 'max_length': '41'}),
367+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}),
368+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}),
369+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
370+ 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'})
371+ },
372+ u'maasserver.nodegroup': {
373+ 'Meta': {'object_name': 'NodeGroup'},
374+ 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
375+ 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}),
376+ 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}),
377+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
378+ 'default_disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
379+ 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
380+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
381+ 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
382+ 'name': ('maasserver.models.nodegroup.DomainNameField', [], {'max_length': '80', 'blank': 'True'}),
383+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
384+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
385+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
386+ },
387+ u'maasserver.nodegroupinterface': {
388+ 'Meta': {'unique_together': "((u'nodegroup', u'name'),)", 'object_name': 'NodeGroupInterface'},
389+ 'broadcast_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
390+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
391+ 'foreign_dhcp_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
392+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
393+ 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
394+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}),
395+ 'ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
396+ 'ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
397+ 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
398+ 'name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
399+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
400+ 'router_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
401+ 'static_ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
402+ 'static_ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
403+ 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'}),
404+ 'subnet_mask': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
405+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
406+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
407+ },
408+ u'maasserver.partition': {
409+ 'Meta': {'object_name': 'Partition'},
410+ 'bootable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
411+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
412+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
413+ 'partition_table': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'partitions'", 'to': u"orm['maasserver.PartitionTable']"}),
414+ 'size': ('django.db.models.fields.BigIntegerField', [], {}),
415+ 'start_offset': ('django.db.models.fields.BigIntegerField', [], {}),
416+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
417+ 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '36', 'unique': 'True', 'null': 'True', 'blank': 'True'})
418+ },
419+ u'maasserver.partitiontable': {
420+ 'Meta': {'object_name': 'PartitionTable'},
421+ 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']"}),
422+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
423+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
424+ 'table_type': ('django.db.models.fields.CharField', [], {'default': "u'GPT'", 'max_length': '20'}),
425+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
426+ },
427+ u'maasserver.physicalblockdevice': {
428+ 'Meta': {'ordering': "[u'id']", 'object_name': 'PhysicalBlockDevice', '_ormbases': [u'maasserver.BlockDevice']},
429+ u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}),
430+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
431+ 'serial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
432+ },
433+ u'maasserver.space': {
434+ 'Meta': {'object_name': 'Space'},
435+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
436+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
437+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
438+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
439+ },
440+ u'maasserver.sshkey': {
441+ 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'},
442+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
443+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
444+ 'key': ('django.db.models.fields.TextField', [], {}),
445+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
446+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
447+ },
448+ u'maasserver.sslkey': {
449+ 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSLKey'},
450+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
451+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
452+ 'key': ('django.db.models.fields.TextField', [], {}),
453+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
454+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
455+ },
456+ u'maasserver.staticipaddress': {
457+ 'Meta': {'object_name': 'StaticIPAddress'},
458+ 'alloc_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
459+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
460+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
461+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
462+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
463+ 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'blank': 'True'}),
464+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
465+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
466+ },
467+ u'maasserver.subnet': {
468+ 'Meta': {'unique_together': "((u'name', u'space'),)", 'object_name': 'Subnet'},
469+ 'cidr': ('maasserver.fields.CIDRField', [], {'unique': 'True'}),
470+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
471+ 'dns_servers': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
472+ 'gateway_ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
473+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
474+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
475+ 'space': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Space']", 'on_delete': 'models.PROTECT'}),
476+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
477+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
478+ },
479+ u'maasserver.tag': {
480+ 'Meta': {'object_name': 'Tag'},
481+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
482+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
483+ 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
484+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
485+ 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
486+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
487+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
488+ },
489+ u'maasserver.userprofile': {
490+ 'Meta': {'object_name': 'UserProfile'},
491+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
492+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
493+ },
494+ u'maasserver.virtualblockdevice': {
495+ 'Meta': {'ordering': "[u'id']", 'object_name': 'VirtualBlockDevice', '_ormbases': [u'maasserver.BlockDevice']},
496+ u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}),
497+ 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'virtual_devices'", 'to': u"orm['maasserver.FilesystemGroup']"}),
498+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
499+ },
500+ u'maasserver.vlan': {
501+ 'Meta': {'unique_together': "((u'vid', u'fabric'), (u'name', u'fabric'))", 'object_name': 'VLAN'},
502+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
503+ 'fabric': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Fabric']"}),
504+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
505+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
506+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
507+ 'vid': ('django.db.models.fields.IntegerField', [], {})
508+ },
509+ u'maasserver.zone': {
510+ 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'},
511+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
512+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
513+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
514+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
515+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
516+ },
517+ u'piston.consumer': {
518+ 'Meta': {'object_name': 'Consumer'},
519+ 'description': ('django.db.models.fields.TextField', [], {}),
520+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
521+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
522+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
523+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
524+ 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}),
525+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"})
526+ },
527+ u'piston.token': {
528+ 'Meta': {'object_name': 'Token'},
529+ 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
530+ 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
531+ 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}),
532+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
533+ 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
534+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
535+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
536+ 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1435567670L'}),
537+ 'token_type': ('django.db.models.fields.IntegerField', [], {}),
538+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}),
539+ 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'})
540+ }
541+ }
542+
543+ complete_apps = ['maasserver']
544\ No newline at end of file
545
546=== modified file 'src/maasserver/models/interface.py'
547--- src/maasserver/models/interface.py 2015-06-18 12:47:13 +0000
548+++ src/maasserver/models/interface.py 2015-06-29 11:36:56 +0000
549@@ -91,6 +91,9 @@
550 'VLAN', default=get_default_vlan, editable=True, blank=False,
551 null=False, on_delete=PROTECT)
552
553+ ip_addresses = ManyToManyField(
554+ 'StaticIPAddress', editable=True, blank=True, null=True)
555+
556 mac = ForeignKey('MACAddress', editable=True, blank=True, null=True)
557
558 ipv4_params = JSONObjectField(blank=True, default="")
559
560=== modified file 'src/maasserver/models/staticipaddress.py'
561--- src/maasserver/models/staticipaddress.py 2015-05-07 18:14:38 +0000
562+++ src/maasserver/models/staticipaddress.py 2015-06-29 11:36:56 +0000
563@@ -328,9 +328,12 @@
564 verbose_name = "Static IP Address"
565 verbose_name_plural = "Static IP Addresses"
566
567+ # IP can be none when a DHCP lease has expired: in this case the entry
568+ # in the StaticIPAddress only materializes the connection between an
569+ # interface and a subnet.
570 ip = MAASIPAddressField(
571- unique=True, null=False, editable=False, blank=False,
572- verbose_name='IP')
573+ unique=True, null=True, editable=False, blank=True,
574+ default=None, verbose_name='IP')
575
576 # The MACStaticIPAddressLink table is used to link StaticIPAddress to
577 # MACAddress. See MACAddress.ip_addresses, and the reverse relation
578@@ -340,6 +343,10 @@
579 alloc_type = IntegerField(
580 editable=False, null=False, blank=False, default=IPADDRESS_TYPE.AUTO)
581
582+ # Subnet is only null for IP addresses allocate before the new networking
583+ # model.
584+ subnet = ForeignKey('Subnet', editable=True, blank=True, null=True)
585+
586 # XXX: removing the null=True here causes dozens of tests to fail with
587 # NOT NULL constraint violations. (an empty string an NULL should mean
588 # the same thing here.)