Merge lp:~blake-rouse/maas/fix-1508056 into lp:~maas-committers/maas/trunk

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 4481
Proposed branch: lp:~blake-rouse/maas/fix-1508056
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 846 lines (+636/-15)
13 files modified
src/maasserver/api/interfaces.py (+5/-0)
src/maasserver/api/nodes.py (+1/-0)
src/maasserver/api/tests/test_interfaces.py (+1/-0)
src/maasserver/forms_vlan.py (+5/-0)
src/maasserver/migrations/0190_add_mtu_to_vlan_model.py (+547/-0)
src/maasserver/models/interface.py (+9/-0)
src/maasserver/models/tests/test_filesystemgroup.py (+3/-2)
src/maasserver/models/tests/test_interface.py (+16/-0)
src/maasserver/models/vlan.py (+11/-0)
src/maasserver/preseed_network.py (+2/-1)
src/maasserver/tests/test_forms_vlan.py (+33/-11)
src/maasserver/tests/test_preseed_network.py (+2/-1)
src/maasserver/websockets/handlers/tests/test_vlan.py (+1/-0)
To merge this branch: bzr merge lp:~blake-rouse/maas/fix-1508056
Reviewer Review Type Date Requested Status
Mike Pontillo (community) Approve
Andres Rodriguez (community) Approve
Review via email: mp+277050@code.launchpad.net

Commit message

Add MTU field to VLAN. Add the effective MTU for an interface in the API output and the network preseed generation.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm!

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (1019.6 KiB)

The attempt to merge lp:~blake-rouse/maas/fix-1508056 into lp:maas failed. Below is the output from the failed tests.

Get:1 http://security.ubuntu.com trusty-security InRelease [64.4 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Get:2 http://nova.clouds.archive.ubuntu.com trusty-updates InRelease [64.4 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:3 http://security.ubuntu.com trusty-security/main Sources [98.0 kB]
Get:4 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [242 kB]
Get:5 http://security.ubuntu.com trusty-security/universe Sources [30.9 kB]
Get:6 http://security.ubuntu.com trusty-security/main amd64 Packages [362 kB]
Get:7 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [143 kB]
Get:8 http://security.ubuntu.com trusty-security/universe amd64 Packages [117 kB]
Get:9 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [644 kB]
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Get:10 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [326 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Fetched 2,092 kB in 4s (495 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm pep8 phantomjs postgresql pyflakes python-apt python-bson python-bzrlib python-convoy python-coverage python-crochet python-cssselect python-curtin python-dev python-distro-info python-django python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-extras python-fixtures python-flake8 python-formencode python-hivex python-httplib2 python-jinja2 python-jsonschema python-lxml python-mock python-netaddr python-netifaces python-nose python-oauth python-openssl python-paramiko python-pexpect python-pip python-pocket-lint python-psycopg2 python-pyinotify python-pyparsing python-seamicroclient python-simplejson python-simplestreams python-sphinx python-subunit python-tempita python-testresources python-testscenarios python-te...

Revision history for this message
Mike Pontillo (mpontillo) wrote :

Looks good; you may want to enforce an upper limit though. (I suggest 65535 since that's the max packet size for both IPv4 and IPv6.)

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

Thanks for the review. I have added the upper limit.

Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (1019.9 KiB)

The attempt to merge lp:~blake-rouse/maas/fix-1508056 into lp:maas failed. Below is the output from the failed tests.

Get:1 http://security.ubuntu.com trusty-security InRelease [64.4 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Get:2 http://nova.clouds.archive.ubuntu.com trusty-updates InRelease [64.4 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:3 http://security.ubuntu.com trusty-security/main Sources [98.0 kB]
Get:4 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [242 kB]
Get:5 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [144 kB]
Get:6 http://security.ubuntu.com trusty-security/universe Sources [32.5 kB]
Get:7 http://security.ubuntu.com trusty-security/main amd64 Packages [366 kB]
Get:8 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [649 kB]
Get:9 http://security.ubuntu.com trusty-security/universe amd64 Packages [122 kB]
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Get:10 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [331 kB]
Get:11 http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en [317 kB]
Get:12 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en [177 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Fetched 2,607 kB in 4s (529 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb chromium-browser chromium-chromedriver curl daemontools debhelper dh-apport dh-systemd distro-info dnsutils firefox freeipmi-tools git gjs ipython isc-dhcp-common libjs-angularjs libjs-jquery libjs-jquery-hotkeys libjs-yui3-full libjs-yui3-min libpq-dev make nodejs-legacy npm pep8 phantomjs postgresql pyflakes python-apt python-bson python-bzrlib python-convoy python-coverage python-crochet python-cssselect python-curtin python-dev python-distro-info python-django python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-extras python-fixtures python-flake8 python-formencode python-hivex python-httplib2 python-jinja2 python-jsonschema python-lxml python-mock python-netaddr python-netifaces python-nose python-oauth python-openssl python-paramiko python-pexpect python-pip python-pocket-lint python-psycopg2 python-pyinotify python-pyparsing python-seamicroclient python-simplejson python-simplestreams python-sphinx python-subunit python-tempita python-testresources python...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/api/interfaces.py'
2--- src/maasserver/api/interfaces.py 2015-10-30 20:53:53 +0000
3+++ src/maasserver/api/interfaces.py 2015-11-10 16:55:31 +0000
4@@ -64,6 +64,7 @@
5 'links',
6 'params',
7 'discovered',
8+ 'effective_mtu',
9 )
10
11
12@@ -284,6 +285,10 @@
13 def discovered(cls, interface):
14 return interface.get_discovered()
15
16+ @classmethod
17+ def effective_mtu(cls, interface):
18+ return interface.get_effective_mtu()
19+
20 def read(self, request, system_id, interface_id):
21 """Read interface on node.
22
23
24=== modified file 'src/maasserver/api/nodes.py'
25--- src/maasserver/api/nodes.py 2015-11-09 22:27:59 +0000
26+++ src/maasserver/api/nodes.py 2015-11-10 16:55:31 +0000
27@@ -136,6 +136,7 @@
28 'links',
29 'params',
30 'discovered',
31+ 'effective_mtu',
32 )),
33 'routers',
34 'zone',
35
36=== modified file 'src/maasserver/api/tests/test_interfaces.py'
37--- src/maasserver/api/tests/test_interfaces.py 2015-10-30 20:53:53 +0000
38+++ src/maasserver/api/tests/test_interfaces.py 2015-11-10 16:55:31 +0000
39@@ -512,6 +512,7 @@
40 "tags": Equals(bond.tags),
41 "resource_uri": Equals(get_node_interface_uri(bond)),
42 "params": Equals(bond.params),
43+ "effective_mtu": Equals(bond.get_effective_mtu()),
44 }))
45 self.assertEquals(sorted(
46 nic.name
47
48=== modified file 'src/maasserver/forms_vlan.py'
49--- src/maasserver/forms_vlan.py 2015-10-09 06:06:47 +0000
50+++ src/maasserver/forms_vlan.py 2015-11-10 16:55:31 +0000
51@@ -16,6 +16,7 @@
52 "VLANForm",
53 ]
54
55+from django import forms
56 from django.core.exceptions import ValidationError
57 from maasserver.forms import MAASModelForm
58 from maasserver.models.vlan import VLAN
59@@ -24,11 +25,15 @@
60 class VLANForm(MAASModelForm):
61 """VLAN creation/edition form."""
62
63+ # Linux doesn't allow lower than 552 for the MTU.
64+ mtu = forms.IntegerField(min_value=552, required=False)
65+
66 class Meta:
67 model = VLAN
68 fields = (
69 'name',
70 'vid',
71+ 'mtu',
72 )
73
74 def __init__(self, *args, **kwargs):
75
76=== added file 'src/maasserver/migrations/0190_add_mtu_to_vlan_model.py'
77--- src/maasserver/migrations/0190_add_mtu_to_vlan_model.py 1970-01-01 00:00:00 +0000
78+++ src/maasserver/migrations/0190_add_mtu_to_vlan_model.py 2015-11-10 16:55:31 +0000
79@@ -0,0 +1,547 @@
80+from django.db import models
81+from south.db import db
82+# -*- coding: utf-8 -*-
83+from south.utils import datetime_utils as datetime
84+from south.v2 import SchemaMigration
85+
86+
87+class Migration(SchemaMigration):
88+
89+ def forwards(self, orm):
90+ # Adding field 'VLAN.mtu'
91+ db.add_column(u'maasserver_vlan', 'mtu',
92+ self.gf('django.db.models.fields.IntegerField')(default=1500),
93+ keep_default=False)
94+
95+
96+ # Changing field 'BootSourceSelection.labels'
97+ db.alter_column(u'maasserver_bootsourceselection', 'labels', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text', null=True))
98+
99+ # Changing field 'BootSourceSelection.arches'
100+ db.alter_column(u'maasserver_bootsourceselection', 'arches', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text', null=True))
101+
102+ # Changing field 'BootSourceSelection.subarches'
103+ db.alter_column(u'maasserver_bootsourceselection', 'subarches', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text', null=True))
104+
105+ # Changing field 'Node.routers'
106+ db.alter_column(u'maasserver_node', 'routers', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'macaddr', null=True))
107+
108+ # Changing field 'Subnet.dns_servers'
109+ db.alter_column(u'maasserver_subnet', 'dns_servers', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text', null=True))
110+
111+ # Changing field 'BlockDevice.tags'
112+ db.alter_column(u'maasserver_blockdevice', 'tags', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text'))
113+
114+ # Changing field 'Interface.tags'
115+ db.alter_column(u'maasserver_interface', 'tags', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text'))
116+
117+ def backwards(self, orm):
118+ # Deleting field 'VLAN.mtu'
119+ db.delete_column(u'maasserver_vlan', 'mtu')
120+
121+
122+ # Changing field 'BootSourceSelection.labels'
123+ db.alter_column(u'maasserver_bootsourceselection', 'labels', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text'))
124+
125+ # Changing field 'BootSourceSelection.arches'
126+ db.alter_column(u'maasserver_bootsourceselection', 'arches', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text'))
127+
128+ # Changing field 'BootSourceSelection.subarches'
129+ db.alter_column(u'maasserver_bootsourceselection', 'subarches', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text'))
130+
131+ # Changing field 'Node.routers'
132+ db.alter_column(u'maasserver_node', 'routers', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'macaddr'))
133+
134+ # Changing field 'Subnet.dns_servers'
135+ db.alter_column(u'maasserver_subnet', 'dns_servers', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text'))
136+
137+ # Changing field 'BlockDevice.tags'
138+ db.alter_column(u'maasserver_blockdevice', 'tags', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text', null=False))
139+
140+ # Changing field 'Interface.tags'
141+ db.alter_column(u'maasserver_interface', 'tags', self.gf('djorm_pgarray.fields.ArrayField')(dbtype=u'text', null=False))
142+
143+ models = {
144+ u'auth.group': {
145+ 'Meta': {'object_name': 'Group'},
146+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
147+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
148+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
149+ },
150+ u'auth.permission': {
151+ 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
152+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
153+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
154+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
155+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
156+ },
157+ u'auth.user': {
158+ 'Meta': {'object_name': 'User'},
159+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
160+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
161+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
162+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
163+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
164+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
165+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
166+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
167+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
168+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
169+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
170+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
171+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
172+ },
173+ u'contenttypes.contenttype': {
174+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
175+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
176+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
177+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
178+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
179+ },
180+ u'maasserver.blockdevice': {
181+ 'Meta': {'ordering': "[u'id']", 'unique_together': "((u'node', u'name'),)", 'object_name': 'BlockDevice'},
182+ 'block_size': ('django.db.models.fields.IntegerField', [], {}),
183+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
184+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
185+ 'id_path': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
186+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
187+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
188+ 'size': ('django.db.models.fields.BigIntegerField', [], {}),
189+ 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}),
190+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
191+ },
192+ u'maasserver.bootresource': {
193+ 'Meta': {'unique_together': "((u'name', u'architecture'),)", 'object_name': 'BootResource'},
194+ 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
195+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
196+ 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
197+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
198+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
199+ 'rtype': ('django.db.models.fields.IntegerField', [], {'max_length': '10'}),
200+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
201+ },
202+ u'maasserver.bootresourcefile': {
203+ 'Meta': {'unique_together': "((u'resource_set', u'filetype'),)", 'object_name': 'BootResourceFile'},
204+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
205+ 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
206+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
207+ 'filetype': ('django.db.models.fields.CharField', [], {'default': "u'root-tgz'", 'max_length': '20'}),
208+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
209+ 'largefile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.LargeFile']"}),
210+ 'resource_set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'files'", 'to': u"orm['maasserver.BootResourceSet']"}),
211+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
212+ },
213+ u'maasserver.bootresourceset': {
214+ 'Meta': {'unique_together': "((u'resource', u'version'),)", 'object_name': 'BootResourceSet'},
215+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
216+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
217+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
218+ 'resource': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'sets'", 'to': u"orm['maasserver.BootResource']"}),
219+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
220+ 'version': ('django.db.models.fields.CharField', [], {'max_length': '255'})
221+ },
222+ u'maasserver.bootsource': {
223+ 'Meta': {'object_name': 'BootSource'},
224+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
225+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
226+ 'keyring_data': ('maasserver.fields.EditableBinaryField', [], {'blank': 'True'}),
227+ 'keyring_filename': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}),
228+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
229+ 'url': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '200'})
230+ },
231+ u'maasserver.bootsourcecache': {
232+ 'Meta': {'object_name': 'BootSourceCache'},
233+ 'arch': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
234+ 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}),
235+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
236+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
237+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
238+ 'os': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
239+ 'release': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
240+ 'subarch': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
241+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
242+ },
243+ u'maasserver.bootsourceselection': {
244+ 'Meta': {'unique_together': "((u'boot_source', u'os', u'release'),)", 'object_name': 'BootSourceSelection'},
245+ 'arches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
246+ 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}),
247+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
248+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
249+ 'labels': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
250+ 'os': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
251+ 'release': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
252+ 'subarches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
253+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
254+ },
255+ u'maasserver.cacheset': {
256+ 'Meta': {'object_name': 'CacheSet'},
257+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
258+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
259+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
260+ },
261+ u'maasserver.candidatename': {
262+ 'Meta': {'unique_together': "((u'name', u'position'),)", 'object_name': 'CandidateName'},
263+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
264+ 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
265+ 'position': ('django.db.models.fields.IntegerField', [], {})
266+ },
267+ u'maasserver.componenterror': {
268+ 'Meta': {'object_name': 'ComponentError'},
269+ 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
270+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
271+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
272+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
273+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
274+ },
275+ u'maasserver.config': {
276+ 'Meta': {'object_name': 'Config'},
277+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
278+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
279+ 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'})
280+ },
281+ u'maasserver.downloadprogress': {
282+ 'Meta': {'object_name': 'DownloadProgress'},
283+ 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
284+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
285+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}),
286+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
287+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
288+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
289+ 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
290+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
291+ },
292+ u'maasserver.event': {
293+ 'Meta': {'object_name': 'Event'},
294+ 'action': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}),
295+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
296+ 'description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}),
297+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
298+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
299+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.EventType']"}),
300+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
301+ },
302+ u'maasserver.eventtype': {
303+ 'Meta': {'object_name': 'EventType'},
304+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
305+ 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
306+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
307+ 'level': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
308+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
309+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
310+ },
311+ u'maasserver.fabric': {
312+ 'Meta': {'object_name': 'Fabric'},
313+ 'class_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
314+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
315+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
316+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
317+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
318+ },
319+ u'maasserver.fannetwork': {
320+ 'Meta': {'object_name': 'FanNetwork'},
321+ 'bridge': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
322+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
323+ 'dhcp': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
324+ 'host_reserve': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'null': 'True', 'blank': 'True'}),
325+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
326+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
327+ 'off': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
328+ 'overlay': ('maasserver.fields.IPv4CIDRField', [], {'unique': 'True'}),
329+ 'underlay': ('maasserver.fields.IPv4CIDRField', [], {'unique': 'True'}),
330+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
331+ },
332+ u'maasserver.filestorage': {
333+ 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'},
334+ 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}),
335+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
336+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
337+ 'key': ('django.db.models.fields.CharField', [], {'default': "u'53797bc2-87b8-11e5-a272-bcee7b78dc5b'", 'unique': 'True', 'max_length': '36'}),
338+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'})
339+ },
340+ u'maasserver.filesystem': {
341+ 'Meta': {'unique_together': "((u'partition', u'acquired'), (u'block_device', u'acquired'))", 'object_name': 'Filesystem'},
342+ 'acquired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
343+ 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']", 'null': 'True', 'blank': 'True'}),
344+ 'cache_set': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.CacheSet']"}),
345+ 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
346+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
347+ 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.FilesystemGroup']"}),
348+ 'fstype': ('django.db.models.fields.CharField', [], {'default': "u'ext4'", 'max_length': '20'}),
349+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
350+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
351+ 'mount_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
352+ 'mount_point': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
353+ 'partition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Partition']", 'null': 'True', 'blank': 'True'}),
354+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
355+ 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '36'})
356+ },
357+ u'maasserver.filesystemgroup': {
358+ 'Meta': {'object_name': 'FilesystemGroup'},
359+ 'cache_mode': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
360+ 'cache_set': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.CacheSet']", 'null': 'True', 'blank': 'True'}),
361+ 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
362+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
363+ 'group_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
364+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
365+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
366+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
367+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
368+ },
369+ u'maasserver.interface': {
370+ 'Meta': {'ordering': "(u'created',)", 'object_name': 'Interface'},
371+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
372+ 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
373+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
374+ 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.StaticIPAddress']", 'null': 'True', 'blank': 'True'}),
375+ 'ipv4_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
376+ 'ipv6_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
377+ 'mac_address': ('maasserver.fields.MACAddressField', [], {'null': 'True', 'blank': 'True'}),
378+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
379+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'null': 'True', 'blank': 'True'}),
380+ 'params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
381+ 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.Interface']", 'null': 'True', 'through': u"orm['maasserver.InterfaceRelationship']", 'blank': 'True'}),
382+ 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}),
383+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
384+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
385+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
386+ },
387+ u'maasserver.interfacerelationship': {
388+ 'Meta': {'object_name': 'InterfaceRelationship'},
389+ 'child': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'parent_relationships'", 'to': u"orm['maasserver.Interface']"}),
390+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
391+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
392+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'children_relationships'", 'to': u"orm['maasserver.Interface']"}),
393+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
394+ },
395+ u'maasserver.largefile': {
396+ 'Meta': {'object_name': 'LargeFile'},
397+ 'content': ('maasserver.fields.LargeObjectField', [], {}),
398+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
399+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
400+ 'sha256': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
401+ 'total_size': ('django.db.models.fields.BigIntegerField', [], {}),
402+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
403+ },
404+ u'maasserver.licensekey': {
405+ 'Meta': {'unique_together': "((u'osystem', u'distro_series'),)", 'object_name': 'LicenseKey'},
406+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
407+ 'distro_series': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
408+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
409+ 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
410+ 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
411+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
412+ },
413+ u'maasserver.node': {
414+ 'Meta': {'object_name': 'Node'},
415+ 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
416+ 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}),
417+ 'bios_boot_method': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}),
418+ 'boot_cluster_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
419+ 'boot_disk': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.PhysicalBlockDevice']", 'blank': 'True', 'null': 'True'}),
420+ 'boot_interface': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.Interface']", 'blank': 'True', 'null': 'True'}),
421+ 'boot_type': ('django.db.models.fields.CharField', [], {'default': "u'fastpath'", 'max_length': '20'}),
422+ 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
423+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
424+ 'disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
425+ 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
426+ 'enable_ssh': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
427+ 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
428+ 'error_description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}),
429+ 'gateway_link_ipv4': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.StaticIPAddress']", 'blank': 'True', 'null': 'True'}),
430+ 'gateway_link_ipv6': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': u"orm['maasserver.StaticIPAddress']", 'blank': 'True', 'null': 'True'}),
431+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}),
432+ 'hwe_kernel': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}),
433+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
434+ 'installable': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
435+ 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
436+ 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
437+ 'min_hwe_kernel': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}),
438+ 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
439+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
440+ 'osystem': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
441+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'}),
442+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "u'children'", 'null': 'True', 'blank': 'True', 'to': u"orm['maasserver.Node']"}),
443+ 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'max_length': '32768', 'blank': 'True'}),
444+ 'power_state': ('django.db.models.fields.CharField', [], {'default': "u'unknown'", 'max_length': '10'}),
445+ 'power_state_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
446+ 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}),
447+ 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}),
448+ 'skip_networking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
449+ 'skip_storage': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
450+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}),
451+ 'swap_size': ('django.db.models.fields.BigIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
452+ 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-537a4b56-87b8-11e5-a272-bcee7b78dc5b'", 'unique': 'True', 'max_length': '41'}),
453+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}),
454+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}),
455+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
456+ 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'})
457+ },
458+ u'maasserver.nodegroup': {
459+ 'Meta': {'object_name': 'NodeGroup'},
460+ 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
461+ 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}),
462+ 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}),
463+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
464+ 'default_disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
465+ 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
466+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
467+ 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
468+ 'name': ('maasserver.models.nodegroup.DomainNameField', [], {'max_length': '80', 'blank': 'True'}),
469+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
470+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
471+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
472+ },
473+ u'maasserver.nodegroupinterface': {
474+ 'Meta': {'unique_together': "((u'nodegroup', u'name'),)", 'object_name': 'NodeGroupInterface'},
475+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
476+ 'foreign_dhcp_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
477+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
478+ 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
479+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}),
480+ 'ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
481+ 'ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
482+ 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
483+ 'name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
484+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
485+ 'static_ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
486+ 'static_ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
487+ 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'}),
488+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
489+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
490+ },
491+ u'maasserver.partition': {
492+ 'Meta': {'object_name': 'Partition'},
493+ 'bootable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
494+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
495+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
496+ 'partition_table': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'partitions'", 'to': u"orm['maasserver.PartitionTable']"}),
497+ 'size': ('django.db.models.fields.BigIntegerField', [], {}),
498+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
499+ 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '36', 'unique': 'True', 'null': 'True', 'blank': 'True'})
500+ },
501+ u'maasserver.partitiontable': {
502+ 'Meta': {'object_name': 'PartitionTable'},
503+ 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']"}),
504+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
505+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
506+ 'table_type': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '20'}),
507+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
508+ },
509+ u'maasserver.physicalblockdevice': {
510+ 'Meta': {'ordering': "[u'id']", 'object_name': 'PhysicalBlockDevice', '_ormbases': [u'maasserver.BlockDevice']},
511+ u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}),
512+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
513+ 'serial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
514+ },
515+ u'maasserver.space': {
516+ 'Meta': {'object_name': 'Space'},
517+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
518+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
519+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
520+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
521+ },
522+ u'maasserver.sshkey': {
523+ 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'},
524+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
525+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
526+ 'key': ('django.db.models.fields.TextField', [], {}),
527+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
528+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
529+ },
530+ u'maasserver.sslkey': {
531+ 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSLKey'},
532+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
533+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
534+ 'key': ('django.db.models.fields.TextField', [], {}),
535+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
536+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
537+ },
538+ u'maasserver.staticipaddress': {
539+ 'Meta': {'object_name': 'StaticIPAddress'},
540+ 'alloc_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
541+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
542+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
543+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
544+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
545+ 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'blank': 'True'}),
546+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
547+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'})
548+ },
549+ u'maasserver.subnet': {
550+ 'Meta': {'unique_together': "((u'name', u'space'),)", 'object_name': 'Subnet'},
551+ 'cidr': ('maasserver.fields.CIDRField', [], {'unique': 'True'}),
552+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
553+ 'dns_servers': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
554+ 'gateway_ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
555+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
556+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
557+ 'space': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Space']", 'on_delete': 'models.PROTECT'}),
558+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
559+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
560+ },
561+ u'maasserver.tag': {
562+ 'Meta': {'object_name': 'Tag'},
563+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
564+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
565+ 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
566+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
567+ 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
568+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
569+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
570+ },
571+ u'maasserver.userprofile': {
572+ 'Meta': {'object_name': 'UserProfile'},
573+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
574+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
575+ },
576+ u'maasserver.virtualblockdevice': {
577+ 'Meta': {'ordering': "[u'id']", 'object_name': 'VirtualBlockDevice', '_ormbases': [u'maasserver.BlockDevice']},
578+ u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}),
579+ 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'virtual_devices'", 'to': u"orm['maasserver.FilesystemGroup']"}),
580+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
581+ },
582+ u'maasserver.vlan': {
583+ 'Meta': {'unique_together': "((u'vid', u'fabric'),)", 'object_name': 'VLAN'},
584+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
585+ 'fabric': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Fabric']"}),
586+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
587+ 'mtu': ('django.db.models.fields.IntegerField', [], {'default': '1500'}),
588+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
589+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
590+ 'vid': ('django.db.models.fields.IntegerField', [], {})
591+ },
592+ u'maasserver.zone': {
593+ 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'},
594+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
595+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
596+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
597+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
598+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
599+ },
600+ u'piston.consumer': {
601+ 'Meta': {'object_name': 'Consumer'},
602+ 'description': ('django.db.models.fields.TextField', [], {}),
603+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
604+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
605+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
606+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
607+ 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}),
608+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"})
609+ },
610+ u'piston.token': {
611+ 'Meta': {'object_name': 'Token'},
612+ 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
613+ 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
614+ 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}),
615+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
616+ 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
617+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
618+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
619+ 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1447166144L'}),
620+ 'token_type': ('django.db.models.fields.IntegerField', [], {}),
621+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}),
622+ 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'})
623+ }
624+ }
625+
626+ complete_apps = ['maasserver']
627\ No newline at end of file
628
629=== modified file 'src/maasserver/models/interface.py'
630--- src/maasserver/models/interface.py 2015-11-06 16:57:58 +0000
631+++ src/maasserver/models/interface.py 2015-11-10 16:55:31 +0000
632@@ -336,6 +336,15 @@
633 def is_enabled(self):
634 return self.enabled
635
636+ def get_effective_mtu(self):
637+ """Return the effective MTU value for this interface."""
638+ mtu = None
639+ if self.params:
640+ mtu = self.params.get('mtu', None)
641+ if mtu is None:
642+ mtu = self.vlan.mtu
643+ return mtu
644+
645 def get_links(self):
646 """Return the definition of links connected to this interface.
647
648
649=== modified file 'src/maasserver/models/tests/test_filesystemgroup.py'
650--- src/maasserver/models/tests/test_filesystemgroup.py 2015-10-28 17:32:43 +0000
651+++ src/maasserver/models/tests/test_filesystemgroup.py 2015-11-10 16:55:31 +0000
652@@ -213,10 +213,11 @@
653 [filesystem_group.id], result_filesystem_group_ids)
654
655 def test__volume_group_on_partition(self):
656- block_device = factory.make_PhysicalBlockDevice()
657+ block_device = factory.make_PhysicalBlockDevice(size=10 * 1024 ** 3)
658 partition_table = factory.make_PartitionTable(
659 block_device=block_device)
660- partition = factory.make_Partition(partition_table=partition_table)
661+ partition = factory.make_Partition(
662+ size=5 * 1024 ** 3, partition_table=partition_table)
663 filesystem = factory.make_Filesystem(
664 fstype=FILESYSTEM_TYPE.LVM_PV, partition=partition)
665 filesystem_group = factory.make_FilesystemGroup(
666
667=== modified file 'src/maasserver/models/tests/test_interface.py'
668--- src/maasserver/models/tests/test_interface.py 2015-11-06 16:57:58 +0000
669+++ src/maasserver/models/tests/test_interface.py 2015-11-10 16:55:31 +0000
670@@ -436,6 +436,22 @@
671 self.assertIsNone(reload_object(bond), "Bond was not deleted.")
672 self.assertIsNone(reload_object(vlan), "VLAN was not deleted.")
673
674+ def test_get_effective_mtu_returns_interface_mtu(self):
675+ nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
676+ nic_mtu = random.randint(552, 4096)
677+ nic1.params = {
678+ "mtu": nic_mtu
679+ }
680+ nic1.save()
681+ self.assertEquals(nic_mtu, nic1.get_effective_mtu())
682+
683+ def test_get_effective_mtu_returns_vlan_mtu(self):
684+ nic1 = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
685+ vlan_mtu = random.randint(552, 4096)
686+ nic1.vlan.mtu = vlan_mtu
687+ nic1.vlan.save()
688+ self.assertEquals(vlan_mtu, nic1.get_effective_mtu())
689+
690 def test_get_links_returns_links_for_each_type(self):
691 interface = factory.make_Interface(INTERFACE_TYPE.PHYSICAL)
692 links = []
693
694=== modified file 'src/maasserver/models/vlan.py'
695--- src/maasserver/models/vlan.py 2015-10-23 10:28:17 +0000
696+++ src/maasserver/models/vlan.py 2015-11-10 16:55:31 +0000
697@@ -38,6 +38,7 @@
698
699 DEFAULT_VLAN_NAME = 'Default VLAN'
700 DEFAULT_VID = 0
701+DEFAULT_MTU = 1500
702
703
704 class VLANManager(Manager):
705@@ -84,6 +85,8 @@
706
707 fabric = ForeignKey('Fabric', blank=False, editable=True)
708
709+ mtu = IntegerField(default=DEFAULT_MTU)
710+
711 def __unicode__(self):
712 return "%s.%s" % (self.fabric.get_name(), self.get_name())
713
714@@ -93,8 +96,16 @@
715 {'vid':
716 ["Vid must be between 0 and 4095."]})
717
718+ def clean_mtu(self):
719+ # Linux doesn't allow lower than 552 for the MTU.
720+ if self.mtu < 552 and self.mtu <= 65535:
721+ raise ValidationError(
722+ {'mtu':
723+ ["MTU must be between 552 and 65535."]})
724+
725 def clean(self):
726 self.clean_vid()
727+ self.clean_mtu()
728
729 def is_fabric_default(self):
730 """Is this the default VLAN in the fabric?"""
731
732=== modified file 'src/maasserver/preseed_network.py'
733--- src/maasserver/preseed_network.py 2015-10-15 01:32:03 +0000
734+++ src/maasserver/preseed_network.py 2015-11-10 16:55:31 +0000
735@@ -116,8 +116,9 @@
736 if interface.params:
737 for key, value in interface.params.items():
738 # Don't include bond parameters.
739- if not key.startswith("bond_"):
740+ if not key.startswith("bond_") and key != 'mtu':
741 params[key] = self._get_param_value(value)
742+ params['mtu'] = interface.get_effective_mtu()
743 return params
744
745 def _get_bond_params(self, interface):
746
747=== modified file 'src/maasserver/tests/test_forms_vlan.py'
748--- src/maasserver/tests/test_forms_vlan.py 2015-10-09 06:06:47 +0000
749+++ src/maasserver/tests/test_forms_vlan.py 2015-11-10 16:55:31 +0000
750@@ -17,6 +17,7 @@
751 import random
752
753 from maasserver.forms_vlan import VLANForm
754+from maasserver.models.vlan import DEFAULT_MTU
755 from maasserver.testing.factory import factory
756 from maasserver.testing.orm import reload_object
757 from maasserver.testing.testcase import MAASServerTestCase
758@@ -39,17 +40,35 @@
759 fabric = factory.make_Fabric()
760 vlan_name = factory.make_name("vlan")
761 vid = random.randint(1, 1000)
762- form = VLANForm(fabric=fabric, data={
763- "name": vlan_name,
764- "vid": vid,
765- })
766- self.assertTrue(form.is_valid(), form.errors)
767- vlan = form.save()
768- self.assertEquals(vlan_name, vlan.name)
769- self.assertEquals(vid, vlan.vid)
770- self.assertEquals(fabric, vlan.fabric)
771-
772- def test__doest_require_name_or_vid_on_update(self):
773+ mtu = random.randint(552, 4096)
774+ form = VLANForm(fabric=fabric, data={
775+ "name": vlan_name,
776+ "vid": vid,
777+ "mtu": mtu,
778+ })
779+ self.assertTrue(form.is_valid(), form.errors)
780+ vlan = form.save()
781+ self.assertEquals(vlan_name, vlan.name)
782+ self.assertEquals(vid, vlan.vid)
783+ self.assertEquals(fabric, vlan.fabric)
784+ self.assertEquals(mtu, vlan.mtu)
785+
786+ def test__creates_vlan_with_default_mtu(self):
787+ fabric = factory.make_Fabric()
788+ vlan_name = factory.make_name("vlan")
789+ vid = random.randint(1, 1000)
790+ form = VLANForm(fabric=fabric, data={
791+ "name": vlan_name,
792+ "vid": vid,
793+ })
794+ self.assertTrue(form.is_valid(), form.errors)
795+ vlan = form.save()
796+ self.assertEquals(vlan_name, vlan.name)
797+ self.assertEquals(vid, vlan.vid)
798+ self.assertEquals(fabric, vlan.fabric)
799+ self.assertEquals(DEFAULT_MTU, vlan.mtu)
800+
801+ def test__doest_require_name_vid_or_mtu_on_update(self):
802 vlan = factory.make_VLAN()
803 form = VLANForm(instance=vlan, data={})
804 self.assertTrue(form.is_valid(), form.errors)
805@@ -68,11 +87,14 @@
806 vlan = factory.make_VLAN()
807 new_name = factory.make_name("vlan")
808 new_vid = random.randint(1, 1000)
809+ new_mtu = random.randint(552, 4096)
810 form = VLANForm(instance=vlan, data={
811 "name": new_name,
812 "vid": new_vid,
813+ "mtu": new_mtu,
814 })
815 self.assertTrue(form.is_valid(), form.errors)
816 form.save()
817 self.assertEquals(new_name, reload_object(vlan).name)
818 self.assertEquals(new_vid, reload_object(vlan).vid)
819+ self.assertEquals(new_mtu, reload_object(vlan).mtu)
820
821=== modified file 'src/maasserver/tests/test_preseed_network.py'
822--- src/maasserver/tests/test_preseed_network.py 2015-10-15 01:34:16 +0000
823+++ src/maasserver/tests/test_preseed_network.py 2015-11-10 16:55:31 +0000
824@@ -128,8 +128,9 @@
825 def set_interface_params(iface, ret):
826 if iface.params:
827 for key, value in iface.params.items():
828- if not key.startswith("bond_"):
829+ if not key.startswith("bond_") and key != 'mtu':
830 ret += " %s: %s\n" % (key, get_param_value(value))
831+ ret += " mtu: %s\n" % iface.get_effective_mtu()
832 return ret
833
834 def is_link_up(addresses):
835
836=== modified file 'src/maasserver/websockets/handlers/tests/test_vlan.py'
837--- src/maasserver/websockets/handlers/tests/test_vlan.py 2015-10-09 21:26:04 +0000
838+++ src/maasserver/websockets/handlers/tests/test_vlan.py 2015-11-10 16:55:31 +0000
839@@ -28,6 +28,7 @@
840 "id": vlan.id,
841 "name": vlan.get_name(),
842 "vid": vlan.vid,
843+ "mtu": vlan.mtu,
844 "fabric": vlan.fabric_id,
845 "updated": dehydrate_datetime(vlan.updated),
846 "created": dehydrate_datetime(vlan.created),