Merge lp:~julian-edwards/maas/dns-in-networks into lp:~maas-committers/maas/trunk
- dns-in-networks
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Julian Edwards |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2922 |
Proposed branch: | lp:~julian-edwards/maas/dns-in-networks |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
552 lines (+406/-4) 9 files modified
src/maasserver/api/networks.py (+2/-1) src/maasserver/api/tests/test_network.py (+3/-0) src/maasserver/api/tests/test_networks.py (+3/-1) src/maasserver/forms.py (+1/-0) src/maasserver/migrations/0109_networks_dns_servers.py (+377/-0) src/maasserver/models/network.py (+5/-0) src/maasserver/templates/maasserver/network_detail.html (+4/-0) src/maasserver/testing/factory.py (+8/-2) src/maasserver/views/tests/test_networks.py (+3/-0) |
To merge this branch: | bzr merge lp:~julian-edwards/maas/dns-in-networks |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeroen T. Vermeulen (community) | Approve | ||
Review via email:
|
Commit message
Add dns_servers as a field in Networks. It's purely book-keeping for the cloud installer so nothing special is done with it here.
Description of the change
The UI changes are to put it in the Network detail view only; the listing view is already quite wide and this is not strictly a network property.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Julian Edwards (julian-edwards) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jeroen T. Vermeulen (jtv) wrote : | # |
About time to line-break that ‘fields’ tuple in networks.py properly, I think...
I'd be happy to know I was worried about nothing, but will this new field support both empty strings and nulls? It seems like a recipe for confusion, e.g. if we start doing things like “if no DNS servers have been set on this network that we manage, substitute the MAAS DNS server.” Does that go for nulls, or for blanks as well? Which do you get in API results? Probably worth being clear about.
Personally I would say “space-separated” rather than “space separated”; avoids grammatical ambiguity early on.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Julian Edwards (julian-edwards) wrote : | # |
Thanks for reviewing!
On Friday 05 September 2014 08:06:48 you wrote:
> Review: Approve
>
> About time to line-break that ‘fields’ tuple in networks.py properly, I
> think...
I can't see anything wrong with it.
> I'd be happy to know I was worried about nothing, but will this new field
> support both empty strings and nulls? It seems like a recipe for
> confusion, e.g. if we start doing things like “if no DNS servers have been
> set on this network that we manage, substitute the MAAS DNS server.” Does
> that go for nulls, or for blanks as well? Which do you get in API results?
> Probably worth being clear about.
AFAIK it stores blanks as NULL with those field settings.
Preview Diff
1 | === modified file 'src/maasserver/api/networks.py' | |||
2 | --- src/maasserver/api/networks.py 2014-09-05 01:36:31 +0000 | |||
3 | +++ src/maasserver/api/networks.py 2014-09-05 07:17:23 +0000 | |||
4 | @@ -46,7 +46,8 @@ | |||
5 | 46 | 46 | ||
6 | 47 | model = Network | 47 | model = Network |
7 | 48 | fields = ( | 48 | fields = ( |
9 | 49 | 'name', 'ip', 'netmask', 'vlan_tag', 'description', 'default_gateway') | 49 | 'name', 'ip', 'netmask', 'vlan_tag', 'description', 'default_gateway', |
10 | 50 | 'dns_servers') | ||
11 | 50 | 51 | ||
12 | 51 | # Creation happens on the NetworksHandler. | 52 | # Creation happens on the NetworksHandler. |
13 | 52 | create = None | 53 | create = None |
14 | 53 | 54 | ||
15 | === modified file 'src/maasserver/api/tests/test_network.py' | |||
16 | --- src/maasserver/api/tests/test_network.py 2014-09-05 06:48:30 +0000 | |||
17 | +++ src/maasserver/api/tests/test_network.py 2014-09-05 07:17:23 +0000 | |||
18 | @@ -56,6 +56,7 @@ | |||
19 | 56 | network.vlan_tag, | 56 | network.vlan_tag, |
20 | 57 | network.description, | 57 | network.description, |
21 | 58 | network.default_gateway, | 58 | network.default_gateway, |
22 | 59 | network.dns_servers, | ||
23 | 59 | ), | 60 | ), |
24 | 60 | ( | 61 | ( |
25 | 61 | parsed_result['name'], | 62 | parsed_result['name'], |
26 | @@ -64,6 +65,7 @@ | |||
27 | 64 | parsed_result['vlan_tag'], | 65 | parsed_result['vlan_tag'], |
28 | 65 | parsed_result['description'], | 66 | parsed_result['description'], |
29 | 66 | parsed_result['default_gateway'], | 67 | parsed_result['default_gateway'], |
30 | 68 | parsed_result['dns_servers'], | ||
31 | 67 | )) | 69 | )) |
32 | 68 | 70 | ||
33 | 69 | def test_GET_returns_404_for_unknown_network(self): | 71 | def test_GET_returns_404_for_unknown_network(self): |
34 | @@ -82,6 +84,7 @@ | |||
35 | 82 | 'vlan_tag': factory.make_vlan_tag(), | 84 | 'vlan_tag': factory.make_vlan_tag(), |
36 | 83 | 'description': "Changed description", | 85 | 'description': "Changed description", |
37 | 84 | 'default_gateway': factory.getRandomIPAddress(), | 86 | 'default_gateway': factory.getRandomIPAddress(), |
38 | 87 | 'dns_servers': factory.getRandomIPAddress(), | ||
39 | 85 | } | 88 | } |
40 | 86 | 89 | ||
41 | 87 | response = self.client_put(self.get_url(network.name), new_values) | 90 | response = self.client_put(self.get_url(network.name), new_values) |
42 | 88 | 91 | ||
43 | === modified file 'src/maasserver/api/tests/test_networks.py' | |||
44 | --- src/maasserver/api/tests/test_networks.py 2014-09-05 06:48:30 +0000 | |||
45 | +++ src/maasserver/api/tests/test_networks.py 2014-09-05 07:17:23 +0000 | |||
46 | @@ -38,6 +38,8 @@ | |||
47 | 38 | 'netmask': '%s' % net.netmask, | 38 | 'netmask': '%s' % net.netmask, |
48 | 39 | 'vlan_tag': factory.make_vlan_tag(), | 39 | 'vlan_tag': factory.make_vlan_tag(), |
49 | 40 | 'description': factory.make_string(), | 40 | 'description': factory.make_string(), |
50 | 41 | 'default_gateway': factory.getRandomIPAddress(), | ||
51 | 42 | 'dns_servers': factory.getRandomIPAddress(), | ||
52 | 41 | } | 43 | } |
53 | 42 | response = self.client.post(reverse('networks_handler'), params) | 44 | response = self.client.post(reverse('networks_handler'), params) |
54 | 43 | self.assertEqual(httplib.OK, response.status_code) | 45 | self.assertEqual(httplib.OK, response.status_code) |
55 | @@ -63,7 +65,7 @@ | |||
56 | 63 | [returned_network] = parsed_result | 65 | [returned_network] = parsed_result |
57 | 64 | fields = { | 66 | fields = { |
58 | 65 | 'name', 'ip', 'netmask', 'vlan_tag', 'description', | 67 | 'name', 'ip', 'netmask', 'vlan_tag', 'description', |
60 | 66 | 'default_gateway'} | 68 | 'default_gateway', 'dns_servers'} |
61 | 67 | self.assertEqual( | 69 | self.assertEqual( |
62 | 68 | fields.union({'resource_uri'}), | 70 | fields.union({'resource_uri'}), |
63 | 69 | set(returned_network.keys())) | 71 | set(returned_network.keys())) |
64 | 70 | 72 | ||
65 | === modified file 'src/maasserver/forms.py' | |||
66 | --- src/maasserver/forms.py 2014-09-05 01:32:07 +0000 | |||
67 | +++ src/maasserver/forms.py 2014-09-05 07:17:23 +0000 | |||
68 | @@ -1915,6 +1915,7 @@ | |||
69 | 1915 | 'netmask', | 1915 | 'netmask', |
70 | 1916 | 'vlan_tag', | 1916 | 'vlan_tag', |
71 | 1917 | 'default_gateway', | 1917 | 'default_gateway', |
72 | 1918 | 'dns_servers', | ||
73 | 1918 | ) | 1919 | ) |
74 | 1919 | 1920 | ||
75 | 1920 | mac_addresses = NodeMACAddressChoiceField( | 1921 | mac_addresses = NodeMACAddressChoiceField( |
76 | 1921 | 1922 | ||
77 | === added file 'src/maasserver/migrations/0109_networks_dns_servers.py' | |||
78 | --- src/maasserver/migrations/0109_networks_dns_servers.py 1970-01-01 00:00:00 +0000 | |||
79 | +++ src/maasserver/migrations/0109_networks_dns_servers.py 2014-09-05 07:17:23 +0000 | |||
80 | @@ -0,0 +1,377 @@ | |||
81 | 1 | from django.db import models | ||
82 | 2 | from south.db import db | ||
83 | 3 | # -*- coding: utf-8 -*- | ||
84 | 4 | from south.utils import datetime_utils as datetime | ||
85 | 5 | from south.v2 import SchemaMigration | ||
86 | 6 | |||
87 | 7 | |||
88 | 8 | class Migration(SchemaMigration): | ||
89 | 9 | |||
90 | 10 | def forwards(self, orm): | ||
91 | 11 | # Adding field 'Network.dns_servers' | ||
92 | 12 | db.add_column(u'maasserver_network', 'dns_servers', | ||
93 | 13 | self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), | ||
94 | 14 | keep_default=False) | ||
95 | 15 | |||
96 | 16 | |||
97 | 17 | def backwards(self, orm): | ||
98 | 18 | # Deleting field 'Network.dns_servers' | ||
99 | 19 | db.delete_column(u'maasserver_network', 'dns_servers') | ||
100 | 20 | |||
101 | 21 | |||
102 | 22 | models = { | ||
103 | 23 | u'auth.group': { | ||
104 | 24 | 'Meta': {'object_name': 'Group'}, | ||
105 | 25 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
106 | 26 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
107 | 27 | 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
108 | 28 | }, | ||
109 | 29 | u'auth.permission': { | ||
110 | 30 | 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, | ||
111 | 31 | 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
112 | 32 | 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), | ||
113 | 33 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
114 | 34 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
115 | 35 | }, | ||
116 | 36 | u'auth.user': { | ||
117 | 37 | 'Meta': {'object_name': 'User'}, | ||
118 | 38 | 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
119 | 39 | 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'blank': 'True'}), | ||
120 | 40 | 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
121 | 41 | 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), | ||
122 | 42 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
123 | 43 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
124 | 44 | 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
125 | 45 | 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
126 | 46 | 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
127 | 47 | 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
128 | 48 | 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
129 | 49 | 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), | ||
130 | 50 | 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
131 | 51 | }, | ||
132 | 52 | u'contenttypes.contenttype': { | ||
133 | 53 | 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
134 | 54 | 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
135 | 55 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
136 | 56 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
137 | 57 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
138 | 58 | }, | ||
139 | 59 | u'maasserver.bootimage': { | ||
140 | 60 | 'Meta': {'unique_together': "((u'nodegroup', u'osystem', u'architecture', u'subarchitecture', u'release', u'purpose', u'label'),)", 'object_name': 'BootImage'}, | ||
141 | 61 | 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
142 | 62 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
143 | 63 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
144 | 64 | 'label': ('django.db.models.fields.CharField', [], {'default': "u'release'", 'max_length': '255'}), | ||
145 | 65 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), | ||
146 | 66 | 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
147 | 67 | 'purpose': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
148 | 68 | 'release': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
149 | 69 | 'subarchitecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
150 | 70 | 'supported_subarches': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), | ||
151 | 71 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
152 | 72 | 'xinstall_path': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
153 | 73 | 'xinstall_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '30', 'null': 'True', 'blank': 'True'}) | ||
154 | 74 | }, | ||
155 | 75 | u'maasserver.bootresource': { | ||
156 | 76 | 'Meta': {'unique_together': "((u'name', u'architecture'),)", 'object_name': 'BootResource'}, | ||
157 | 77 | 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
158 | 78 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
159 | 79 | 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
160 | 80 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
161 | 81 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
162 | 82 | 'rtype': ('django.db.models.fields.IntegerField', [], {'max_length': '10'}), | ||
163 | 83 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
164 | 84 | }, | ||
165 | 85 | u'maasserver.bootresourcefile': { | ||
166 | 86 | 'Meta': {'unique_together': "((u'resource_set', u'filetype'),)", 'object_name': 'BootResourceFile'}, | ||
167 | 87 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
168 | 88 | 'extra': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
169 | 89 | 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
170 | 90 | 'filetype': ('django.db.models.fields.CharField', [], {'default': "u'root-tgz'", 'max_length': '20'}), | ||
171 | 91 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
172 | 92 | 'largefile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.LargeFile']"}), | ||
173 | 93 | 'resource_set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'files'", 'to': u"orm['maasserver.BootResourceSet']"}), | ||
174 | 94 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
175 | 95 | }, | ||
176 | 96 | u'maasserver.bootresourceset': { | ||
177 | 97 | 'Meta': {'unique_together': "((u'resource', u'version'),)", 'object_name': 'BootResourceSet'}, | ||
178 | 98 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
179 | 99 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
180 | 100 | 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
181 | 101 | 'resource': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'sets'", 'to': u"orm['maasserver.BootResource']"}), | ||
182 | 102 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
183 | 103 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '255'}) | ||
184 | 104 | }, | ||
185 | 105 | u'maasserver.bootsource': { | ||
186 | 106 | 'Meta': {'object_name': 'BootSource'}, | ||
187 | 107 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
188 | 108 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
189 | 109 | 'keyring_data': ('maasserver.fields.EditableBinaryField', [], {'blank': 'True'}), | ||
190 | 110 | 'keyring_filename': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}), | ||
191 | 111 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
192 | 112 | 'url': ('django.db.models.fields.URLField', [], {'unique': 'True', 'max_length': '200'}) | ||
193 | 113 | }, | ||
194 | 114 | u'maasserver.bootsourceselection': { | ||
195 | 115 | 'Meta': {'object_name': 'BootSourceSelection'}, | ||
196 | 116 | 'arches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), | ||
197 | 117 | 'boot_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.BootSource']"}), | ||
198 | 118 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
199 | 119 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
200 | 120 | 'labels': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), | ||
201 | 121 | 'os': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
202 | 122 | 'release': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
203 | 123 | 'subarches': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'text'", 'null': 'True', 'blank': 'True'}), | ||
204 | 124 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
205 | 125 | }, | ||
206 | 126 | u'maasserver.candidatename': { | ||
207 | 127 | 'Meta': {'unique_together': "((u'name', u'position'),)", 'object_name': 'CandidateName'}, | ||
208 | 128 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
209 | 129 | 'name': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), | ||
210 | 130 | 'position': ('django.db.models.fields.IntegerField', [], {}) | ||
211 | 131 | }, | ||
212 | 132 | u'maasserver.componenterror': { | ||
213 | 133 | 'Meta': {'object_name': 'ComponentError'}, | ||
214 | 134 | 'component': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}), | ||
215 | 135 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
216 | 136 | 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), | ||
217 | 137 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
218 | 138 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
219 | 139 | }, | ||
220 | 140 | u'maasserver.config': { | ||
221 | 141 | 'Meta': {'object_name': 'Config'}, | ||
222 | 142 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
223 | 143 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
224 | 144 | 'value': ('maasserver.fields.JSONObjectField', [], {'null': 'True'}) | ||
225 | 145 | }, | ||
226 | 146 | u'maasserver.dhcplease': { | ||
227 | 147 | 'Meta': {'object_name': 'DHCPLease'}, | ||
228 | 148 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
229 | 149 | 'ip': ('maasserver.fields.MAASIPAddressField', [], {'unique': 'True', 'max_length': '39'}), | ||
230 | 150 | 'mac': ('maasserver.fields.MACAddressField', [], {}), | ||
231 | 151 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}) | ||
232 | 152 | }, | ||
233 | 153 | u'maasserver.downloadprogress': { | ||
234 | 154 | 'Meta': {'object_name': 'DownloadProgress'}, | ||
235 | 155 | 'bytes_downloaded': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
236 | 156 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
237 | 157 | 'error': ('django.db.models.fields.CharField', [], {'max_length': '1000', 'blank': 'True'}), | ||
238 | 158 | 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
239 | 159 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
240 | 160 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), | ||
241 | 161 | 'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), | ||
242 | 162 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
243 | 163 | }, | ||
244 | 164 | u'maasserver.event': { | ||
245 | 165 | 'Meta': {'object_name': 'Event'}, | ||
246 | 166 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
247 | 167 | 'description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}), | ||
248 | 168 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
249 | 169 | 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}), | ||
250 | 170 | 'type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.EventType']"}), | ||
251 | 171 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
252 | 172 | }, | ||
253 | 173 | u'maasserver.eventtype': { | ||
254 | 174 | 'Meta': {'object_name': 'EventType'}, | ||
255 | 175 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
256 | 176 | 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
257 | 177 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
258 | 178 | 'level': ('django.db.models.fields.IntegerField', [], {}), | ||
259 | 179 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), | ||
260 | 180 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
261 | 181 | }, | ||
262 | 182 | u'maasserver.filestorage': { | ||
263 | 183 | 'Meta': {'unique_together': "((u'filename', u'owner'),)", 'object_name': 'FileStorage'}, | ||
264 | 184 | 'content': ('metadataserver.fields.BinaryField', [], {'blank': 'True'}), | ||
265 | 185 | 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
266 | 186 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
267 | 187 | 'key': ('django.db.models.fields.CharField', [], {'default': "u'35907f12-34bb-11e4-bb2b-002215205ce8'", 'unique': 'True', 'max_length': '36'}), | ||
268 | 188 | 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) | ||
269 | 189 | }, | ||
270 | 190 | u'maasserver.largefile': { | ||
271 | 191 | 'Meta': {'object_name': 'LargeFile'}, | ||
272 | 192 | 'content': ('maasserver.fields.LargeObjectField', [], {}), | ||
273 | 193 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
274 | 194 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
275 | 195 | 'sha256': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), | ||
276 | 196 | 'total_size': ('django.db.models.fields.BigIntegerField', [], {}), | ||
277 | 197 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
278 | 198 | }, | ||
279 | 199 | u'maasserver.licensekey': { | ||
280 | 200 | 'Meta': {'unique_together': "((u'osystem', u'distro_series'),)", 'object_name': 'LicenseKey'}, | ||
281 | 201 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
282 | 202 | 'distro_series': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
283 | 203 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
284 | 204 | 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
285 | 205 | 'osystem': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
286 | 206 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
287 | 207 | }, | ||
288 | 208 | u'maasserver.macaddress': { | ||
289 | 209 | 'Meta': {'ordering': "(u'created',)", 'object_name': 'MACAddress'}, | ||
290 | 210 | 'cluster_interface': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['maasserver.NodeGroupInterface']", 'null': 'True', 'blank': 'True'}), | ||
291 | 211 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
292 | 212 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
293 | 213 | 'ip_addresses': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.StaticIPAddress']", 'symmetrical': 'False', 'through': u"orm['maasserver.MACStaticIPAddressLink']", 'blank': 'True'}), | ||
294 | 214 | 'mac_address': ('maasserver.fields.MACAddressField', [], {'unique': 'True'}), | ||
295 | 215 | 'networks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Network']", 'symmetrical': 'False', 'blank': 'True'}), | ||
296 | 216 | 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Node']"}), | ||
297 | 217 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
298 | 218 | }, | ||
299 | 219 | u'maasserver.macstaticipaddresslink': { | ||
300 | 220 | 'Meta': {'unique_together': "((u'ip_address', u'mac_address'),)", 'object_name': 'MACStaticIPAddressLink'}, | ||
301 | 221 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
302 | 222 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
303 | 223 | 'ip_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.StaticIPAddress']", 'unique': 'True'}), | ||
304 | 224 | 'mac_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.MACAddress']"}), | ||
305 | 225 | 'nic_alias': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), | ||
306 | 226 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
307 | 227 | }, | ||
308 | 228 | u'maasserver.network': { | ||
309 | 229 | 'Meta': {'object_name': 'Network'}, | ||
310 | 230 | 'default_gateway': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
311 | 231 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
312 | 232 | 'dns_servers': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
313 | 233 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
314 | 234 | 'ip': ('maasserver.fields.MAASIPAddressField', [], {'unique': 'True', 'max_length': '39'}), | ||
315 | 235 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), | ||
316 | 236 | 'netmask': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}), | ||
317 | 237 | 'vlan_tag': ('django.db.models.fields.PositiveSmallIntegerField', [], {'unique': 'True', 'null': 'True', 'blank': 'True'}) | ||
318 | 238 | }, | ||
319 | 239 | u'maasserver.node': { | ||
320 | 240 | 'Meta': {'object_name': 'Node'}, | ||
321 | 241 | 'agent_name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
322 | 242 | 'architecture': ('django.db.models.fields.CharField', [], {'max_length': '31'}), | ||
323 | 243 | 'boot_type': ('django.db.models.fields.CharField', [], {'default': "u'fastpath'", 'max_length': '20'}), | ||
324 | 244 | 'cpu_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
325 | 245 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
326 | 246 | 'disable_ipv4': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
327 | 247 | 'distro_series': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
328 | 248 | 'error': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
329 | 249 | 'error_description': ('django.db.models.fields.TextField', [], {'default': "u''", 'blank': 'True'}), | ||
330 | 250 | 'hostname': ('django.db.models.fields.CharField', [], {'default': "u''", 'unique': 'True', 'max_length': '255', 'blank': 'True'}), | ||
331 | 251 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
332 | 252 | 'license_key': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), | ||
333 | 253 | 'memory': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
334 | 254 | 'netboot': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
335 | 255 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']", 'null': 'True'}), | ||
336 | 256 | 'osystem': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '20', 'blank': 'True'}), | ||
337 | 257 | 'owner': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}), | ||
338 | 258 | 'power_parameters': ('maasserver.fields.JSONObjectField', [], {'default': "u''", 'blank': 'True'}), | ||
339 | 259 | 'power_state': ('django.db.models.fields.CharField', [], {'default': "u'unknown'", 'max_length': '10'}), | ||
340 | 260 | 'power_type': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '10', 'blank': 'True'}), | ||
341 | 261 | 'routers': ('djorm_pgarray.fields.ArrayField', [], {'default': 'None', 'dbtype': "u'macaddr'", 'null': 'True', 'blank': 'True'}), | ||
342 | 262 | 'status': ('django.db.models.fields.IntegerField', [], {'default': '0', 'max_length': '10'}), | ||
343 | 263 | 'storage': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
344 | 264 | 'system_id': ('django.db.models.fields.CharField', [], {'default': "u'node-358bdb4c-34bb-11e4-bb2b-002215205ce8'", 'unique': 'True', 'max_length': '41'}), | ||
345 | 265 | 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['maasserver.Tag']", 'symmetrical': 'False'}), | ||
346 | 266 | 'token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'null': 'True'}), | ||
347 | 267 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
348 | 268 | 'zone': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.Zone']", 'on_delete': 'models.SET_DEFAULT'}) | ||
349 | 269 | }, | ||
350 | 270 | u'maasserver.nodegroup': { | ||
351 | 271 | 'Meta': {'object_name': 'NodeGroup'}, | ||
352 | 272 | 'api_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '18'}), | ||
353 | 273 | 'api_token': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Token']", 'unique': 'True'}), | ||
354 | 274 | 'cluster_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100', 'blank': 'True'}), | ||
355 | 275 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
356 | 276 | 'dhcp_key': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
357 | 277 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
358 | 278 | 'maas_url': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
359 | 279 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}), | ||
360 | 280 | 'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
361 | 281 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
362 | 282 | 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '36'}) | ||
363 | 283 | }, | ||
364 | 284 | u'maasserver.nodegroupinterface': { | ||
365 | 285 | 'Meta': {'unique_together': "((u'nodegroup', u'name'),)", 'object_name': 'NodeGroupInterface'}, | ||
366 | 286 | 'broadcast_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
367 | 287 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
368 | 288 | 'foreign_dhcp_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
369 | 289 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
370 | 290 | 'interface': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
371 | 291 | 'ip': ('maasserver.fields.MAASIPAddressField', [], {'max_length': '39'}), | ||
372 | 292 | 'ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
373 | 293 | 'ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
374 | 294 | 'management': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
375 | 295 | 'name': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'blank': 'True'}), | ||
376 | 296 | 'nodegroup': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['maasserver.NodeGroup']"}), | ||
377 | 297 | 'router_ip': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
378 | 298 | 'static_ip_range_high': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
379 | 299 | 'static_ip_range_low': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
380 | 300 | 'subnet_mask': ('maasserver.fields.MAASIPAddressField', [], {'default': 'None', 'max_length': '39', 'null': 'True', 'blank': 'True'}), | ||
381 | 301 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
382 | 302 | }, | ||
383 | 303 | u'maasserver.sshkey': { | ||
384 | 304 | 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSHKey'}, | ||
385 | 305 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
386 | 306 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
387 | 307 | 'key': ('django.db.models.fields.TextField', [], {}), | ||
388 | 308 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
389 | 309 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) | ||
390 | 310 | }, | ||
391 | 311 | u'maasserver.sslkey': { | ||
392 | 312 | 'Meta': {'unique_together': "((u'user', u'key'),)", 'object_name': 'SSLKey'}, | ||
393 | 313 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
394 | 314 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
395 | 315 | 'key': ('django.db.models.fields.TextField', [], {}), | ||
396 | 316 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
397 | 317 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) | ||
398 | 318 | }, | ||
399 | 319 | u'maasserver.staticipaddress': { | ||
400 | 320 | 'Meta': {'object_name': 'StaticIPAddress'}, | ||
401 | 321 | 'alloc_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
402 | 322 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
403 | 323 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
404 | 324 | 'ip': ('maasserver.fields.MAASIPAddressField', [], {'unique': 'True', 'max_length': '39'}), | ||
405 | 325 | 'updated': ('django.db.models.fields.DateTimeField', [], {}), | ||
406 | 326 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) | ||
407 | 327 | }, | ||
408 | 328 | u'maasserver.tag': { | ||
409 | 329 | 'Meta': {'object_name': 'Tag'}, | ||
410 | 330 | 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
411 | 331 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
412 | 332 | 'definition': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
413 | 333 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
414 | 334 | 'kernel_opts': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), | ||
415 | 335 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), | ||
416 | 336 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
417 | 337 | }, | ||
418 | 338 | u'maasserver.userprofile': { | ||
419 | 339 | 'Meta': {'object_name': 'UserProfile'}, | ||
420 | 340 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
421 | 341 | 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True'}) | ||
422 | 342 | }, | ||
423 | 343 | u'maasserver.zone': { | ||
424 | 344 | 'Meta': {'ordering': "[u'name']", 'object_name': 'Zone'}, | ||
425 | 345 | 'created': ('django.db.models.fields.DateTimeField', [], {}), | ||
426 | 346 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
427 | 347 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
428 | 348 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '256'}), | ||
429 | 349 | 'updated': ('django.db.models.fields.DateTimeField', [], {}) | ||
430 | 350 | }, | ||
431 | 351 | u'piston.consumer': { | ||
432 | 352 | 'Meta': {'object_name': 'Consumer'}, | ||
433 | 353 | 'description': ('django.db.models.fields.TextField', [], {}), | ||
434 | 354 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
435 | 355 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), | ||
436 | 356 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||
437 | 357 | 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), | ||
438 | 358 | 'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '16'}), | ||
439 | 359 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'consumers'", 'null': 'True', 'to': u"orm['auth.User']"}) | ||
440 | 360 | }, | ||
441 | 361 | u'piston.token': { | ||
442 | 362 | 'Meta': {'object_name': 'Token'}, | ||
443 | 363 | 'callback': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), | ||
444 | 364 | 'callback_confirmed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
445 | 365 | 'consumer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['piston.Consumer']"}), | ||
446 | 366 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
447 | 367 | 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
448 | 368 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '18'}), | ||
449 | 369 | 'secret': ('django.db.models.fields.CharField', [], {'max_length': '32'}), | ||
450 | 370 | 'timestamp': ('django.db.models.fields.IntegerField', [], {'default': '1409893937L'}), | ||
451 | 371 | 'token_type': ('django.db.models.fields.IntegerField', [], {}), | ||
452 | 372 | 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tokens'", 'null': 'True', 'to': u"orm['auth.User']"}), | ||
453 | 373 | 'verifier': ('django.db.models.fields.CharField', [], {'max_length': '10'}) | ||
454 | 374 | } | ||
455 | 375 | } | ||
456 | 376 | |||
457 | 377 | complete_apps = ['maasserver'] | ||
458 | 0 | \ No newline at end of file | 378 | \ No newline at end of file |
459 | 1 | 379 | ||
460 | === modified file 'src/maasserver/models/network.py' | |||
461 | --- src/maasserver/models/network.py 2014-09-01 01:45:04 +0000 | |||
462 | +++ src/maasserver/models/network.py 2014-09-05 07:17:23 +0000 | |||
463 | @@ -248,6 +248,11 @@ | |||
464 | 248 | blank=True, editable=True, null=True, | 248 | blank=True, editable=True, null=True, |
465 | 249 | help_text="Default gateway for this network (e.g. 192.168.1.1).") | 249 | help_text="Default gateway for this network (e.g. 192.168.1.1).") |
466 | 250 | 250 | ||
467 | 251 | dns_servers = CharField( | ||
468 | 252 | blank=True, editable=True, null=True, max_length=255, | ||
469 | 253 | help_text="Space separated list of DNS server addresses that this " | ||
470 | 254 | "network may use.") | ||
471 | 255 | |||
472 | 251 | vlan_tag = PositiveSmallIntegerField( | 256 | vlan_tag = PositiveSmallIntegerField( |
473 | 252 | editable=True, null=True, blank=True, unique=True, | 257 | editable=True, null=True, blank=True, unique=True, |
474 | 253 | help_text="A 12-bit field specifying the VLAN to which the frame " | 258 | help_text="A 12-bit field specifying the VLAN to which the frame " |
475 | 254 | 259 | ||
476 | === modified file 'src/maasserver/templates/maasserver/network_detail.html' | |||
477 | --- src/maasserver/templates/maasserver/network_detail.html 2014-09-05 01:23:06 +0000 | |||
478 | +++ src/maasserver/templates/maasserver/network_detail.html 2014-09-05 07:17:23 +0000 | |||
479 | @@ -44,6 +44,10 @@ | |||
480 | 44 | <span>{{ network.default_gateway|default_if_none:"" }}</span> | 44 | <span>{{ network.default_gateway|default_if_none:"" }}</span> |
481 | 45 | </li> | 45 | </li> |
482 | 46 | <li class="block size2"> | 46 | <li class="block size2"> |
483 | 47 | <h4>DNS servers</h4> | ||
484 | 48 | <span>{{ network.dns_servers|default_if_none:"" }}</span> | ||
485 | 49 | </li> | ||
486 | 50 | <li class="block size2"> | ||
487 | 47 | <h4>Attached nodes</h4> | 51 | <h4>Attached nodes</h4> |
488 | 48 | <span id="nodecount"> | 52 | <span id="nodecount"> |
489 | 49 | <a title="View nodes attached to network {{ network.name }}" | 53 | <a title="View nodes attached to network {{ network.name }}" |
490 | 50 | 54 | ||
491 | === modified file 'src/maasserver/testing/factory.py' | |||
492 | --- src/maasserver/testing/factory.py 2014-09-05 06:36:56 +0000 | |||
493 | +++ src/maasserver/testing/factory.py 2014-09-05 07:17:23 +0000 | |||
494 | @@ -864,7 +864,8 @@ | |||
495 | 864 | 864 | ||
496 | 865 | def make_Network(self, name=None, network=None, vlan_tag=NO_VALUE, | 865 | def make_Network(self, name=None, network=None, vlan_tag=NO_VALUE, |
497 | 866 | description=None, sortable_name=False, | 866 | description=None, sortable_name=False, |
499 | 867 | disjoint_from=None, default_gateway=None): | 867 | disjoint_from=None, default_gateway=None, |
500 | 868 | dns_servers=None): | ||
501 | 868 | """Create a `Network`. | 869 | """Create a `Network`. |
502 | 869 | 870 | ||
503 | 870 | :param network: An `IPNetwork`. If given, the `ip` and `netmask` | 871 | :param network: An `IPNetwork`. If given, the `ip` and `netmask` |
504 | @@ -899,6 +900,10 @@ | |||
505 | 899 | network = self.getRandomNetwork(disjoint_from=disjoint_from) | 900 | network = self.getRandomNetwork(disjoint_from=disjoint_from) |
506 | 900 | if default_gateway is None and self.pick_bool(): | 901 | if default_gateway is None and self.pick_bool(): |
507 | 901 | default_gateway = self.pick_ip_in_network(network) | 902 | default_gateway = self.pick_ip_in_network(network) |
508 | 903 | if dns_servers is None and self.pick_bool(): | ||
509 | 904 | dns_servers = " ".join( | ||
510 | 905 | self.getRandomIPAddress() | ||
511 | 906 | for _ in range(random.choice((1, 2)))) | ||
512 | 902 | ip = unicode(network.ip) | 907 | ip = unicode(network.ip) |
513 | 903 | netmask = unicode(network.netmask) | 908 | netmask = unicode(network.netmask) |
514 | 904 | if description is None: | 909 | if description is None: |
515 | @@ -907,7 +912,8 @@ | |||
516 | 907 | vlan_tag = self.make_vlan_tag() | 912 | vlan_tag = self.make_vlan_tag() |
517 | 908 | network = Network( | 913 | network = Network( |
518 | 909 | name=name, ip=ip, netmask=netmask, vlan_tag=vlan_tag, | 914 | name=name, ip=ip, netmask=netmask, vlan_tag=vlan_tag, |
520 | 910 | description=description, default_gateway=default_gateway) | 915 | description=description, default_gateway=default_gateway, |
521 | 916 | dns_servers=dns_servers) | ||
522 | 911 | network.save() | 917 | network.save() |
523 | 912 | return network | 918 | return network |
524 | 913 | 919 | ||
525 | 914 | 920 | ||
526 | === modified file 'src/maasserver/views/tests/test_networks.py' | |||
527 | --- src/maasserver/views/tests/test_networks.py 2014-09-05 06:48:30 +0000 | |||
528 | +++ src/maasserver/views/tests/test_networks.py 2014-09-05 07:17:23 +0000 | |||
529 | @@ -200,6 +200,7 @@ | |||
530 | 200 | 'netmask': "%s" % network.netmask, | 200 | 'netmask': "%s" % network.netmask, |
531 | 201 | 'vlan_tag': factory.make_vlan_tag(), | 201 | 'vlan_tag': factory.make_vlan_tag(), |
532 | 202 | 'default_gateway': factory.getRandomIPAddress(), | 202 | 'default_gateway': factory.getRandomIPAddress(), |
533 | 203 | 'dns_servers': factory.getRandomIPAddress(), | ||
534 | 203 | } | 204 | } |
535 | 204 | response = self.client.post(reverse('network-add'), definition) | 205 | response = self.client.post(reverse('network-add'), definition) |
536 | 205 | self.assertEqual(httplib.FOUND, response.status_code) | 206 | self.assertEqual(httplib.FOUND, response.status_code) |
537 | @@ -315,6 +316,7 @@ | |||
538 | 315 | factory.make_mac_address() | 316 | factory.make_mac_address() |
539 | 316 | for _ in range(3)] | 317 | for _ in range(3)] |
540 | 317 | new_gateway = factory.getRandomIPAddress() | 318 | new_gateway = factory.getRandomIPAddress() |
541 | 319 | new_dns_servers = factory.getRandomIPAddress() | ||
542 | 318 | response = self.client.post( | 320 | response = self.client.post( |
543 | 319 | reverse('network-edit', args=[network.name]), | 321 | reverse('network-edit', args=[network.name]), |
544 | 320 | data={ | 322 | data={ |
545 | @@ -322,6 +324,7 @@ | |||
546 | 322 | 'description': new_description, | 324 | 'description': new_description, |
547 | 323 | 'default_gateway': new_gateway, | 325 | 'default_gateway': new_gateway, |
548 | 324 | 'mac_addresses': new_macs, | 326 | 'mac_addresses': new_macs, |
549 | 327 | 'dns_servers': new_dns_servers, | ||
550 | 325 | }) | 328 | }) |
551 | 326 | self.assertEqual( | 329 | self.assertEqual( |
552 | 327 | reverse('network-list'), extract_redirect(response), | 330 | reverse('network-list'), extract_redirect(response), |
Don't be afraid of the size of the branch, most of it is the migration.