Merge lp:~blake-rouse/maas/remove-path-and-compute 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: 4064
Proposed branch: lp:~blake-rouse/maas/remove-path-and-compute
Merge into: lp:~maas-committers/maas/trunk
Prerequisite: lp:~blake-rouse/maas/auto-create-virtual-block-device
Diff against target: 765 lines (+546/-30)
9 files modified
src/maasserver/api/tests/test_blockdevice.py (+0/-4)
src/maasserver/migrations/0148_remove_path_from_block_device.py (+517/-0)
src/maasserver/models/blockdevice.py (+6/-5)
src/maasserver/models/tests/test_blockdevice.py (+6/-0)
src/maasserver/models/tests/test_virtualblockdevice.py (+2/-2)
src/maasserver/models/virtualblockdevice.py (+1/-2)
src/maasserver/testing/factory.py (+12/-13)
src/metadataserver/models/commissioningscript.py (+0/-1)
src/metadataserver/models/tests/test_noderesults.py (+2/-3)
To merge this branch: bzr merge lp:~blake-rouse/maas/remove-path-and-compute
Reviewer Review Type Date Requested Status
Raphaël Badin (community) Approve
Review via email: mp+263433@code.launchpad.net

Commit message

Remove the path field from BlockDevice and add it as a property.

This is done because curtin will make sure that every time a node is deployed or rebooted that the disks will always show up at this path. This is the best way we can set specific device names because udev will not allow you to set the name of the device at the "/dev" level.

To post a comment you must log in.
Revision history for this message
Raphaël Badin (rvb) wrote :

See my question below…

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

Not going to block you on this, please just add the missing test.

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

The attempt to merge lp:~blake-rouse/maas/remove-path-and-compute into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Get:1 http://security.ubuntu.com trusty-security Release.gpg [933 B]
Get:2 http://security.ubuntu.com trusty-security Release [63.5 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Get:3 http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:4 http://security.ubuntu.com trusty-security/main Sources [87.4 kB]
Get:5 http://nova.clouds.archive.ubuntu.com trusty-updates Release [63.5 kB]
Get:6 http://security.ubuntu.com trusty-security/universe Sources [28.1 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
Get:7 http://security.ubuntu.com trusty-security/main amd64 Packages [304 kB]
Get:8 http://security.ubuntu.com trusty-security/universe amd64 Packages [111 kB]
Get:9 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [212 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 Sources [123 kB]
Get:11 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [562 kB]
Get:12 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [292 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
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 1,848 kB in 3s (536 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-iscpy python-jinja2 python-jsonschema python-lockfile python-lxml python-mock python-netaddr python-netifa...

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

The attempt to merge lp:~blake-rouse/maas/remove-path-and-compute into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Get:1 http://security.ubuntu.com trusty-security Release.gpg [933 B]
Get:2 http://security.ubuntu.com trusty-security Release [63.5 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Get:3 http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:4 http://nova.clouds.archive.ubuntu.com trusty-updates Release [63.5 kB]
Get:5 http://security.ubuntu.com trusty-security/main Sources [87.4 kB]
Get:6 http://security.ubuntu.com trusty-security/universe Sources [28.1 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Get:7 http://security.ubuntu.com trusty-security/main amd64 Packages [304 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Get:8 http://security.ubuntu.com trusty-security/universe amd64 Packages [111 kB]
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
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Get:9 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [212 kB]
Get:10 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [123 kB]
Get:11 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [562 kB]
Get:12 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [292 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
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 1,849 kB in 3s (612 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-iscpy python-jinja2 python-jsonschema python-lockfile python-lxml python-mock python-netaddr python-netifa...

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

The attempt to merge lp:~blake-rouse/maas/remove-path-and-compute into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Get:1 http://security.ubuntu.com trusty-security Release.gpg [933 B]
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Get:2 http://security.ubuntu.com trusty-security Release [63.5 kB]
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Get:3 http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:4 http://nova.clouds.archive.ubuntu.com trusty-updates Release [63.5 kB]
Get:5 http://security.ubuntu.com trusty-security/main Sources [87.4 kB]
Get:6 http://security.ubuntu.com trusty-security/universe Sources [28.1 kB]
Get:7 http://security.ubuntu.com trusty-security/main amd64 Packages [304 kB]
Get:8 http://security.ubuntu.com trusty-security/universe amd64 Packages [111 kB]
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://security.ubuntu.com trusty-security/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
Get:9 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [212 kB]
Get:10 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [123 kB]
Get:11 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [562 kB]
Get:12 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [292 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
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 1,849 kB in 6s (300 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-iscpy python-jinja2 python-jsonschema python-lockfile python-lxml python-mock python-netaddr python-netifa...

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

I guess I will just keep pressing approved until this lands...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/api/tests/test_blockdevice.py'
2--- src/maasserver/api/tests/test_blockdevice.py 2015-07-01 21:13:08 +0000
3+++ src/maasserver/api/tests/test_blockdevice.py 2015-07-02 04:22:18 +0000
4@@ -191,7 +191,6 @@
5 'name': 'sda',
6 'block_size': 1024,
7 'size': 140 * 1024,
8- 'path': '/dev/sda',
9 'model': 'A2M0003',
10 'serial': '42',
11 })
12@@ -208,7 +207,6 @@
13 'name': 'sda',
14 'block_size': 1024,
15 'size': 140 * 1024,
16- 'path': '/dev/sda',
17 'model': 'A2M0003',
18 'serial': '42',
19 })
20@@ -219,7 +217,6 @@
21 self.assertEqual(pbd.name, 'sda')
22 self.assertEqual(pbd.block_size, 1024)
23 self.assertEqual(pbd.size, 140 * 1024)
24- self.assertEqual(pbd.path, '/dev/sda')
25 self.assertEqual(pbd.model, 'A2M0003')
26 self.assertEqual(pbd.serial, '42')
27
28@@ -232,7 +229,6 @@
29 'name': 'sda',
30 'block_size': 1024,
31 'size': 100 * 1024,
32- 'path': '/dev/sda',
33 'model': 'A2M0003',
34 'serial': '42',
35 })
36
37=== added file 'src/maasserver/migrations/0148_remove_path_from_block_device.py'
38--- src/maasserver/migrations/0148_remove_path_from_block_device.py 1970-01-01 00:00:00 +0000
39+++ src/maasserver/migrations/0148_remove_path_from_block_device.py 2015-07-02 04:22:18 +0000
40@@ -0,0 +1,517 @@
41+from django.db import models
42+from south.db import db
43+# -*- coding: utf-8 -*-
44+from south.utils import datetime_utils as datetime
45+from south.v2 import SchemaMigration
46+
47+
48+class Migration(SchemaMigration):
49+
50+ def forwards(self, orm):
51+ # Removing unique constraint on 'BlockDevice', fields ['node', 'path']
52+ db.delete_unique(u'maasserver_blockdevice', ['node_id', 'path'])
53+
54+ # Deleting field 'BlockDevice.path'
55+ db.delete_column(u'maasserver_blockdevice', 'path')
56+
57+ # Adding unique constraint on 'BlockDevice', fields ['node', 'name']
58+ db.create_unique(u'maasserver_blockdevice', ['node_id', 'name'])
59+
60+
61+ def backwards(self, orm):
62+ # Removing unique constraint on 'BlockDevice', fields ['node', 'name']
63+ db.delete_unique(u'maasserver_blockdevice', ['node_id', 'name'])
64+
65+ # blake_r - I don't really like this but since path has NOT NULL, and
66+ # unique we just can't set it to a default value.
67+ raise RuntimeError(
68+ "Cannot reverse this migration. 'BlockDevice.path' and its values "
69+ "cannot be restored.")
70+
71+
72+ models = {
73+ u'auth.group': {
74+ 'Meta': {'object_name': 'Group'},
75+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
76+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
77+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
78+ },
79+ u'auth.permission': {
80+ 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
81+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
82+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
83+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
84+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
85+ },
86+ u'auth.user': {
87+ 'Meta': {'object_name': 'User'},
88+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
89+ 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}),
90+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
91+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
92+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
93+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
94+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
95+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
96+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
97+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
98+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
99+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
100+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
101+ },
102+ u'contenttypes.contenttype': {
103+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
104+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
105+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
106+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
107+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
108+ },
109+ u'maasserver.blockdevice': {
110+ 'Meta': {'ordering': "[u'id']", 'unique_together': "((u'node', u'name'),)", 'object_name': 'BlockDevice'},
111+ 'block_size': ('django.db.models.fields.IntegerField', [], {}),
112+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
113+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
114+ 'id_path': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
115+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
116+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
117+ 'size': ('django.db.models.fields.BigIntegerField', [], {}),
118+ 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}),
119+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
120+ },
121+ u'maasserver.bootresource': {
122+ 'Meta': {'unique_together': "((u'name', u'architecture'),)", 'object_name': 'BootResource'},
123+ 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
124+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
125+ 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
126+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
127+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
128+ 'rtype': ('django.db.models.fields.IntegerField', [], {'max_length': '10'}),
129+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
130+ },
131+ u'maasserver.bootresourcefile': {
132+ 'Meta': {'unique_together': "((u'resource_set', u'filetype'),)", 'object_name': 'BootResourceFile'},
133+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
134+ 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
135+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
136+ 'filetype': ('django.db.models.fields.CharField', [], {'default': "u'root-tgz'", 'max_length': '20'}),
137+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
138+ 'largefile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.LargeFile']"}),
139+ 'resource_set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'files'", 'to': u"orm['maasserver.BootResourceSet']"}),
140+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
141+ },
142+ u'maasserver.bootresourceset': {
143+ 'Meta': {'unique_together': "((u'resource', u'version'),)", 'object_name': 'BootResourceSet'},
144+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
145+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
146+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
147+ 'resource': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'sets'", 'to': u"orm['maasserver.BootResource']"}),
148+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
149+ 'version': ('django.db.models.fields.CharField', [], {'max_length': '255'})
150+ },
151+ u'maasserver.bootsource': {
152+ 'Meta': {'object_name': 'BootSource'},
153+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
154+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
155+ 'keyring_data': ('maasserver.fields.EditableBinaryField', [], {'blank': 'True'}),
156+ 'keyring_filename': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}),
157+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
158+ 'url': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '200'})
159+ },
160+ u'maasserver.bootsourcecache': {
161+ 'Meta': {'object_name': 'BootSourceCache'},
162+ 'arch': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
163+ 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}),
164+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
165+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
166+ 'label': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
167+ 'os': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
168+ 'release': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
169+ 'subarch': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
170+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
171+ },
172+ u'maasserver.bootsourceselection': {
173+ 'Meta': {'unique_together': "((u'boot_source', u'os', u'release'),)", 'object_name': 'BootSourceSelection'},
174+ 'arches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
175+ 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}),
176+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
177+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
178+ 'labels': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
179+ 'os': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
180+ 'release': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
181+ 'subarches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
182+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
183+ },
184+ u'maasserver.candidatename': {
185+ 'Meta': {'unique_together': "((u'name', u'position'),)", 'object_name': 'CandidateName'},
186+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
187+ 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
188+ 'position': ('django.db.models.fields.IntegerField', [], {})
189+ },
190+ u'maasserver.componenterror': {
191+ 'Meta': {'object_name': 'ComponentError'},
192+ 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
193+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
194+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
195+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
196+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
197+ },
198+ u'maasserver.config': {
199+ 'Meta': {'object_name': 'Config'},
200+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
201+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
202+ 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'})
203+ },
204+ u'maasserver.dhcplease': {
205+ 'Meta': {'object_name': 'DHCPLease'},
206+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
207+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
208+ 'mac': ('maasserver.fields.MACAddressField', [], {}),
209+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"})
210+ },
211+ u'maasserver.downloadprogress': {
212+ 'Meta': {'object_name': 'DownloadProgress'},
213+ 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
214+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
215+ 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}),
216+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
217+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
218+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
219+ 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
220+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
221+ },
222+ u'maasserver.event': {
223+ 'Meta': {'object_name': 'Event'},
224+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
225+ 'description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}),
226+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
227+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}),
228+ 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.EventType']"}),
229+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
230+ },
231+ u'maasserver.eventtype': {
232+ 'Meta': {'object_name': 'EventType'},
233+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
234+ 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
235+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
236+ 'level': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
237+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
238+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
239+ },
240+ u'maasserver.fabric': {
241+ 'Meta': {'object_name': 'Fabric'},
242+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
243+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
244+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
245+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
246+ },
247+ u'maasserver.filestorage': {
248+ 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'},
249+ 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}),
250+ 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
251+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
252+ 'key': ('django.db.models.fields.CharField', [], {'default': "u'dfe1a812-1f73-11e5-9405-bcee7b78dc5b'", 'unique': 'True', 'max_length': '36'}),
253+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
254+ },
255+ u'maasserver.filesystem': {
256+ 'Meta': {'object_name': 'Filesystem'},
257+ 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'null': 'True', 'blank': 'True'}),
258+ 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
259+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
260+ 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.FilesystemGroup']"}),
261+ 'fstype': ('django.db.models.fields.CharField', [], {'default': "u'ext4'", 'max_length': '20'}),
262+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
263+ 'mount_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
264+ 'mount_point': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
265+ 'partition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Partition']", 'unique': 'True', 'null': 'True', 'blank': 'True'}),
266+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
267+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
268+ },
269+ u'maasserver.filesystemgroup': {
270+ 'Meta': {'object_name': 'FilesystemGroup'},
271+ 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
272+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
273+ 'group_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
274+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
275+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
276+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
277+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
278+ },
279+ u'maasserver.interface': {
280+ 'Meta': {'ordering': "(u'created',)", 'object_name': 'Interface'},
281+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
282+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
283+ 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.StaticIPAddress']", 'null': 'True', 'blank': 'True'}),
284+ 'ipv4_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
285+ 'ipv6_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
286+ 'mac': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.MACAddress']", 'null': 'True', 'blank': 'True'}),
287+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
288+ 'params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
289+ 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.Interface']", 'null': 'True', 'through': u"orm['maasserver.InterfaceRelationship']", 'blank': 'True'}),
290+ 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}),
291+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
292+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
293+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
294+ },
295+ u'maasserver.interfacerelationship': {
296+ 'Meta': {'object_name': 'InterfaceRelationship'},
297+ 'child': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'parent_relationships'", 'to': u"orm['maasserver.Interface']"}),
298+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
299+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
300+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'children_relationships'", 'to': u"orm['maasserver.Interface']"}),
301+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
302+ },
303+ u'maasserver.largefile': {
304+ 'Meta': {'object_name': 'LargeFile'},
305+ 'content': ('maasserver.fields.LargeObjectField', [], {}),
306+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
307+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
308+ 'sha256': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
309+ 'total_size': ('django.db.models.fields.BigIntegerField', [], {}),
310+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
311+ },
312+ u'maasserver.licensekey': {
313+ 'Meta': {'unique_together': "((u'osystem', u'distro_series'),)", 'object_name': 'LicenseKey'},
314+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
315+ 'distro_series': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
316+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
317+ 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
318+ 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
319+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
320+ },
321+ u'maasserver.macaddress': {
322+ 'Meta': {'ordering': "(u'created',)", 'object_name': 'MACAddress'},
323+ 'cluster_interface': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['maasserver.NodeGroupInterface']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
324+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
325+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
326+ 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.StaticIPAddress']", 'symmetrical': 'False', 'through': u"orm['maasserver.MACStaticIPAddressLink']", 'blank': 'True'}),
327+ 'mac_address': ('maasserver.fields.MACAddressField', [], {'unique': 'True'}),
328+ 'networks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Network']", 'symmetrical': 'False', 'blank': 'True'}),
329+ 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'null': 'True', 'blank': 'True'}),
330+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
331+ },
332+ u'maasserver.macstaticipaddresslink': {
333+ 'Meta': {'unique_together': "((u'ip_address', u'mac_address'),)", 'object_name': 'MACStaticIPAddressLink'},
334+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
335+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
336+ 'ip_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.StaticIPAddress']", 'unique': 'True'}),
337+ 'mac_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.MACAddress']"}),
338+ 'nic_alias': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
339+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
340+ },
341+ u'maasserver.network': {
342+ 'Meta': {'object_name': 'Network'},
343+ 'default_gateway': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
344+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
345+ 'dns_servers': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
346+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
347+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
348+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
349+ 'netmask': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}),
350+ 'vlan_tag': ('django.db.models.fields.PositiveSmallIntegerField', [], {'unique': 'True', 'null': 'True', 'blank': 'True'})
351+ },
352+ u'maasserver.node': {
353+ 'Meta': {'object_name': 'Node'},
354+ 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
355+ 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}),
356+ 'boot_type': ('django.db.models.fields.CharField', [], {'default': "u'fastpath'", 'max_length': '20'}),
357+ 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
358+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
359+ 'disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
360+ 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
361+ 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
362+ 'error_description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}),
363+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}),
364+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
365+ 'installable': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
366+ 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
367+ 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
368+ 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
369+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}),
370+ 'osystem': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}),
371+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
372+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "u'children'", 'null': 'True', 'blank': 'True', 'to': u"orm['maasserver.Node']"}),
373+ 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}),
374+ 'power_state': ('django.db.models.fields.CharField', [], {'default': "u'unknown'", 'max_length': '10'}),
375+ 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}),
376+ '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'}),
377+ 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}),
378+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}),
379+ 'swap_size': ('django.db.models.fields.BigIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
380+ 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-dfdfe702-1f73-11e5-9405-bcee7b78dc5b'", 'unique': 'True', 'max_length': '41'}),
381+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}),
382+ 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}),
383+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
384+ 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'})
385+ },
386+ u'maasserver.nodegroup': {
387+ 'Meta': {'object_name': 'NodeGroup'},
388+ 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}),
389+ 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}),
390+ 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}),
391+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
392+ 'default_disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
393+ 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
394+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
395+ 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
396+ 'name': ('maasserver.models.nodegroup.DomainNameField', [], {'max_length': '80', 'blank': 'True'}),
397+ 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
398+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
399+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
400+ },
401+ u'maasserver.nodegroupinterface': {
402+ 'Meta': {'unique_together': "((u'nodegroup', u'name'),)", 'object_name': 'NodeGroupInterface'},
403+ 'broadcast_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
404+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
405+ 'foreign_dhcp_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
406+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
407+ 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
408+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}),
409+ 'ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
410+ 'ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
411+ 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
412+ 'name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}),
413+ 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}),
414+ 'router_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
415+ 'static_ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
416+ 'static_ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
417+ 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'}),
418+ 'subnet_mask': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}),
419+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
420+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
421+ },
422+ u'maasserver.partition': {
423+ 'Meta': {'object_name': 'Partition'},
424+ 'bootable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
425+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
426+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
427+ 'partition_table': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'partitions'", 'to': u"orm['maasserver.PartitionTable']"}),
428+ 'size': ('django.db.models.fields.BigIntegerField', [], {}),
429+ 'start_offset': ('django.db.models.fields.BigIntegerField', [], {}),
430+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
431+ 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '36', 'unique': 'True', 'null': 'True', 'blank': 'True'})
432+ },
433+ u'maasserver.partitiontable': {
434+ 'Meta': {'object_name': 'PartitionTable'},
435+ 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']"}),
436+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
437+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
438+ 'table_type': ('django.db.models.fields.CharField', [], {'default': "u'GPT'", 'max_length': '20'}),
439+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
440+ },
441+ u'maasserver.physicalblockdevice': {
442+ 'Meta': {'ordering': "[u'id']", 'object_name': 'PhysicalBlockDevice', '_ormbases': [u'maasserver.BlockDevice']},
443+ u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}),
444+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
445+ 'serial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
446+ },
447+ u'maasserver.space': {
448+ 'Meta': {'object_name': 'Space'},
449+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
450+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
451+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
452+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
453+ },
454+ u'maasserver.sshkey': {
455+ 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'},
456+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
457+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
458+ 'key': ('django.db.models.fields.TextField', [], {}),
459+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
460+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
461+ },
462+ u'maasserver.sslkey': {
463+ 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSLKey'},
464+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
465+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
466+ 'key': ('django.db.models.fields.TextField', [], {}),
467+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
468+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
469+ },
470+ u'maasserver.staticipaddress': {
471+ 'Meta': {'object_name': 'StaticIPAddress'},
472+ 'alloc_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
473+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
474+ 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}),
475+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
476+ 'ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
477+ 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'blank': 'True'}),
478+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
479+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
480+ },
481+ u'maasserver.subnet': {
482+ 'Meta': {'unique_together': "((u'name', u'space'),)", 'object_name': 'Subnet'},
483+ 'cidr': ('maasserver.fields.CIDRField', [], {'unique': 'True'}),
484+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
485+ 'dns_servers': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}),
486+ 'gateway_ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
487+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
488+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
489+ 'space': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Space']", 'on_delete': 'models.PROTECT'}),
490+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
491+ 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'})
492+ },
493+ u'maasserver.tag': {
494+ 'Meta': {'object_name': 'Tag'},
495+ 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
496+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
497+ 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
498+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
499+ 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
500+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
501+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
502+ },
503+ u'maasserver.userprofile': {
504+ 'Meta': {'object_name': 'UserProfile'},
505+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
506+ 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'})
507+ },
508+ u'maasserver.virtualblockdevice': {
509+ 'Meta': {'ordering': "[u'id']", 'object_name': 'VirtualBlockDevice', '_ormbases': [u'maasserver.BlockDevice']},
510+ u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}),
511+ 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'virtual_devices'", 'to': u"orm['maasserver.FilesystemGroup']"}),
512+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'})
513+ },
514+ u'maasserver.vlan': {
515+ 'Meta': {'unique_together': "((u'vid', u'fabric'), (u'name', u'fabric'))", 'object_name': 'VLAN'},
516+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
517+ 'fabric': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Fabric']"}),
518+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
519+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
520+ 'updated': ('django.db.models.fields.DateTimeField', [], {}),
521+ 'vid': ('django.db.models.fields.IntegerField', [], {})
522+ },
523+ u'maasserver.zone': {
524+ 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'},
525+ 'created': ('django.db.models.fields.DateTimeField', [], {}),
526+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
527+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
528+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}),
529+ 'updated': ('django.db.models.fields.DateTimeField', [], {})
530+ },
531+ u'piston.consumer': {
532+ 'Meta': {'object_name': 'Consumer'},
533+ 'description': ('django.db.models.fields.TextField', [], {}),
534+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
535+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
536+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
537+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
538+ 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}),
539+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"})
540+ },
541+ u'piston.token': {
542+ 'Meta': {'object_name': 'Token'},
543+ 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
544+ 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
545+ 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}),
546+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
547+ 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
548+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}),
549+ 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
550+ 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1435701821L'}),
551+ 'token_type': ('django.db.models.fields.IntegerField', [], {}),
552+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}),
553+ 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'})
554+ }
555+ }
556+
557+ complete_apps = ['maasserver']
558
559=== modified file 'src/maasserver/models/blockdevice.py'
560--- src/maasserver/models/blockdevice.py 2015-07-01 21:20:06 +0000
561+++ src/maasserver/models/blockdevice.py 2015-07-02 04:22:18 +0000
562@@ -94,7 +94,7 @@
563
564 class Meta(DefaultMeta):
565 """Needed for South to recognize this model."""
566- unique_together = ("node", "path")
567+ unique_together = ("node", "name")
568 ordering = ["id"]
569
570 objects = BlockDeviceManager()
571@@ -105,10 +105,6 @@
572 max_length=255, blank=False,
573 help_text="Name of block device. (e.g. sda)")
574
575- path = FilePathField(
576- blank=False,
577- help_text="Path of block device. (e.g. /dev/sda)")
578-
579 id_path = FilePathField(
580 blank=True, null=True,
581 help_text="Path of by-id alias. (e.g. /dev/disk/by-id/wwn-0x50004...)")
582@@ -127,6 +123,11 @@
583 dbtype="text", blank=True, null=False, default=[])
584
585 @property
586+ def path(self):
587+ # Path is persistent and set by curtin on deploy.
588+ return "/dev/disk/by-dname/%s" % self.name
589+
590+ @property
591 def type(self):
592 # Circular imports, since PhysicalBlockDevice and VirtualBlockDevice
593 # extend from this calss.
594
595=== modified file 'src/maasserver/models/tests/test_blockdevice.py'
596--- src/maasserver/models/tests/test_blockdevice.py 2015-07-01 21:20:06 +0000
597+++ src/maasserver/models/tests/test_blockdevice.py 2015-07-02 04:22:18 +0000
598@@ -215,6 +215,12 @@
599 class TestBlockDevice(MAASServerTestCase):
600 """Tests for the `BlockDevice` model."""
601
602+ def test_path(self):
603+ block_device = factory.make_PhysicalBlockDevice()
604+ self.assertEquals(
605+ "/dev/disk/by-dname/%s" % block_device.name,
606+ block_device.path)
607+
608 def test_type_physical(self):
609 block_device = factory.make_PhysicalBlockDevice()
610 self.assertEquals("physical", block_device.type)
611
612=== modified file 'src/maasserver/models/tests/test_virtualblockdevice.py'
613--- src/maasserver/models/tests/test_virtualblockdevice.py 2015-07-01 22:06:26 +0000
614+++ src/maasserver/models/tests/test_virtualblockdevice.py 2015-07-02 04:22:18 +0000
615@@ -81,7 +81,7 @@
616 proposed_name = "%s%s" % (prefix, current_idx - 1)
617 self.assertThat(
618 filesystem_group.virtual_device, MatchesStructure.byEquality(
619- name=proposed_name, path="/dev/%s" % proposed_name,
620+ name=proposed_name,
621 size=filesystem_group.get_size(),
622 block_size=(
623 filesystem_group.get_virtual_block_device_block_size())))
624@@ -97,7 +97,7 @@
625 proposed_name = "%s%s" % (prefix, current_idx - 1)
626 self.assertThat(
627 filesystem_group.virtual_device, MatchesStructure.byEquality(
628- name=proposed_name, path="/dev/%s" % proposed_name,
629+ name=proposed_name,
630 size=filesystem_group.get_size(),
631 block_size=(
632 filesystem_group.get_virtual_block_device_block_size())))
633
634=== modified file 'src/maasserver/models/virtualblockdevice.py'
635--- src/maasserver/models/virtualblockdevice.py 2015-07-01 21:20:06 +0000
636+++ src/maasserver/models/virtualblockdevice.py 2015-07-02 04:22:18 +0000
637@@ -73,8 +73,7 @@
638 name = self.get_available_name_for(filesystem_group)
639 block_device = VirtualBlockDevice(
640 node=filesystem_group.get_node(),
641- name=name, path="/dev/%s" % name,
642- filesystem_group=filesystem_group)
643+ name=name, filesystem_group=filesystem_group)
644 block_device.size = filesystem_group.get_size()
645 block_device.block_size = (
646 filesystem_group.get_virtual_block_device_block_size())
647
648=== modified file 'src/maasserver/testing/factory.py'
649--- src/maasserver/testing/factory.py 2015-07-01 21:13:08 +0000
650+++ src/maasserver/testing/factory.py 2015-07-02 04:22:18 +0000
651@@ -1150,14 +1150,12 @@
652 return resource
653
654 def make_BlockDevice(
655- self, node=None, name=None, path=None, id_path=None, size=None,
656+ self, node=None, name=None, id_path=None, size=None,
657 block_size=None, tags=None):
658 if node is None:
659 node = self.make_Node()
660 if name is None:
661 name = self.make_name('name')
662- if path is None:
663- path = '/dev/%s' % name
664 if id_path is None:
665 id_path = '/dev/disk/by-id/id_%s' % name
666 if block_size is None:
667@@ -1167,18 +1165,18 @@
668 if tags is None:
669 tags = [self.make_name('tag') for _ in range(3)]
670 return BlockDevice.objects.create(
671- node=node, name=name, path=path, size=size, block_size=block_size,
672+ node=node, name=name, size=size, block_size=block_size,
673 tags=tags)
674
675 def make_PhysicalBlockDevice(
676- self, node=None, name=None, path=None, size=None, block_size=None,
677+ self, node=None, name=None, size=None, block_size=None,
678 tags=None, model=None, serial=None):
679 if node is None:
680 node = self.make_Node()
681 if name is None:
682 name = self.make_name('name')
683- if path is None:
684- path = '/dev/%s' % name
685+ if size is None:
686+ size = random.randint(1000 * 1000, 1000 * 1000 * 1000)
687 if block_size is None:
688 block_size = random.choice([512, 1024, 4096])
689 if size is None:
690@@ -1190,7 +1188,7 @@
691 if serial is None:
692 serial = self.make_name('serial')
693 return PhysicalBlockDevice.objects.create(
694- node=node, name=name, path=path, size=size, block_size=block_size,
695+ node=node, name=name, size=size, block_size=block_size,
696 tags=tags, model=model, serial=serial)
697
698 def make_PartitionTable(self, table_type=None, block_device=None):
699@@ -1320,7 +1318,7 @@
700 return group
701
702 def make_VirtualBlockDevice(
703- self, name=None, path=None, size=None, block_size=None,
704+ self, name=None, size=None, block_size=None,
705 tags=None, uuid=None, filesystem_group=None, node=None):
706 if node is None:
707 node = factory.make_Node()
708@@ -1346,11 +1344,12 @@
709 "VirtualBlockDevice automatically.")
710 if name is None:
711 name = self.make_name("device")
712- if path is None:
713- path = "/dev/mapper/%s-%s" % (filesystem_group.name, name)
714-
715+ if size is None:
716+ size = random.randint(1, filesystem_group.get_size())
717+ if block_size is None:
718+ block_size = random.choice([512, 1024, 4096])
719 return VirtualBlockDevice.objects.create(
720- name=name, path=path, size=size, block_size=block_size,
721+ name=name, size=size, block_size=block_size,
722 tags=tags, uuid=uuid, filesystem_group=filesystem_group)
723
724
725
726=== modified file 'src/metadataserver/models/commissioningscript.py'
727--- src/metadataserver/models/commissioningscript.py 2015-06-29 17:34:52 +0000
728+++ src/metadataserver/models/commissioningscript.py 2015-07-02 04:22:18 +0000
729@@ -621,7 +621,6 @@
730 PhysicalBlockDevice.objects.create(
731 node=node,
732 name=block_info["NAME"],
733- path=block_info["PATH"],
734 id_path=block_info.get("ID_PATH"),
735 size=long(block_info["SIZE"]),
736 block_size=int(block_info["BLOCK_SIZE"]),
737
738=== modified file 'src/metadataserver/models/tests/test_noderesults.py'
739--- src/metadataserver/models/tests/test_noderesults.py 2015-06-29 17:34:52 +0000
740+++ src/metadataserver/models/tests/test_noderesults.py 2015-07-02 04:22:18 +0000
741@@ -1015,14 +1015,13 @@
742
743 def test__creates_physical_block_device(self):
744 name = factory.make_name('name')
745- path = '/dev/%s' % name
746 id_path = '/dev/disk/by-id/deviceid'
747 size = random.randint(1000 * 1000, 1000 * 1000 * 1000)
748 block_size = random.choice([512, 1024, 4096])
749 model = factory.make_name('model')
750 serial = factory.make_name('serial')
751 device = self.make_block_device(
752- name=name, path=path, size=size, block_size=block_size,
753+ name=name, size=size, block_size=block_size,
754 model=model, serial=serial)
755 node = factory.make_Node()
756 json_output = json.dumps([device]).encode('utf-8')
757@@ -1030,7 +1029,7 @@
758 self.assertThat(
759 PhysicalBlockDevice.objects.filter(node=node).first(),
760 MatchesStructure.byEquality(
761- name=name, path=path, id_path=id_path, size=size,
762+ name=name, id_path=id_path, size=size,
763 block_size=block_size, model=model, serial=serial))
764
765 def test__creates_physical_block_device_only_for_node(self):