Merge lp:~blake-rouse/maas/fix-vlan-to-untagged into lp:~maas-committers/maas/trunk
- fix-vlan-to-untagged
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Blake Rouse |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4370 |
Proposed branch: | lp:~blake-rouse/maas/fix-vlan-to-untagged |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
1262 lines (+742/-63) 26 files modified
src/maasserver/api/fabrics.py (+5/-0) src/maasserver/api/tests/test_fabrics.py (+1/-11) src/maasserver/api/tests/test_vlans.py (+3/-4) src/maasserver/api/vlans.py (+6/-1) src/maasserver/context_processors.py (+1/-0) src/maasserver/fixtures/dev_fixture.yaml (+4/-4) src/maasserver/forms_vlan.py (+8/-0) src/maasserver/migrations/0183_remove_required_name_from_vlan_and_fabric.py (+519/-0) src/maasserver/models/fabric.py (+8/-1) src/maasserver/models/tests/test_fabric.py (+9/-0) src/maasserver/models/tests/test_vlan.py (+9/-0) src/maasserver/models/vlan.py (+10/-4) src/maasserver/static/js/angular/controllers/node_details_networking.js (+28/-3) src/maasserver/static/js/angular/controllers/subnets_list.js (+3/-1) src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js (+58/-11) src/maasserver/static/js/angular/filters/remove_default_vlan.js (+17/-0) src/maasserver/static/js/angular/filters/tests/test_remove_default_vlan.js (+30/-0) src/maasserver/static/partials/node-details.html (+6/-6) src/maasserver/testing/factory.py (+0/-4) src/maasserver/tests/test_forms_fabric.py (+0/-7) src/maasserver/tests/test_forms_space.py (+2/-2) src/maasserver/tests/test_forms_vlan.py (+11/-2) src/maasserver/websockets/handlers/fabric.py (+1/-0) src/maasserver/websockets/handlers/tests/test_fabric.py (+1/-1) src/maasserver/websockets/handlers/tests/test_vlan.py (+1/-1) src/maasserver/websockets/handlers/vlan.py (+1/-0) |
To merge this branch: | bzr merge lp:~blake-rouse/maas/fix-vlan-to-untagged |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Blake Rouse (community) | Approve | ||
Mike Pontillo (community) | Approve | ||
Review via email: mp+273948@code.launchpad.net |
Commit message
Remove the requirement of names on fabric and vlan. Fix fabric name and vlan name based on the id and vid respectively. Fix the UI to not allow the VLAN editing on physical interfaces. Fix other small UI issues with node networking. Prevent the default VLAN from being editable on a fabric.
Description of the change
Blake Rouse (blake-rouse) wrote : | # |
Thanks for the review. I added it to the commit message.
MAAS Lander (maas-lander) wrote : | # |
The attempt to merge lp:~blake-rouse/maas/fix-vlan-to-untagged into lp:maas failed. Below is the output from the failed tests.
Hit http://
Ign http://
Get:1 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Get:2 http://
Get:3 http://
Get:4 http://
Get:5 http://
Get:6 http://
Get:7 http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Hit http://
Ign http://
Ign http://
Fetched 1,868 kB in 4s (466 kB/s)
Reading package lists...
sudo DEBIAN_
--
Preview Diff
1 | === modified file 'src/maasserver/api/fabrics.py' | |||
2 | --- src/maasserver/api/fabrics.py 2015-08-18 15:10:54 +0000 | |||
3 | +++ src/maasserver/api/fabrics.py 2015-10-09 21:26:30 +0000 | |||
4 | @@ -75,6 +75,11 @@ | |||
5 | 75 | return ('fabric_handler', (fabric_id,)) | 75 | return ('fabric_handler', (fabric_id,)) |
6 | 76 | 76 | ||
7 | 77 | @classmethod | 77 | @classmethod |
8 | 78 | def name(cls, fabric): | ||
9 | 79 | """Return the name of the fabric.""" | ||
10 | 80 | return fabric.get_name() | ||
11 | 81 | |||
12 | 82 | @classmethod | ||
13 | 78 | def vlans(cls, fabric): | 83 | def vlans(cls, fabric): |
14 | 79 | """Return VLANs within the specified fabric.""" | 84 | """Return VLANs within the specified fabric.""" |
15 | 80 | return fabric.vlan_set.all() | 85 | return fabric.vlan_set.all() |
16 | 81 | 86 | ||
17 | === modified file 'src/maasserver/api/tests/test_fabrics.py' | |||
18 | --- src/maasserver/api/tests/test_fabrics.py 2015-08-13 19:29:08 +0000 | |||
19 | +++ src/maasserver/api/tests/test_fabrics.py 2015-10-09 21:26:30 +0000 | |||
20 | @@ -82,16 +82,6 @@ | |||
21 | 82 | self.assertEqual( | 82 | self.assertEqual( |
22 | 83 | httplib.FORBIDDEN, response.status_code, response.content) | 83 | httplib.FORBIDDEN, response.status_code, response.content) |
23 | 84 | 84 | ||
24 | 85 | def test_create_requires_name(self): | ||
25 | 86 | self.become_admin() | ||
26 | 87 | uri = get_fabrics_uri() | ||
27 | 88 | response = self.client.post(uri, {}) | ||
28 | 89 | self.assertEqual( | ||
29 | 90 | httplib.BAD_REQUEST, response.status_code, response.content) | ||
30 | 91 | self.assertEqual({ | ||
31 | 92 | "name": ["This field is required."], | ||
32 | 93 | }, json.loads(response.content)) | ||
33 | 94 | |||
34 | 95 | 85 | ||
35 | 96 | class TestFabricAPI(APITestCase): | 86 | class TestFabricAPI(APITestCase): |
36 | 97 | 87 | ||
37 | @@ -112,7 +102,7 @@ | |||
38 | 112 | parsed_fabric = json.loads(response.content) | 102 | parsed_fabric = json.loads(response.content) |
39 | 113 | self.assertThat(parsed_fabric, ContainsDict({ | 103 | self.assertThat(parsed_fabric, ContainsDict({ |
40 | 114 | "id": Equals(fabric.id), | 104 | "id": Equals(fabric.id), |
42 | 115 | "name": Equals(fabric.name), | 105 | "name": Equals(fabric.get_name()), |
43 | 116 | })) | 106 | })) |
44 | 117 | self.assertItemsEqual([ | 107 | self.assertItemsEqual([ |
45 | 118 | vlan.id | 108 | vlan.id |
46 | 119 | 109 | ||
47 | === modified file 'src/maasserver/api/tests/test_vlans.py' | |||
48 | --- src/maasserver/api/tests/test_vlans.py 2015-08-15 00:08:54 +0000 | |||
49 | +++ src/maasserver/api/tests/test_vlans.py 2015-10-09 21:26:30 +0000 | |||
50 | @@ -93,7 +93,7 @@ | |||
51 | 93 | self.assertEqual( | 93 | self.assertEqual( |
52 | 94 | httplib.FORBIDDEN, response.status_code, response.content) | 94 | httplib.FORBIDDEN, response.status_code, response.content) |
53 | 95 | 95 | ||
55 | 96 | def test_create_requires_name_and_vid(self): | 96 | def test_create_requires_vid(self): |
56 | 97 | self.become_admin() | 97 | self.become_admin() |
57 | 98 | fabric = factory.make_Fabric() | 98 | fabric = factory.make_Fabric() |
58 | 99 | uri = get_vlans_uri(fabric) | 99 | uri = get_vlans_uri(fabric) |
59 | @@ -101,7 +101,6 @@ | |||
60 | 101 | self.assertEqual( | 101 | self.assertEqual( |
61 | 102 | httplib.BAD_REQUEST, response.status_code, response.content) | 102 | httplib.BAD_REQUEST, response.status_code, response.content) |
62 | 103 | self.assertEqual({ | 103 | self.assertEqual({ |
63 | 104 | "name": ["This field is required."], | ||
64 | 105 | "vid": [ | 104 | "vid": [ |
65 | 106 | "This field is required.", | 105 | "This field is required.", |
66 | 107 | "Vid must be between 0 and 4095."], | 106 | "Vid must be between 0 and 4095."], |
67 | @@ -128,9 +127,9 @@ | |||
68 | 128 | parsed_vlan = json.loads(response.content) | 127 | parsed_vlan = json.loads(response.content) |
69 | 129 | self.assertThat(parsed_vlan, ContainsDict({ | 128 | self.assertThat(parsed_vlan, ContainsDict({ |
70 | 130 | "id": Equals(vlan.id), | 129 | "id": Equals(vlan.id), |
72 | 131 | "name": Equals(vlan.name), | 130 | "name": Equals(vlan.get_name()), |
73 | 132 | "vid": Equals(vlan.vid), | 131 | "vid": Equals(vlan.vid), |
75 | 133 | "fabric": Equals(fabric.name), | 132 | "fabric": Equals(fabric.get_name()), |
76 | 134 | "resource_uri": Equals(get_vlan_uri(vlan)), | 133 | "resource_uri": Equals(get_vlan_uri(vlan)), |
77 | 135 | })) | 134 | })) |
78 | 136 | 135 | ||
79 | 137 | 136 | ||
80 | === modified file 'src/maasserver/api/vlans.py' | |||
81 | --- src/maasserver/api/vlans.py 2015-08-18 15:25:03 +0000 | |||
82 | +++ src/maasserver/api/vlans.py 2015-10-09 21:26:30 +0000 | |||
83 | @@ -90,7 +90,12 @@ | |||
84 | 90 | @classmethod | 90 | @classmethod |
85 | 91 | def fabric(cls, vlan): | 91 | def fabric(cls, vlan): |
86 | 92 | """Return fabric name.""" | 92 | """Return fabric name.""" |
88 | 93 | return vlan.fabric.name | 93 | return vlan.fabric.get_name() |
89 | 94 | |||
90 | 95 | @classmethod | ||
91 | 96 | def name(cls, vlan): | ||
92 | 97 | """Return the VLAN name.""" | ||
93 | 98 | return vlan.get_name() | ||
94 | 94 | 99 | ||
95 | 95 | def read(self, request, fabric_id, vlan_id): | 100 | def read(self, request, fabric_id, vlan_id): |
96 | 96 | """Read VLAN on fabric. | 101 | """Read VLAN on fabric. |
97 | 97 | 102 | ||
98 | === modified file 'src/maasserver/context_processors.py' | |||
99 | --- src/maasserver/context_processors.py 2015-09-30 22:30:55 +0000 | |||
100 | +++ src/maasserver/context_processors.py 2015-10-09 21:26:30 +0000 | |||
101 | @@ -76,6 +76,7 @@ | |||
102 | 76 | 'js/angular/filters/by_fabric.js', | 76 | 'js/angular/filters/by_fabric.js', |
103 | 77 | 'js/angular/filters/by_vlan.js', | 77 | 'js/angular/filters/by_vlan.js', |
104 | 78 | 'js/angular/filters/by_space.js', | 78 | 'js/angular/filters/by_space.js', |
105 | 79 | 'js/angular/filters/remove_default_vlan.js', | ||
106 | 79 | 'js/angular/controllers/error.js', | 80 | 'js/angular/controllers/error.js', |
107 | 80 | 'js/angular/controllers/nodes_list.js', | 81 | 'js/angular/controllers/nodes_list.js', |
108 | 81 | 'js/angular/controllers/add_hardware.js', | 82 | 'js/angular/controllers/add_hardware.js', |
109 | 82 | 83 | ||
110 | === modified file 'src/maasserver/fixtures/dev_fixture.yaml' | |||
111 | --- src/maasserver/fixtures/dev_fixture.yaml 2015-09-27 20:01:05 +0000 | |||
112 | +++ src/maasserver/fixtures/dev_fixture.yaml 2015-10-09 21:26:30 +0000 | |||
113 | @@ -9484,11 +9484,11 @@ | |||
114 | 9484 | updated: ! '2015-09-18 15:38:26.981744'} | 9484 | updated: ! '2015-09-18 15:38:26.981744'} |
115 | 9485 | model: maasserver.event | 9485 | model: maasserver.event |
116 | 9486 | pk: 236 | 9486 | pk: 236 |
118 | 9487 | - fields: {created: ! '2015-09-18 15:14:45.727015', name: Default fabric, updated: ! '2015-09-18 | 9487 | - fields: {created: ! '2015-09-18 15:14:45.727015', updated: ! '2015-09-18 |
119 | 9488 | 15:14:45.727015'} | 9488 | 15:14:45.727015'} |
120 | 9489 | model: maasserver.fabric | 9489 | model: maasserver.fabric |
121 | 9490 | pk: 0 | 9490 | pk: 0 |
123 | 9491 | - fields: {created: ! '2015-09-18 15:14:45.727015', name: Extra fabric, updated: ! '2015-09-18 | 9491 | - fields: {created: ! '2015-09-18 15:14:45.727015', updated: ! '2015-09-18 |
124 | 9492 | 15:14:45.727015'} | 9492 | 15:14:45.727015'} |
125 | 9493 | model: maasserver.fabric | 9493 | model: maasserver.fabric |
126 | 9494 | pk: 1 | 9494 | pk: 1 |
127 | @@ -9512,11 +9512,11 @@ | |||
128 | 9512 | - fields: {filesystem_group: 4, uuid: 3a140acf-6a98-4572-aa2f-3de2ba56b818} | 9512 | - fields: {filesystem_group: 4, uuid: 3a140acf-6a98-4572-aa2f-3de2ba56b818} |
129 | 9513 | model: maasserver.virtualblockdevice | 9513 | model: maasserver.virtualblockdevice |
130 | 9514 | pk: 12 | 9514 | pk: 12 |
132 | 9515 | - fields: {created: ! '2015-09-18 15:14:45.727015', fabric: 0, name: Default VLAN, | 9515 | - fields: {created: ! '2015-09-18 15:14:45.727015', fabric: 0, |
133 | 9516 | updated: ! '2015-09-18 15:14:45.727015', vid: 0} | 9516 | updated: ! '2015-09-18 15:14:45.727015', vid: 0} |
134 | 9517 | model: maasserver.vlan | 9517 | model: maasserver.vlan |
135 | 9518 | pk: 0 | 9518 | pk: 0 |
137 | 9519 | - fields: {created: ! '2015-09-18 15:14:45.727015', fabric: 1, name: Extra VLAN, | 9519 | - fields: {created: ! '2015-09-18 15:14:45.727015', fabric: 1, |
138 | 9520 | updated: ! '2015-09-18 15:14:45.727015', vid: 0} | 9520 | updated: ! '2015-09-18 15:14:45.727015', vid: 0} |
139 | 9521 | model: maasserver.vlan | 9521 | model: maasserver.vlan |
140 | 9522 | pk: 1 | 9522 | pk: 1 |
141 | 9523 | 9523 | ||
142 | === modified file 'src/maasserver/forms_vlan.py' | |||
143 | --- src/maasserver/forms_vlan.py 2015-08-14 14:00:46 +0000 | |||
144 | +++ src/maasserver/forms_vlan.py 2015-10-09 21:26:30 +0000 | |||
145 | @@ -16,6 +16,7 @@ | |||
146 | 16 | "VLANForm", | 16 | "VLANForm", |
147 | 17 | ] | 17 | ] |
148 | 18 | 18 | ||
149 | 19 | from django.core.exceptions import ValidationError | ||
150 | 19 | from maasserver.forms import MAASModelForm | 20 | from maasserver.forms import MAASModelForm |
151 | 20 | from maasserver.models.vlan import VLAN | 21 | from maasserver.models.vlan import VLAN |
152 | 21 | 22 | ||
153 | @@ -37,6 +38,13 @@ | |||
154 | 37 | if instance is None and self.fabric is None: | 38 | if instance is None and self.fabric is None: |
155 | 38 | raise ValueError("Form requires either a instance or a fabric.") | 39 | raise ValueError("Form requires either a instance or a fabric.") |
156 | 39 | 40 | ||
157 | 41 | def clean(self): | ||
158 | 42 | cleaned_data = super(VLANForm, self).clean() | ||
159 | 43 | if self.instance.id is not None and self.instance.is_fabric_default(): | ||
160 | 44 | raise ValidationError( | ||
161 | 45 | "Cannot modify the default VLAN for a fabric.") | ||
162 | 46 | return cleaned_data | ||
163 | 47 | |||
164 | 40 | def save(self): | 48 | def save(self): |
165 | 41 | """Persist the interface into the database.""" | 49 | """Persist the interface into the database.""" |
166 | 42 | interface = super(VLANForm, self).save(commit=False) | 50 | interface = super(VLANForm, self).save(commit=False) |
167 | 43 | 51 | ||
168 | === added file 'src/maasserver/migrations/0183_remove_required_name_from_vlan_and_fabric.py' | |||
169 | --- src/maasserver/migrations/0183_remove_required_name_from_vlan_and_fabric.py 1970-01-01 00:00:00 +0000 | |||
170 | +++ src/maasserver/migrations/0183_remove_required_name_from_vlan_and_fabric.py 2015-10-09 21:26:30 +0000 | |||
171 | @@ -0,0 +1,519 @@ | |||
172 | 1 | from django.db import models | ||
173 | 2 | from south.db import db | ||
174 | 3 | # -*- coding: utf-8 -*- | ||
175 | 4 | from south.utils import datetime_utils as datetime | ||
176 | 5 | from south.v2 import SchemaMigration | ||
177 | 6 | |||
178 | 7 | |||
179 | 8 | class Migration(SchemaMigration): | ||
180 | 9 | |||
181 | 10 | def forwards(self, orm): | ||
182 | 11 | # Removing unique constraint on 'Fabric', fields ['name'] | ||
183 | 12 | db.delete_unique(u'maasserver_fabric', ['name']) | ||
184 | 13 | |||
185 | 14 | # Removing unique constraint on 'VLAN', fields ['name', 'fabric'] | ||
186 | 15 | db.delete_unique(u'maasserver_vlan', ['name', 'fabric_id']) | ||
187 | 16 | |||
188 | 17 | |||
189 | 18 | # Changing field 'VLAN.name' | ||
190 | 19 | db.alter_column(u'maasserver_vlan', 'name', self.gf('django.db.models.fields.CharField')(max_length=256, null=True)) | ||
191 | 20 | |||
192 | 21 | # Changing field 'Fabric.name' | ||
193 | 22 | db.alter_column(u'maasserver_fabric', 'name', self.gf('django.db.models.fields.CharField')(max_length=256, null=True)) | ||
194 | 23 | |||
195 | 24 | def backwards(self, orm): | ||
196 | 25 | |||
197 | 26 | # User chose to not deal with backwards NULL issues for 'VLAN.name' | ||
198 | 27 | raise RuntimeError("Cannot reverse this migration. 'VLAN.name' and its values cannot be restored.") | ||
199 | 28 | # Adding unique constraint on 'VLAN', fields ['name', 'fabric'] | ||
200 | 29 | db.create_unique(u'maasserver_vlan', ['name', 'fabric_id']) | ||
201 | 30 | |||
202 | 31 | |||
203 | 32 | # User chose to not deal with backwards NULL issues for 'Fabric.name' | ||
204 | 33 | raise RuntimeError("Cannot reverse this migration. 'Fabric.name' and its values cannot be restored.") | ||
205 | 34 | # Adding unique constraint on 'Fabric', fields ['name'] | ||
206 | 35 | db.create_unique(u'maasserver_fabric', ['name']) | ||
207 | 36 | |||
208 | 37 | |||
209 | 38 | models = { | ||
210 | 39 | u'auth.group': { | ||
211 | 40 | 'Meta': {'object_name': 'Group'}, | ||
212 | 41 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
213 | 42 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
214 | 43 | 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
215 | 44 | }, | ||
216 | 45 | u'auth.permission': { | ||
217 | 46 | 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, | ||
218 | 47 | 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
219 | 48 | 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), | ||
220 | 49 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
221 | 50 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
222 | 51 | }, | ||
223 | 52 | u'auth.user': { | ||
224 | 53 | 'Meta': {'object_name': 'User'}, | ||
225 | 54 | 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
226 | 55 | 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}), | ||
227 | 56 | 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
228 | 57 | 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), | ||
229 | 58 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
230 | 59 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
231 | 60 | 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
232 | 61 | 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
233 | 62 | 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
234 | 63 | 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
235 | 64 | 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
236 | 65 | 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), | ||
237 | 66 | 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
238 | 67 | }, | ||
239 | 68 | u'contenttypes.contenttype': { | ||
240 | 69 | 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
241 | 70 | 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
242 | 71 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
243 | 72 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
244 | 73 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
245 | 74 | }, | ||
246 | 75 | u'maasserver.blockdevice': { | ||
247 | 76 | 'Meta': {'ordering': "[u'id']", 'unique_together': "((u'node', u'name'),)", 'object_name': 'BlockDevice'}, | ||
248 | 77 | 'block_size': ('django.db.models.fields.IntegerField', [], {}), | ||
249 | 78 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
250 | 79 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
251 | 80 | 'id_path': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), | ||
252 | 81 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
253 | 82 | 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}), | ||
254 | 83 | 'size': ('django.db.models.fields.BigIntegerField', [], {}), | ||
255 | 84 | 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}), | ||
256 | 85 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
257 | 86 | }, | ||
258 | 87 | u'maasserver.bootresource': { | ||
259 | 88 | 'Meta': {'unique_together': "((u'name', u'architecture'),)", 'object_name': 'BootResource'}, | ||
260 | 89 | 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
261 | 90 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
262 | 91 | 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
263 | 92 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
264 | 93 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
265 | 94 | 'rtype': ('django.db.models.fields.IntegerField', [], {'max_length': '10'}), | ||
266 | 95 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
267 | 96 | }, | ||
268 | 97 | u'maasserver.bootresourcefile': { | ||
269 | 98 | 'Meta': {'unique_together': "((u'resource_set', u'filetype'),)", 'object_name': 'BootResourceFile'}, | ||
270 | 99 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
271 | 100 | 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
272 | 101 | 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
273 | 102 | 'filetype': ('django.db.models.fields.CharField', [], {'default': "u'root-tgz'", 'max_length': '20'}), | ||
274 | 103 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
275 | 104 | 'largefile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.LargeFile']"}), | ||
276 | 105 | 'resource_set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'files'", 'to': u"orm['maasserver.BootResourceSet']"}), | ||
277 | 106 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
278 | 107 | }, | ||
279 | 108 | u'maasserver.bootresourceset': { | ||
280 | 109 | 'Meta': {'unique_together': "((u'resource', u'version'),)", 'object_name': 'BootResourceSet'}, | ||
281 | 110 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
282 | 111 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
283 | 112 | 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
284 | 113 | 'resource': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'sets'", 'to': u"orm['maasserver.BootResource']"}), | ||
285 | 114 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
286 | 115 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '255'}) | ||
287 | 116 | }, | ||
288 | 117 | u'maasserver.bootsource': { | ||
289 | 118 | 'Meta': {'object_name': 'BootSource'}, | ||
290 | 119 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
291 | 120 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
292 | 121 | 'keyring_data': ('maasserver.fields.EditableBinaryField', [], {'blank': 'True'}), | ||
293 | 122 | 'keyring_filename': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}), | ||
294 | 123 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
295 | 124 | 'url': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '200'}) | ||
296 | 125 | }, | ||
297 | 126 | u'maasserver.bootsourcecache': { | ||
298 | 127 | 'Meta': {'object_name': 'BootSourceCache'}, | ||
299 | 128 | 'arch': ('django.db.models.fields.CharField', [], {'max_length': '20'}), | ||
300 | 129 | 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}), | ||
301 | 130 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
302 | 131 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
303 | 132 | 'label': ('django.db.models.fields.CharField', [], {'max_length': '20'}), | ||
304 | 133 | 'os': ('django.db.models.fields.CharField', [], {'max_length': '20'}), | ||
305 | 134 | 'release': ('django.db.models.fields.CharField', [], {'max_length': '20'}), | ||
306 | 135 | 'subarch': ('django.db.models.fields.CharField', [], {'max_length': '20'}), | ||
307 | 136 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
308 | 137 | }, | ||
309 | 138 | u'maasserver.bootsourceselection': { | ||
310 | 139 | 'Meta': {'unique_together': "((u'boot_source', u'os', u'release'),)", 'object_name': 'BootSourceSelection'}, | ||
311 | 140 | 'arches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), | ||
312 | 141 | 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}), | ||
313 | 142 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
314 | 143 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
315 | 144 | 'labels': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), | ||
316 | 145 | 'os': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
317 | 146 | 'release': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
318 | 147 | 'subarches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), | ||
319 | 148 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
320 | 149 | }, | ||
321 | 150 | u'maasserver.cacheset': { | ||
322 | 151 | 'Meta': {'object_name': 'CacheSet'}, | ||
323 | 152 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
324 | 153 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
325 | 154 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
326 | 155 | }, | ||
327 | 156 | u'maasserver.candidatename': { | ||
328 | 157 | 'Meta': {'unique_together': "((u'name', u'position'),)", 'object_name': 'CandidateName'}, | ||
329 | 158 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
330 | 159 | 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), | ||
331 | 160 | 'position': ('django.db.models.fields.IntegerField', [], {}) | ||
332 | 161 | }, | ||
333 | 162 | u'maasserver.componenterror': { | ||
334 | 163 | 'Meta': {'object_name': 'ComponentError'}, | ||
335 | 164 | 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}), | ||
336 | 165 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
337 | 166 | 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), | ||
338 | 167 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
339 | 168 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
340 | 169 | }, | ||
341 | 170 | u'maasserver.config': { | ||
342 | 171 | 'Meta': {'object_name': 'Config'}, | ||
343 | 172 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
344 | 173 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), | ||
345 | 174 | 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'}) | ||
346 | 175 | }, | ||
347 | 176 | u'maasserver.downloadprogress': { | ||
348 | 177 | 'Meta': {'object_name': 'DownloadProgress'}, | ||
349 | 178 | 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
350 | 179 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
351 | 180 | 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}), | ||
352 | 181 | 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
353 | 182 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
354 | 183 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), | ||
355 | 184 | 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
356 | 185 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
357 | 186 | }, | ||
358 | 187 | u'maasserver.event': { | ||
359 | 188 | 'Meta': {'object_name': 'Event'}, | ||
360 | 189 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
361 | 190 | 'description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}), | ||
362 | 191 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
363 | 192 | 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}), | ||
364 | 193 | 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.EventType']"}), | ||
365 | 194 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
366 | 195 | }, | ||
367 | 196 | u'maasserver.eventtype': { | ||
368 | 197 | 'Meta': {'object_name': 'EventType'}, | ||
369 | 198 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
370 | 199 | 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
371 | 200 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
372 | 201 | 'level': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), | ||
373 | 202 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), | ||
374 | 203 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
375 | 204 | }, | ||
376 | 205 | u'maasserver.fabric': { | ||
377 | 206 | 'Meta': {'object_name': 'Fabric'}, | ||
378 | 207 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
379 | 208 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
380 | 209 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}), | ||
381 | 210 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
382 | 211 | }, | ||
383 | 212 | u'maasserver.fannetwork': { | ||
384 | 213 | 'Meta': {'object_name': 'FanNetwork'}, | ||
385 | 214 | 'bridge': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
386 | 215 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
387 | 216 | 'dhcp': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), | ||
388 | 217 | 'host_reserve': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'null': 'True', 'blank': 'True'}), | ||
389 | 218 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
390 | 219 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), | ||
391 | 220 | 'off': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}), | ||
392 | 221 | 'overlay': ('maasserver.fields.IPv4CIDRField', [], {'unique': 'True'}), | ||
393 | 222 | 'underlay': ('maasserver.fields.IPv4CIDRField', [], {'unique': 'True'}), | ||
394 | 223 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
395 | 224 | }, | ||
396 | 225 | u'maasserver.filestorage': { | ||
397 | 226 | 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'}, | ||
398 | 227 | 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}), | ||
399 | 228 | 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
400 | 229 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
401 | 230 | 'key': ('django.db.models.fields.CharField', [], {'default': "u'a1d75a4c-6e44-11e5-a1dc-c48e8ffbb365'", 'unique': 'True', 'max_length': '36'}), | ||
402 | 231 | 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) | ||
403 | 232 | }, | ||
404 | 233 | u'maasserver.filesystem': { | ||
405 | 234 | 'Meta': {'unique_together': "((u'partition', u'acquired'), (u'block_device', u'acquired'))", 'object_name': 'Filesystem'}, | ||
406 | 235 | 'acquired': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
407 | 236 | 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']", 'null': 'True', 'blank': 'True'}), | ||
408 | 237 | 'cache_set': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.CacheSet']"}), | ||
409 | 238 | 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
410 | 239 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
411 | 240 | 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'filesystems'", 'null': 'True', 'to': u"orm['maasserver.FilesystemGroup']"}), | ||
412 | 241 | 'fstype': ('django.db.models.fields.CharField', [], {'default': "u'ext4'", 'max_length': '20'}), | ||
413 | 242 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
414 | 243 | 'label': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
415 | 244 | 'mount_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
416 | 245 | 'mount_point': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
417 | 246 | 'partition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Partition']", 'null': 'True', 'blank': 'True'}), | ||
418 | 247 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
419 | 248 | 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '36'}) | ||
420 | 249 | }, | ||
421 | 250 | u'maasserver.filesystemgroup': { | ||
422 | 251 | 'Meta': {'object_name': 'FilesystemGroup'}, | ||
423 | 252 | 'cache_mode': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), | ||
424 | 253 | 'cache_set': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.CacheSet']", 'null': 'True', 'blank': 'True'}), | ||
425 | 254 | 'create_params': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
426 | 255 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
427 | 256 | 'group_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}), | ||
428 | 257 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
429 | 258 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
430 | 259 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
431 | 260 | 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) | ||
432 | 261 | }, | ||
433 | 262 | u'maasserver.interface': { | ||
434 | 263 | 'Meta': {'ordering': "(u'created',)", 'object_name': 'Interface'}, | ||
435 | 264 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
436 | 265 | 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
437 | 266 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
438 | 267 | 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.StaticIPAddress']", 'null': 'True', 'blank': 'True'}), | ||
439 | 268 | 'ipv4_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
440 | 269 | 'ipv6_params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
441 | 270 | 'mac_address': ('maasserver.fields.MACAddressField', [], {'null': 'True', 'blank': 'True'}), | ||
442 | 271 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
443 | 272 | 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']", 'null': 'True', 'blank': 'True'}), | ||
444 | 273 | 'params': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
445 | 274 | 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['maasserver.Interface']", 'null': 'True', 'through': u"orm['maasserver.InterfaceRelationship']", 'blank': 'True'}), | ||
446 | 275 | 'tags': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'blank': 'True'}), | ||
447 | 276 | 'type': ('django.db.models.fields.CharField', [], {'max_length': '20'}), | ||
448 | 277 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
449 | 278 | 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'}) | ||
450 | 279 | }, | ||
451 | 280 | u'maasserver.interfacerelationship': { | ||
452 | 281 | 'Meta': {'object_name': 'InterfaceRelationship'}, | ||
453 | 282 | 'child': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'parent_relationships'", 'to': u"orm['maasserver.Interface']"}), | ||
454 | 283 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
455 | 284 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
456 | 285 | 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'children_relationships'", 'to': u"orm['maasserver.Interface']"}), | ||
457 | 286 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
458 | 287 | }, | ||
459 | 288 | u'maasserver.largefile': { | ||
460 | 289 | 'Meta': {'object_name': 'LargeFile'}, | ||
461 | 290 | 'content': ('maasserver.fields.LargeObjectField', [], {}), | ||
462 | 291 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
463 | 292 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
464 | 293 | 'sha256': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), | ||
465 | 294 | 'total_size': ('django.db.models.fields.BigIntegerField', [], {}), | ||
466 | 295 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
467 | 296 | }, | ||
468 | 297 | u'maasserver.licensekey': { | ||
469 | 298 | 'Meta': {'unique_together': "((u'osystem', u'distro_series'),)", 'object_name': 'LicenseKey'}, | ||
470 | 299 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
471 | 300 | 'distro_series': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
472 | 301 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
473 | 302 | 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
474 | 303 | 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
475 | 304 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
476 | 305 | }, | ||
477 | 306 | u'maasserver.node': { | ||
478 | 307 | 'Meta': {'object_name': 'Node'}, | ||
479 | 308 | 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
480 | 309 | 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), | ||
481 | 310 | 'bios_boot_method': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), | ||
482 | 311 | 'block_poweroff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
483 | 312 | 'boot_cluster_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
484 | 313 | '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'}), | ||
485 | 314 | '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'}), | ||
486 | 315 | 'boot_type': ('django.db.models.fields.CharField', [], {'default': "u'fastpath'", 'max_length': '20'}), | ||
487 | 316 | 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
488 | 317 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
489 | 318 | 'disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
490 | 319 | 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
491 | 320 | 'enable_ssh': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
492 | 321 | 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
493 | 322 | 'error_description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}), | ||
494 | 323 | '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'}), | ||
495 | 324 | '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'}), | ||
496 | 325 | 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}), | ||
497 | 326 | 'hwe_kernel': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), | ||
498 | 327 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
499 | 328 | 'installable': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), | ||
500 | 329 | 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), | ||
501 | 330 | 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
502 | 331 | 'min_hwe_kernel': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True', 'blank': 'True'}), | ||
503 | 332 | 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
504 | 333 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}), | ||
505 | 334 | 'osystem': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
506 | 335 | 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}), | ||
507 | 336 | 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "u'children'", 'null': 'True', 'blank': 'True', 'to': u"orm['maasserver.Node']"}), | ||
508 | 337 | 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'max_length': '32768', 'blank': 'True'}), | ||
509 | 338 | 'power_state': ('django.db.models.fields.CharField', [], {'default': "u'unknown'", 'max_length': '10'}), | ||
510 | 339 | 'power_state_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), | ||
511 | 340 | 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}), | ||
512 | 341 | 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}), | ||
513 | 342 | 'skip_networking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
514 | 343 | 'skip_storage': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
515 | 344 | 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}), | ||
516 | 345 | 'swap_size': ('django.db.models.fields.BigIntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), | ||
517 | 346 | 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-a1d55db4-6e44-11e5-a1dc-c48e8ffbb365'", 'unique': 'True', 'max_length': '41'}), | ||
518 | 347 | 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}), | ||
519 | 348 | 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}), | ||
520 | 349 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
521 | 350 | 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'}) | ||
522 | 351 | }, | ||
523 | 352 | u'maasserver.nodegroup': { | ||
524 | 353 | 'Meta': {'object_name': 'NodeGroup'}, | ||
525 | 354 | 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}), | ||
526 | 355 | 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}), | ||
527 | 356 | 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}), | ||
528 | 357 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
529 | 358 | 'default_disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
530 | 359 | 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
531 | 360 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
532 | 361 | 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
533 | 362 | 'name': ('maasserver.models.nodegroup.DomainNameField', [], {'max_length': '80', 'blank': 'True'}), | ||
534 | 363 | 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), | ||
535 | 364 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
536 | 365 | 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) | ||
537 | 366 | }, | ||
538 | 367 | u'maasserver.nodegroupinterface': { | ||
539 | 368 | 'Meta': {'unique_together': "((u'nodegroup', u'name'),)", 'object_name': 'NodeGroupInterface'}, | ||
540 | 369 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
541 | 370 | 'foreign_dhcp_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
542 | 371 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
543 | 372 | 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
544 | 373 | 'ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}), | ||
545 | 374 | 'ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
546 | 375 | 'ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
547 | 376 | 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
548 | 377 | 'name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
549 | 378 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), | ||
550 | 379 | 'static_ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
551 | 380 | 'static_ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
552 | 381 | 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'on_delete': 'models.PROTECT', 'blank': 'True'}), | ||
553 | 382 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
554 | 383 | 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'}) | ||
555 | 384 | }, | ||
556 | 385 | u'maasserver.partition': { | ||
557 | 386 | 'Meta': {'object_name': 'Partition'}, | ||
558 | 387 | 'bootable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
559 | 388 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
560 | 389 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
561 | 390 | 'partition_table': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'partitions'", 'to': u"orm['maasserver.PartitionTable']"}), | ||
562 | 391 | 'size': ('django.db.models.fields.BigIntegerField', [], {}), | ||
563 | 392 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
564 | 393 | 'uuid': ('django.db.models.fields.CharField', [], {'max_length': '36', 'unique': 'True', 'null': 'True', 'blank': 'True'}) | ||
565 | 394 | }, | ||
566 | 395 | u'maasserver.partitiontable': { | ||
567 | 396 | 'Meta': {'object_name': 'PartitionTable'}, | ||
568 | 397 | 'block_device': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BlockDevice']"}), | ||
569 | 398 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
570 | 399 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
571 | 400 | 'table_type': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '20'}), | ||
572 | 401 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
573 | 402 | }, | ||
574 | 403 | u'maasserver.physicalblockdevice': { | ||
575 | 404 | 'Meta': {'ordering': "[u'id']", 'object_name': 'PhysicalBlockDevice', '_ormbases': [u'maasserver.BlockDevice']}, | ||
576 | 405 | u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}), | ||
577 | 406 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
578 | 407 | 'serial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) | ||
579 | 408 | }, | ||
580 | 409 | u'maasserver.space': { | ||
581 | 410 | 'Meta': {'object_name': 'Space'}, | ||
582 | 411 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
583 | 412 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
584 | 413 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), | ||
585 | 414 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
586 | 415 | }, | ||
587 | 416 | u'maasserver.sshkey': { | ||
588 | 417 | 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'}, | ||
589 | 418 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
590 | 419 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
591 | 420 | 'key': ('django.db.models.fields.TextField', [], {}), | ||
592 | 421 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
593 | 422 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) | ||
594 | 423 | }, | ||
595 | 424 | u'maasserver.sslkey': { | ||
596 | 425 | 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSLKey'}, | ||
597 | 426 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
598 | 427 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
599 | 428 | 'key': ('django.db.models.fields.TextField', [], {}), | ||
600 | 429 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
601 | 430 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) | ||
602 | 431 | }, | ||
603 | 432 | u'maasserver.staticipaddress': { | ||
604 | 433 | 'Meta': {'object_name': 'StaticIPAddress'}, | ||
605 | 434 | 'alloc_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
606 | 435 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
607 | 436 | 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
608 | 437 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
609 | 438 | 'ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}), | ||
610 | 439 | 'subnet': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Subnet']", 'null': 'True', 'blank': 'True'}), | ||
611 | 440 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
612 | 441 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) | ||
613 | 442 | }, | ||
614 | 443 | u'maasserver.subnet': { | ||
615 | 444 | 'Meta': {'unique_together': "((u'name', u'space'),)", 'object_name': 'Subnet'}, | ||
616 | 445 | 'cidr': ('maasserver.fields.CIDRField', [], {'unique': 'True'}), | ||
617 | 446 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
618 | 447 | 'dns_servers': ('djorm_pgarray.fields.ArrayField', [], {'default': '[]', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), | ||
619 | 448 | 'gateway_ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
620 | 449 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
621 | 450 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
622 | 451 | 'space': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Space']", 'on_delete': 'models.PROTECT'}), | ||
623 | 452 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
624 | 453 | 'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.VLAN']", 'on_delete': 'models.PROTECT'}) | ||
625 | 454 | }, | ||
626 | 455 | u'maasserver.tag': { | ||
627 | 456 | 'Meta': {'object_name': 'Tag'}, | ||
628 | 457 | 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
629 | 458 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
630 | 459 | 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
631 | 460 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
632 | 461 | 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), | ||
633 | 462 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), | ||
634 | 463 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
635 | 464 | }, | ||
636 | 465 | u'maasserver.userprofile': { | ||
637 | 466 | 'Meta': {'object_name': 'UserProfile'}, | ||
638 | 467 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
639 | 468 | 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'}) | ||
640 | 469 | }, | ||
641 | 470 | u'maasserver.virtualblockdevice': { | ||
642 | 471 | 'Meta': {'ordering': "[u'id']", 'object_name': 'VirtualBlockDevice', '_ormbases': [u'maasserver.BlockDevice']}, | ||
643 | 472 | u'blockdevice_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['maasserver.BlockDevice']", 'unique': 'True', 'primary_key': 'True'}), | ||
644 | 473 | 'filesystem_group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'virtual_devices'", 'to': u"orm['maasserver.FilesystemGroup']"}), | ||
645 | 474 | 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) | ||
646 | 475 | }, | ||
647 | 476 | u'maasserver.vlan': { | ||
648 | 477 | 'Meta': {'unique_together': "((u'vid', u'fabric'),)", 'object_name': 'VLAN'}, | ||
649 | 478 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
650 | 479 | 'fabric': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Fabric']"}), | ||
651 | 480 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
652 | 481 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}), | ||
653 | 482 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
654 | 483 | 'vid': ('django.db.models.fields.IntegerField', [], {}) | ||
655 | 484 | }, | ||
656 | 485 | u'maasserver.zone': { | ||
657 | 486 | 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'}, | ||
658 | 487 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
659 | 488 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
660 | 489 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
661 | 490 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), | ||
662 | 491 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
663 | 492 | }, | ||
664 | 493 | u'piston.consumer': { | ||
665 | 494 | 'Meta': {'object_name': 'Consumer'}, | ||
666 | 495 | 'description': ('django.db.models.fields.TextField', [], {}), | ||
667 | 496 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
668 | 497 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), | ||
669 | 498 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
670 | 499 | 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), | ||
671 | 500 | 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}), | ||
672 | 501 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"}) | ||
673 | 502 | }, | ||
674 | 503 | u'piston.token': { | ||
675 | 504 | 'Meta': {'object_name': 'Token'}, | ||
676 | 505 | 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
677 | 506 | 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
678 | 507 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}), | ||
679 | 508 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
680 | 509 | 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
681 | 510 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), | ||
682 | 511 | 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), | ||
683 | 512 | 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1444367666L'}), | ||
684 | 513 | 'token_type': ('django.db.models.fields.IntegerField', [], {}), | ||
685 | 514 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}), | ||
686 | 515 | 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) | ||
687 | 516 | } | ||
688 | 517 | } | ||
689 | 518 | |||
690 | 519 | complete_apps = ['maasserver'] | ||
691 | 0 | \ No newline at end of file | 520 | \ No newline at end of file |
692 | 1 | 521 | ||
693 | === modified file 'src/maasserver/models/fabric.py' | |||
694 | --- src/maasserver/models/fabric.py 2015-08-13 23:00:22 +0000 | |||
695 | +++ src/maasserver/models/fabric.py 2015-10-09 21:26:30 +0000 | |||
696 | @@ -101,7 +101,7 @@ | |||
697 | 101 | objects = FabricManager() | 101 | objects = FabricManager() |
698 | 102 | 102 | ||
699 | 103 | name = CharField( | 103 | name = CharField( |
701 | 104 | max_length=256, unique=True, editable=True, | 104 | max_length=256, editable=True, null=True, blank=True, |
702 | 105 | validators=[FABRIC_NAME_VALIDATOR]) | 105 | validators=[FABRIC_NAME_VALIDATOR]) |
703 | 106 | 106 | ||
704 | 107 | def __unicode__(self): | 107 | def __unicode__(self): |
705 | @@ -114,6 +114,13 @@ | |||
706 | 114 | def get_default_vlan(self): | 114 | def get_default_vlan(self): |
707 | 115 | return self.vlan_set.all().order_by('id').first() | 115 | return self.vlan_set.all().order_by('id').first() |
708 | 116 | 116 | ||
709 | 117 | def get_name(self): | ||
710 | 118 | """Return the name of the fabric.""" | ||
711 | 119 | if self.name: | ||
712 | 120 | return self.name | ||
713 | 121 | else: | ||
714 | 122 | return "fabric-%s" % self.id | ||
715 | 123 | |||
716 | 117 | def delete(self): | 124 | def delete(self): |
717 | 118 | if self.is_default(): | 125 | if self.is_default(): |
718 | 119 | raise ValidationError( | 126 | raise ValidationError( |
719 | 120 | 127 | ||
720 | === modified file 'src/maasserver/models/tests/test_fabric.py' | |||
721 | --- src/maasserver/models/tests/test_fabric.py 2015-08-28 02:34:50 +0000 | |||
722 | +++ src/maasserver/models/tests/test_fabric.py 2015-10-09 21:26:30 +0000 | |||
723 | @@ -90,6 +90,15 @@ | |||
724 | 90 | 90 | ||
725 | 91 | class TestFabric(MAASServerTestCase): | 91 | class TestFabric(MAASServerTestCase): |
726 | 92 | 92 | ||
727 | 93 | def test_get_name_for_empty_name(self): | ||
728 | 94 | fabric = factory.make_Fabric() | ||
729 | 95 | self.assertEquals("fabric-%s" % fabric.id, fabric.get_name()) | ||
730 | 96 | |||
731 | 97 | def test_get_name_for_set_name(self): | ||
732 | 98 | name = factory.make_name('name') | ||
733 | 99 | fabric = factory.make_Fabric(name=name) | ||
734 | 100 | self.assertEquals(name, fabric.get_name()) | ||
735 | 101 | |||
736 | 93 | def test_creates_fabric_with_default_vlan(self): | 102 | def test_creates_fabric_with_default_vlan(self): |
737 | 94 | name = factory.make_name('name') | 103 | name = factory.make_name('name') |
738 | 95 | fabric = factory.make_Fabric(name=name) | 104 | fabric = factory.make_Fabric(name=name) |
739 | 96 | 105 | ||
740 | === modified file 'src/maasserver/models/tests/test_vlan.py' | |||
741 | --- src/maasserver/models/tests/test_vlan.py 2015-08-28 02:34:50 +0000 | |||
742 | +++ src/maasserver/models/tests/test_vlan.py 2015-10-09 21:26:30 +0000 | |||
743 | @@ -34,6 +34,15 @@ | |||
744 | 34 | 34 | ||
745 | 35 | class VLANTest(MAASServerTestCase): | 35 | class VLANTest(MAASServerTestCase): |
746 | 36 | 36 | ||
747 | 37 | def test_get_name_for_default_vlan_is_untagged(self): | ||
748 | 38 | fabric = factory.make_Fabric() | ||
749 | 39 | self.assertEquals("untagged", fabric.get_default_vlan().get_name()) | ||
750 | 40 | |||
751 | 41 | def test_get_name_for_set_name(self): | ||
752 | 42 | name = factory.make_name('name') | ||
753 | 43 | vlan = factory.make_VLAN(name=name) | ||
754 | 44 | self.assertEquals(name, vlan.get_name()) | ||
755 | 45 | |||
756 | 37 | def test_creates_vlan(self): | 46 | def test_creates_vlan(self): |
757 | 38 | name = factory.make_name('name') | 47 | name = factory.make_name('name') |
758 | 39 | vid = random.randint(3, 55) | 48 | vid = random.randint(3, 55) |
759 | 40 | 49 | ||
760 | === modified file 'src/maasserver/models/vlan.py' | |||
761 | --- src/maasserver/models/vlan.py 2015-06-19 09:53:30 +0000 | |||
762 | +++ src/maasserver/models/vlan.py 2015-10-09 21:26:30 +0000 | |||
763 | @@ -66,19 +66,18 @@ | |||
764 | 66 | verbose_name_plural = "VLANs" | 66 | verbose_name_plural = "VLANs" |
765 | 67 | unique_together = ( | 67 | unique_together = ( |
766 | 68 | ('vid', 'fabric'), | 68 | ('vid', 'fabric'), |
767 | 69 | ('name', 'fabric'), | ||
768 | 70 | ) | 69 | ) |
769 | 71 | 70 | ||
770 | 72 | name = CharField( | 71 | name = CharField( |
772 | 73 | max_length=256, editable=True, validators=[VLAN_NAME_VALIDATOR]) | 72 | max_length=256, editable=True, null=True, blank=True, |
773 | 73 | validators=[VLAN_NAME_VALIDATOR]) | ||
774 | 74 | 74 | ||
775 | 75 | vid = IntegerField(editable=True) | 75 | vid = IntegerField(editable=True) |
776 | 76 | 76 | ||
777 | 77 | fabric = ForeignKey('Fabric', blank=False, editable=True) | 77 | fabric = ForeignKey('Fabric', blank=False, editable=True) |
778 | 78 | 78 | ||
779 | 79 | def __unicode__(self): | 79 | def __unicode__(self): |
782 | 80 | return "name=%s, vid=%d, fabric=%s" % ( | 80 | return "%s.%s" % (self.fabric.get_name(), self.get_name()) |
781 | 81 | self.name, self.vid, self.fabric.name) | ||
783 | 82 | 81 | ||
784 | 83 | def clean_vid(self): | 82 | def clean_vid(self): |
785 | 84 | if self.vid < 0 or self.vid > 4095: | 83 | if self.vid < 0 or self.vid > 4095: |
786 | @@ -93,6 +92,13 @@ | |||
787 | 93 | """Is this the default VLAN in the fabric?""" | 92 | """Is this the default VLAN in the fabric?""" |
788 | 94 | return self.fabric.get_default_vlan() == self | 93 | return self.fabric.get_default_vlan() == self |
789 | 95 | 94 | ||
790 | 95 | def get_name(self): | ||
791 | 96 | """Return the name of the VLAN.""" | ||
792 | 97 | if self.is_fabric_default(): | ||
793 | 98 | return "untagged" | ||
794 | 99 | else: | ||
795 | 100 | return self.name | ||
796 | 101 | |||
797 | 96 | def manage_connected_interfaces(self): | 102 | def manage_connected_interfaces(self): |
798 | 97 | """Deal with connected interfaces: | 103 | """Deal with connected interfaces: |
799 | 98 | 104 | ||
800 | 99 | 105 | ||
801 | === modified file 'src/maasserver/static/js/angular/controllers/node_details_networking.js' | |||
802 | --- src/maasserver/static/js/angular/controllers/node_details_networking.js 2015-10-06 05:50:44 +0000 | |||
803 | +++ src/maasserver/static/js/angular/controllers/node_details_networking.js 2015-10-09 21:26:30 +0000 | |||
804 | @@ -61,6 +61,26 @@ | |||
805 | 61 | }); | 61 | }); |
806 | 62 | 62 | ||
807 | 63 | 63 | ||
808 | 64 | // Filter that is specific to the NodeNetworkingController. Remove the default | ||
809 | 65 | // VLAN if the interface is a VLAN interface. | ||
810 | 66 | angular.module('MAAS').filter('removeDefaultVLANIfVLAN', function() { | ||
811 | 67 | return function(vlans, interfaceType) { | ||
812 | 68 | if(!angular.isString(interfaceType)) { | ||
813 | 69 | return vlans; | ||
814 | 70 | } | ||
815 | 71 | var filtered = []; | ||
816 | 72 | angular.forEach(vlans, function(vlan) { | ||
817 | 73 | if(interfaceType !== "vlan") { | ||
818 | 74 | filtered.push(vlan); | ||
819 | 75 | } else if(vlan.vid !== 0) { | ||
820 | 76 | filtered.push(vlan); | ||
821 | 77 | } | ||
822 | 78 | }); | ||
823 | 79 | return filtered; | ||
824 | 80 | }; | ||
825 | 81 | }); | ||
826 | 82 | |||
827 | 83 | |||
828 | 64 | angular.module('MAAS').controller('NodeNetworkingController', [ | 84 | angular.module('MAAS').controller('NodeNetworkingController', [ |
829 | 65 | '$scope', '$filter', 'FabricsManager', 'VLANsManager', 'SubnetsManager', | 85 | '$scope', '$filter', 'FabricsManager', 'VLANsManager', 'SubnetsManager', |
830 | 66 | 'NodesManager', 'GeneralManager', 'ManagerHelperService', | 86 | 'NodesManager', 'GeneralManager', 'ManagerHelperService', |
831 | @@ -332,7 +352,8 @@ | |||
832 | 332 | // Return list of unused VLANs for an interface. Also remove the | 352 | // Return list of unused VLANs for an interface. Also remove the |
833 | 333 | // ignoreVLANs from the returned list. | 353 | // ignoreVLANs from the returned list. |
834 | 334 | function getUnusedVLANs(nic, ignoreVLANs) { | 354 | function getUnusedVLANs(nic, ignoreVLANs) { |
836 | 335 | var vlans = $filter('filterByFabric')($scope.vlans, nic.fabric); | 355 | var vlans = $filter('removeDefaultVLAN')($scope.vlans); |
837 | 356 | vlans = $filter('filterByFabric')(vlans, nic.fabric); | ||
838 | 336 | vlans = $filter('filterByUnusedForInterface')( | 357 | vlans = $filter('filterByUnusedForInterface')( |
839 | 337 | vlans, nic, $scope.originalInterfaces); | 358 | vlans, nic, $scope.originalInterfaces); |
840 | 338 | 359 | ||
841 | @@ -413,7 +434,9 @@ | |||
842 | 413 | return ""; | 434 | return ""; |
843 | 414 | } | 435 | } |
844 | 415 | 436 | ||
846 | 416 | if(angular.isString(vlan.name) && vlan.name.length > 0) { | 437 | if(vlan.vid === 0) { |
847 | 438 | return "untagged"; | ||
848 | 439 | } else if(angular.isString(vlan.name) && vlan.name.length > 0) { | ||
849 | 417 | return vlan.vid + " (" + vlan.name + ")"; | 440 | return vlan.vid + " (" + vlan.name + ")"; |
850 | 418 | } else { | 441 | } else { |
851 | 419 | return vlan.vid; | 442 | return vlan.vid; |
852 | @@ -624,7 +647,8 @@ | |||
853 | 624 | // Return True if the interface IP address that the user typed is | 647 | // Return True if the interface IP address that the user typed is |
854 | 625 | // invalid. | 648 | // invalid. |
855 | 626 | $scope.isIPAddressInvalid = function(nic) { | 649 | $scope.isIPAddressInvalid = function(nic) { |
857 | 627 | return (nic.ip_address.length === 0 || | 650 | return (!angular.isString(nic.ip_address) || |
858 | 651 | nic.ip_address.length === 0 || | ||
859 | 628 | !ValidationService.validateIP(nic.ip_address) || | 652 | !ValidationService.validateIP(nic.ip_address) || |
860 | 629 | !ValidationService.validateIPInNetwork( | 653 | !ValidationService.validateIPInNetwork( |
861 | 630 | nic.ip_address, nic.subnet.cidr)); | 654 | nic.ip_address, nic.subnet.cidr)); |
862 | @@ -907,6 +931,7 @@ | |||
863 | 907 | } else { | 931 | } else { |
864 | 908 | $scope.selectedMode = SELECTION_MODE.NONE; | 932 | $scope.selectedMode = SELECTION_MODE.NONE; |
865 | 909 | $scope.selectedInterfaces = []; | 933 | $scope.selectedInterfaces = []; |
866 | 934 | $scope.newInterface = {}; | ||
867 | 910 | } | 935 | } |
868 | 911 | }; | 936 | }; |
869 | 912 | 937 | ||
870 | 913 | 938 | ||
871 | === modified file 'src/maasserver/static/js/angular/controllers/subnets_list.js' | |||
872 | --- src/maasserver/static/js/angular/controllers/subnets_list.js 2015-10-06 22:24:06 +0000 | |||
873 | +++ src/maasserver/static/js/angular/controllers/subnets_list.js 2015-10-09 21:26:30 +0000 | |||
874 | @@ -104,7 +104,9 @@ | |||
875 | 104 | // Return the name name for the VLAN. | 104 | // Return the name name for the VLAN. |
876 | 105 | function getVLANName(vlan) { | 105 | function getVLANName(vlan) { |
877 | 106 | var name = vlan.vid; | 106 | var name = vlan.vid; |
879 | 107 | if(angular.isString(vlan.name) && vlan.name !== "") { | 107 | if(vlan.vid === 0) { |
880 | 108 | name = "untagged"; | ||
881 | 109 | } else if(angular.isString(vlan.name) && vlan.name !== "") { | ||
882 | 108 | name += " (" + vlan.name + ")"; | 110 | name += " (" + vlan.name + ")"; |
883 | 109 | } | 111 | } |
884 | 110 | return name; | 112 | return name; |
885 | 111 | 113 | ||
886 | === modified file 'src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js' | |||
887 | --- src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js 2015-10-06 05:50:44 +0000 | |||
888 | +++ src/maasserver/static/js/angular/controllers/tests/test_node_details_networking.js 2015-10-09 21:26:30 +0000 | |||
889 | @@ -26,7 +26,7 @@ | |||
890 | 26 | expect(filterByUnusedForInterface(vlans)).toEqual([]); | 26 | expect(filterByUnusedForInterface(vlans)).toEqual([]); |
891 | 27 | }); | 27 | }); |
892 | 28 | 28 | ||
894 | 29 | it("returns empty if undefined originalInterfaces", function() { | 29 | it("returns only free vlans", function() { |
895 | 30 | var i, vlan, used_vlans = [], free_vlans = [], all_vlans = []; | 30 | var i, vlan, used_vlans = [], free_vlans = [], all_vlans = []; |
896 | 31 | for(i = 0; i < 3; i++) { | 31 | for(i = 0; i < 3; i++) { |
897 | 32 | vlan = { | 32 | vlan = { |
898 | @@ -125,6 +125,48 @@ | |||
899 | 125 | }); | 125 | }); |
900 | 126 | 126 | ||
901 | 127 | 127 | ||
902 | 128 | describe("removeDefaultVLANIfVLAN", function() { | ||
903 | 129 | |||
904 | 130 | // Load the MAAS module. | ||
905 | 131 | beforeEach(module("MAAS")); | ||
906 | 132 | |||
907 | 133 | // Load the removeDefaultVLANIfVLAN. | ||
908 | 134 | var removeDefaultVLANIfVLAN; | ||
909 | 135 | beforeEach(inject(function($filter) { | ||
910 | 136 | removeDefaultVLANIfVLAN = $filter("removeDefaultVLANIfVLAN"); | ||
911 | 137 | })); | ||
912 | 138 | |||
913 | 139 | it("returns vlans if undefined type", function() { | ||
914 | 140 | var i, vlan, vlans = []; | ||
915 | 141 | for(i = 0; i < 3; i++) { | ||
916 | 142 | vlan = { | ||
917 | 143 | id: i, | ||
918 | 144 | vid: i, | ||
919 | 145 | fabric: 0 | ||
920 | 146 | }; | ||
921 | 147 | vlans.push(vlan); | ||
922 | 148 | } | ||
923 | 149 | expect(removeDefaultVLANIfVLAN(vlans)).toEqual(vlans); | ||
924 | 150 | }); | ||
925 | 151 | |||
926 | 152 | it("removes default vlans from vlans", function() { | ||
927 | 153 | var i, vlan, vlans = []; | ||
928 | 154 | for(i = 0; i < 3; i++) { | ||
929 | 155 | vlan = { | ||
930 | 156 | id: i, | ||
931 | 157 | vid: i, | ||
932 | 158 | fabric: 0 | ||
933 | 159 | }; | ||
934 | 160 | vlans.push(vlan); | ||
935 | 161 | } | ||
936 | 162 | |||
937 | 163 | expect( | ||
938 | 164 | removeDefaultVLANIfVLAN( | ||
939 | 165 | vlans, "vlan")).toEqual([vlans[1], vlans[2]]); | ||
940 | 166 | }); | ||
941 | 167 | }); | ||
942 | 168 | |||
943 | 169 | |||
944 | 128 | describe("NodeNetworkingController", function() { | 170 | describe("NodeNetworkingController", function() { |
945 | 129 | // Load the MAAS module. | 171 | // Load the MAAS module. |
946 | 130 | beforeEach(module("MAAS")); | 172 | beforeEach(module("MAAS")); |
947 | @@ -2498,10 +2540,11 @@ | |||
948 | 2498 | var parent = { | 2540 | var parent = { |
949 | 2499 | id: makeInteger(0, 100) | 2541 | id: makeInteger(0, 100) |
950 | 2500 | }; | 2542 | }; |
951 | 2543 | var subnet = {}; | ||
952 | 2501 | $scope.newInterface = { | 2544 | $scope.newInterface = { |
953 | 2502 | type: "alias", | 2545 | type: "alias", |
954 | 2503 | mode: "auto", | 2546 | mode: "auto", |
956 | 2504 | subnet: {}, | 2547 | subnet: subnet, |
957 | 2505 | parent: parent | 2548 | parent: parent |
958 | 2506 | }; | 2549 | }; |
959 | 2507 | $scope.selectedInterfaces = [{}]; | 2550 | $scope.selectedInterfaces = [{}]; |
960 | @@ -2511,11 +2554,12 @@ | |||
961 | 2511 | expect($scope.saveInterfaceLink).toHaveBeenCalledWith({ | 2554 | expect($scope.saveInterfaceLink).toHaveBeenCalledWith({ |
962 | 2512 | id: parent.id, | 2555 | id: parent.id, |
963 | 2513 | mode: "auto", | 2556 | mode: "auto", |
965 | 2514 | subnet: $scope.newInterface.subnet, | 2557 | subnet: subnet, |
966 | 2515 | ip_address: "" | 2558 | ip_address: "" |
967 | 2516 | }); | 2559 | }); |
968 | 2517 | expect($scope.selectedMode).toBeNull(); | 2560 | expect($scope.selectedMode).toBeNull(); |
969 | 2518 | expect($scope.selectedInterfaces).toEqual([]); | 2561 | expect($scope.selectedInterfaces).toEqual([]); |
970 | 2562 | expect($scope.newInterface).toEqual({}); | ||
971 | 2519 | }); | 2563 | }); |
972 | 2520 | 2564 | ||
973 | 2521 | it("calls createVLANInterface with correct params", function() { | 2565 | it("calls createVLANInterface with correct params", function() { |
974 | @@ -2523,16 +2567,18 @@ | |||
975 | 2523 | var parent = { | 2567 | var parent = { |
976 | 2524 | id: makeInteger(0, 100) | 2568 | id: makeInteger(0, 100) |
977 | 2525 | }; | 2569 | }; |
978 | 2570 | var vlan = { | ||
979 | 2571 | id: makeInteger(0, 100) | ||
980 | 2572 | }; | ||
981 | 2573 | var subnet = { | ||
982 | 2574 | id: makeInteger(0, 100) | ||
983 | 2575 | }; | ||
984 | 2526 | $scope.newInterface = { | 2576 | $scope.newInterface = { |
985 | 2527 | type: "vlan", | 2577 | type: "vlan", |
986 | 2528 | mode: "auto", | 2578 | mode: "auto", |
987 | 2529 | parent: parent, | 2579 | parent: parent, |
994 | 2530 | vlan: { | 2580 | vlan: vlan, |
995 | 2531 | id: makeInteger(0, 100) | 2581 | subnet: subnet |
990 | 2532 | }, | ||
991 | 2533 | subnet: { | ||
992 | 2534 | id: makeInteger(0, 100) | ||
993 | 2535 | } | ||
996 | 2536 | }; | 2582 | }; |
997 | 2537 | $scope.selectedInterfaces = [{}]; | 2583 | $scope.selectedInterfaces = [{}]; |
998 | 2538 | $scope.selectedMode = "add"; | 2584 | $scope.selectedMode = "add"; |
999 | @@ -2543,12 +2589,13 @@ | |||
1000 | 2543 | expect(NodesManager.createVLANInterface).toHaveBeenCalledWith( | 2589 | expect(NodesManager.createVLANInterface).toHaveBeenCalledWith( |
1001 | 2544 | node, { | 2590 | node, { |
1002 | 2545 | parent: parent.id, | 2591 | parent: parent.id, |
1004 | 2546 | vlan: $scope.newInterface.vlan.id, | 2592 | vlan: vlan.id, |
1005 | 2547 | mode: "auto", | 2593 | mode: "auto", |
1007 | 2548 | subnet: $scope.newInterface.subnet.id | 2594 | subnet: subnet.id |
1008 | 2549 | }); | 2595 | }); |
1009 | 2550 | expect($scope.selectedMode).toBeNull(); | 2596 | expect($scope.selectedMode).toBeNull(); |
1010 | 2551 | expect($scope.selectedInterfaces).toEqual([]); | 2597 | expect($scope.selectedInterfaces).toEqual([]); |
1011 | 2598 | expect($scope.newInterface).toEqual({}); | ||
1012 | 2552 | }); | 2599 | }); |
1013 | 2553 | 2600 | ||
1014 | 2554 | it("calls add again with type", function() { | 2601 | it("calls add again with type", function() { |
1015 | 2555 | 2602 | ||
1016 | === added file 'src/maasserver/static/js/angular/filters/remove_default_vlan.js' | |||
1017 | --- src/maasserver/static/js/angular/filters/remove_default_vlan.js 1970-01-01 00:00:00 +0000 | |||
1018 | +++ src/maasserver/static/js/angular/filters/remove_default_vlan.js 2015-10-09 21:26:30 +0000 | |||
1019 | @@ -0,0 +1,17 @@ | |||
1020 | 1 | /* Copyright 2015 Canonical Ltd. This software is licensed under the | ||
1021 | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). | ||
1022 | 3 | * | ||
1023 | 4 | * MAAS Filter to remove the default VLAN as an option. | ||
1024 | 5 | */ | ||
1025 | 6 | |||
1026 | 7 | angular.module('MAAS').filter('removeDefaultVLAN', function() { | ||
1027 | 8 | return function(vlans) { | ||
1028 | 9 | var filtered = []; | ||
1029 | 10 | angular.forEach(vlans, function(vlan) { | ||
1030 | 11 | if(vlan.vid !== 0) { | ||
1031 | 12 | filtered.push(vlan); | ||
1032 | 13 | } | ||
1033 | 14 | }); | ||
1034 | 15 | return filtered; | ||
1035 | 16 | }; | ||
1036 | 17 | }); | ||
1037 | 0 | 18 | ||
1038 | === added file 'src/maasserver/static/js/angular/filters/tests/test_remove_default_vlan.js' | |||
1039 | --- src/maasserver/static/js/angular/filters/tests/test_remove_default_vlan.js 1970-01-01 00:00:00 +0000 | |||
1040 | +++ src/maasserver/static/js/angular/filters/tests/test_remove_default_vlan.js 2015-10-09 21:26:30 +0000 | |||
1041 | @@ -0,0 +1,30 @@ | |||
1042 | 1 | /* Copyright 2015 Canonical Ltd. This software is licensed under the | ||
1043 | 2 | * GNU Affero General Public License version 3 (see the file LICENSE). | ||
1044 | 3 | * | ||
1045 | 4 | * Unit tests for removeDefaultVLAN. | ||
1046 | 5 | */ | ||
1047 | 6 | |||
1048 | 7 | describe("removeDefaultVLAN", function() { | ||
1049 | 8 | |||
1050 | 9 | // Load the MAAS module. | ||
1051 | 10 | beforeEach(module("MAAS")); | ||
1052 | 11 | |||
1053 | 12 | // Load the removeDefaultVLAN. | ||
1054 | 13 | var removeDefaultVLAN; | ||
1055 | 14 | beforeEach(inject(function($filter) { | ||
1056 | 15 | removeDefaultVLAN = $filter("removeDefaultVLAN"); | ||
1057 | 16 | })); | ||
1058 | 17 | |||
1059 | 18 | it("only returns vlans without vid 0", function() { | ||
1060 | 19 | var i, vlan, vlans = []; | ||
1061 | 20 | for(i = 0; i < 3; i++) { | ||
1062 | 21 | vlan = { | ||
1063 | 22 | id: i, | ||
1064 | 23 | vid: i, | ||
1065 | 24 | fabric: 0 | ||
1066 | 25 | }; | ||
1067 | 26 | vlans.push(vlan); | ||
1068 | 27 | } | ||
1069 | 28 | expect(removeDefaultVLAN(vlans)).toEqual([vlans[1], vlans[2]]); | ||
1070 | 29 | }); | ||
1071 | 30 | }); | ||
1072 | 0 | 31 | ||
1073 | === modified file 'src/maasserver/static/partials/node-details.html' | |||
1074 | --- src/maasserver/static/partials/node-details.html 2015-10-09 07:58:28 +0000 | |||
1075 | +++ src/maasserver/static/partials/node-details.html 2015-10-09 21:26:30 +0000 | |||
1076 | @@ -340,9 +340,9 @@ | |||
1077 | 340 | <label class="checkbox-label" for="{$ getUniqueKey(interface) $}"></label> | 340 | <label class="checkbox-label" for="{$ getUniqueKey(interface) $}"></label> |
1078 | 341 | </div> | 341 | </div> |
1079 | 342 | <div class="table__data table__column--15" data-ng-show="column == 'name'"> | 342 | <div class="table__data table__column--15" data-ng-show="column == 'name'"> |
1081 | 343 | <span class="ng-hide" data-ng-show="interface.type == 'alias'">{$ interface.name $}</span> | 343 | <span class="ng-hide" data-ng-show="interface.type == 'alias' || interface.type == 'vlan'">{$ interface.name $}</span> |
1082 | 344 | <input type="text" class="table__input" | 344 | <input type="text" class="table__input" |
1084 | 345 | data-ng-show="interface.type != 'alias'" | 345 | data-ng-show="interface.type != 'alias' && interface.type != 'vlan'" |
1085 | 346 | data-ng-model="interface.name" | 346 | data-ng-model="interface.name" |
1086 | 347 | data-maas-enter-blur | 347 | data-maas-enter-blur |
1087 | 348 | data-ng-focus="setFocusInterface(interface)" | 348 | data-ng-focus="setFocusInterface(interface)" |
1088 | @@ -368,7 +368,7 @@ | |||
1089 | 368 | <div class="table__data table__column--14"> | 368 | <div class="table__data table__column--14"> |
1090 | 369 | <select class="table__input" name="fabric" id="fabric" | 369 | <select class="table__input" name="fabric" id="fabric" |
1091 | 370 | data-ng-model="interface.fabric" | 370 | data-ng-model="interface.fabric" |
1093 | 371 | data-ng-disabled="interface.type == 'alias'" | 371 | data-ng-disabled="interface.type == 'alias' || interface.type == 'vlan'" |
1094 | 372 | data-ng-change="fabricChanged(interface)" | 372 | data-ng-change="fabricChanged(interface)" |
1095 | 373 | data-ng-options="fabric as fabric.name for fabric in fabrics"> | 373 | data-ng-options="fabric as fabric.name for fabric in fabrics"> |
1096 | 374 | </select> | 374 | </select> |
1097 | @@ -376,9 +376,9 @@ | |||
1098 | 376 | <div class="table__data table__column--14"> | 376 | <div class="table__data table__column--14"> |
1099 | 377 | <select class="table__input" name="vlan" id="vlan" | 377 | <select class="table__input" name="vlan" id="vlan" |
1100 | 378 | data-ng-model="interface.vlan" | 378 | data-ng-model="interface.vlan" |
1102 | 379 | data-ng-disabled="interface.type == 'alias'" | 379 | data-ng-disabled="interface.type == 'alias' || interface.vlan.vid === 0" |
1103 | 380 | data-ng-change="saveInterface(interface)" | 380 | data-ng-change="saveInterface(interface)" |
1105 | 381 | data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | filterByFabric:interface.fabric"> | 381 | data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | removeDefaultVLANIfVLAN:interface.type | filterByFabric:interface.fabric"> |
1106 | 382 | </select> | 382 | </select> |
1107 | 383 | </div> | 383 | </div> |
1108 | 384 | <div class="table__data table__column--18"> | 384 | <div class="table__data table__column--18"> |
1109 | @@ -453,7 +453,7 @@ | |||
1110 | 453 | <select class="table__input" name="vlan" id="vlan" | 453 | <select class="table__input" name="vlan" id="vlan" |
1111 | 454 | data-ng-model="newInterface.vlan" | 454 | data-ng-model="newInterface.vlan" |
1112 | 455 | data-ng-disabled="newInterface.type == 'alias'" | 455 | data-ng-disabled="newInterface.type == 'alias'" |
1114 | 456 | data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | filterByFabric:newInterface.parent.fabric | filterByUnusedForInterface:newInterface.parent:originalInterfaces" | 456 | data-ng-options="vlan as getVLANText(vlan) for vlan in vlans | removeDefaultVLAN | filterByFabric:newInterface.parent.fabric | filterByUnusedForInterface:newInterface.parent:originalInterfaces" |
1115 | 457 | data-ng-show="newInterface.type === 'vlan'" | 457 | data-ng-show="newInterface.type === 'vlan'" |
1116 | 458 | data-ng-change="addVLANChanged()"> | 458 | data-ng-change="addVLANChanged()"> |
1117 | 459 | </select> | 459 | </select> |
1118 | 460 | 460 | ||
1119 | === modified file 'src/maasserver/testing/factory.py' | |||
1120 | --- src/maasserver/testing/factory.py 2015-09-24 16:22:12 +0000 | |||
1121 | +++ src/maasserver/testing/factory.py 2015-10-09 21:26:30 +0000 | |||
1122 | @@ -709,8 +709,6 @@ | |||
1123 | 709 | return fannetwork | 709 | return fannetwork |
1124 | 710 | 710 | ||
1125 | 711 | def make_Fabric(self, name=None): | 711 | def make_Fabric(self, name=None): |
1126 | 712 | if name is None: | ||
1127 | 713 | name = self.make_name('fabric') | ||
1128 | 714 | fabric = Fabric(name=name) | 712 | fabric = Fabric(name=name) |
1129 | 715 | fabric.save() | 713 | fabric.save() |
1130 | 716 | return fabric | 714 | return fabric |
1131 | @@ -727,8 +725,6 @@ | |||
1132 | 727 | 725 | ||
1133 | 728 | def make_VLAN(self, name=None, vid=None, fabric=None): | 726 | def make_VLAN(self, name=None, vid=None, fabric=None): |
1134 | 729 | assert vid != 0, "VID=0 VLANs are auto-created" | 727 | assert vid != 0, "VID=0 VLANs are auto-created" |
1135 | 730 | if name is None: | ||
1136 | 731 | name = self.make_name('vlan') | ||
1137 | 732 | if fabric is None: | 728 | if fabric is None: |
1138 | 733 | fabric = Fabric.objects.get_default_fabric() | 729 | fabric = Fabric.objects.get_default_fabric() |
1139 | 734 | if vid is None: | 730 | if vid is None: |
1140 | 735 | 731 | ||
1141 | === modified file 'src/maasserver/tests/test_forms_fabric.py' | |||
1142 | --- src/maasserver/tests/test_forms_fabric.py 2015-08-13 19:29:08 +0000 | |||
1143 | +++ src/maasserver/tests/test_forms_fabric.py 2015-10-09 21:26:30 +0000 | |||
1144 | @@ -22,13 +22,6 @@ | |||
1145 | 22 | 22 | ||
1146 | 23 | class TestFabricForm(MAASServerTestCase): | 23 | class TestFabricForm(MAASServerTestCase): |
1147 | 24 | 24 | ||
1148 | 25 | def test__requires_name(self): | ||
1149 | 26 | form = FabricForm({}) | ||
1150 | 27 | self.assertFalse(form.is_valid(), form.errors) | ||
1151 | 28 | self.assertEquals({ | ||
1152 | 29 | "name": ["This field is required."] | ||
1153 | 30 | }, form.errors) | ||
1154 | 31 | |||
1155 | 32 | def test__creates_fabric(self): | 25 | def test__creates_fabric(self): |
1156 | 33 | fabric_name = factory.make_name("fabric") | 26 | fabric_name = factory.make_name("fabric") |
1157 | 34 | form = FabricForm({ | 27 | form = FabricForm({ |
1158 | 35 | 28 | ||
1159 | === modified file 'src/maasserver/tests/test_forms_space.py' | |||
1160 | --- src/maasserver/tests/test_forms_space.py 2015-09-01 18:29:48 +0000 | |||
1161 | +++ src/maasserver/tests/test_forms_space.py 2015-10-09 21:26:30 +0000 | |||
1162 | @@ -39,13 +39,13 @@ | |||
1163 | 39 | self.assertEquals(space_name, space.name) | 39 | self.assertEquals(space_name, space.name) |
1164 | 40 | 40 | ||
1165 | 41 | def test__doest_require_name_on_update(self): | 41 | def test__doest_require_name_on_update(self): |
1167 | 42 | space = factory.make_Fabric() | 42 | space = factory.make_Space() |
1168 | 43 | form = SpaceForm(instance=space, data={}) | 43 | form = SpaceForm(instance=space, data={}) |
1169 | 44 | self.assertTrue(form.is_valid(), form.errors) | 44 | self.assertTrue(form.is_valid(), form.errors) |
1170 | 45 | 45 | ||
1171 | 46 | def test__updates_space(self): | 46 | def test__updates_space(self): |
1172 | 47 | new_name = factory.make_name("space") | 47 | new_name = factory.make_name("space") |
1174 | 48 | space = factory.make_Fabric() | 48 | space = factory.make_Space() |
1175 | 49 | form = SpaceForm(instance=space, data={ | 49 | form = SpaceForm(instance=space, data={ |
1176 | 50 | "name": new_name, | 50 | "name": new_name, |
1177 | 51 | }) | 51 | }) |
1178 | 52 | 52 | ||
1179 | === modified file 'src/maasserver/tests/test_forms_vlan.py' | |||
1180 | --- src/maasserver/tests/test_forms_vlan.py 2015-08-18 15:55:43 +0000 | |||
1181 | +++ src/maasserver/tests/test_forms_vlan.py 2015-10-09 21:26:30 +0000 | |||
1182 | @@ -24,12 +24,11 @@ | |||
1183 | 24 | 24 | ||
1184 | 25 | class TestVLANForm(MAASServerTestCase): | 25 | class TestVLANForm(MAASServerTestCase): |
1185 | 26 | 26 | ||
1187 | 27 | def test__requires_name(self): | 27 | def test__requires_vid(self): |
1188 | 28 | fabric = factory.make_Fabric() | 28 | fabric = factory.make_Fabric() |
1189 | 29 | form = VLANForm(fabric=fabric, data={}) | 29 | form = VLANForm(fabric=fabric, data={}) |
1190 | 30 | self.assertFalse(form.is_valid(), form.errors) | 30 | self.assertFalse(form.is_valid(), form.errors) |
1191 | 31 | self.assertEquals({ | 31 | self.assertEquals({ |
1192 | 32 | "name": ["This field is required."], | ||
1193 | 33 | "vid": [ | 32 | "vid": [ |
1194 | 34 | "This field is required.", | 33 | "This field is required.", |
1195 | 35 | "Vid must be between 0 and 4095.", | 34 | "Vid must be between 0 and 4095.", |
1196 | @@ -55,6 +54,16 @@ | |||
1197 | 55 | form = VLANForm(instance=vlan, data={}) | 54 | form = VLANForm(instance=vlan, data={}) |
1198 | 56 | self.assertTrue(form.is_valid(), form.errors) | 55 | self.assertTrue(form.is_valid(), form.errors) |
1199 | 57 | 56 | ||
1200 | 57 | def test__cannot_edit_default_vlan(self): | ||
1201 | 58 | fabric = factory.make_Fabric() | ||
1202 | 59 | form = VLANForm(instance=fabric.get_default_vlan(), data={}) | ||
1203 | 60 | self.assertFalse(form.is_valid(), form.errors) | ||
1204 | 61 | self.assertEquals({ | ||
1205 | 62 | "__all__": [ | ||
1206 | 63 | "Cannot modify the default VLAN for a fabric.", | ||
1207 | 64 | ], | ||
1208 | 65 | }, form.errors) | ||
1209 | 66 | |||
1210 | 58 | def test__updates_vlan(self): | 67 | def test__updates_vlan(self): |
1211 | 59 | vlan = factory.make_VLAN() | 68 | vlan = factory.make_VLAN() |
1212 | 60 | new_name = factory.make_name("vlan") | 69 | new_name = factory.make_name("vlan") |
1213 | 61 | 70 | ||
1214 | === modified file 'src/maasserver/websockets/handlers/fabric.py' | |||
1215 | --- src/maasserver/websockets/handlers/fabric.py 2015-10-04 22:28:33 +0000 | |||
1216 | +++ src/maasserver/websockets/handlers/fabric.py 2015-10-09 21:26:30 +0000 | |||
1217 | @@ -35,6 +35,7 @@ | |||
1218 | 35 | ] | 35 | ] |
1219 | 36 | 36 | ||
1220 | 37 | def dehydrate(self, obj, data, for_list=False): | 37 | def dehydrate(self, obj, data, for_list=False): |
1221 | 38 | data["name"] = obj.get_name() | ||
1222 | 38 | data["vlan_ids"] = [ | 39 | data["vlan_ids"] = [ |
1223 | 39 | vlan.id | 40 | vlan.id |
1224 | 40 | for vlan in obj.vlan_set.all() | 41 | for vlan in obj.vlan_set.all() |
1225 | 41 | 42 | ||
1226 | === modified file 'src/maasserver/websockets/handlers/tests/test_fabric.py' | |||
1227 | --- src/maasserver/websockets/handlers/tests/test_fabric.py 2015-09-16 20:59:38 +0000 | |||
1228 | +++ src/maasserver/websockets/handlers/tests/test_fabric.py 2015-10-09 21:26:30 +0000 | |||
1229 | @@ -26,7 +26,7 @@ | |||
1230 | 26 | def dehydrate_fabric(self, fabric): | 26 | def dehydrate_fabric(self, fabric): |
1231 | 27 | data = { | 27 | data = { |
1232 | 28 | "id": fabric.id, | 28 | "id": fabric.id, |
1234 | 29 | "name": fabric.name, | 29 | "name": fabric.get_name(), |
1235 | 30 | "updated": dehydrate_datetime(fabric.updated), | 30 | "updated": dehydrate_datetime(fabric.updated), |
1236 | 31 | "created": dehydrate_datetime(fabric.created), | 31 | "created": dehydrate_datetime(fabric.created), |
1237 | 32 | "vlan_ids": [ | 32 | "vlan_ids": [ |
1238 | 33 | 33 | ||
1239 | === modified file 'src/maasserver/websockets/handlers/tests/test_vlan.py' | |||
1240 | --- src/maasserver/websockets/handlers/tests/test_vlan.py 2015-09-16 20:59:38 +0000 | |||
1241 | +++ src/maasserver/websockets/handlers/tests/test_vlan.py 2015-10-09 21:26:30 +0000 | |||
1242 | @@ -26,7 +26,7 @@ | |||
1243 | 26 | def dehydrate_vlan(self, vlan): | 26 | def dehydrate_vlan(self, vlan): |
1244 | 27 | data = { | 27 | data = { |
1245 | 28 | "id": vlan.id, | 28 | "id": vlan.id, |
1247 | 29 | "name": vlan.name, | 29 | "name": vlan.get_name(), |
1248 | 30 | "vid": vlan.vid, | 30 | "vid": vlan.vid, |
1249 | 31 | "fabric": vlan.fabric_id, | 31 | "fabric": vlan.fabric_id, |
1250 | 32 | "updated": dehydrate_datetime(vlan.updated), | 32 | "updated": dehydrate_datetime(vlan.updated), |
1251 | 33 | 33 | ||
1252 | === modified file 'src/maasserver/websockets/handlers/vlan.py' | |||
1253 | --- src/maasserver/websockets/handlers/vlan.py 2015-09-16 20:59:38 +0000 | |||
1254 | +++ src/maasserver/websockets/handlers/vlan.py 2015-10-09 21:26:30 +0000 | |||
1255 | @@ -36,6 +36,7 @@ | |||
1256 | 36 | ] | 36 | ] |
1257 | 37 | 37 | ||
1258 | 38 | def dehydrate(self, obj, data, for_list=False): | 38 | def dehydrate(self, obj, data, for_list=False): |
1259 | 39 | data["name"] = obj.get_name() | ||
1260 | 39 | data["subnet_ids"] = [ | 40 | data["subnet_ids"] = [ |
1261 | 40 | subnet.id | 41 | subnet.id |
1262 | 41 | for subnet in obj.subnet_set.all() | 42 | for subnet in obj.subnet_set.all() |
Just one minor comment - not sure it's desired to not allow any editing of the default VLAN.
It's a minor enough debate that I wouldn't block landing this, but please call it out in the commit message too.