Merge lp:~rvb/launchpad/virtuality-restricted-bug-837975 into lp:launchpad

Proposed by Raphaël Badin
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 13895
Proposed branch: lp:~rvb/launchpad/virtuality-restricted-bug-837975
Merge into: lp:launchpad
Diff against target: 683 lines (+387/-45)
8 files modified
lib/lp/registry/browser/distribution.py (+110/-3)
lib/lp/registry/browser/tests/distribution-views.txt (+2/-0)
lib/lp/registry/browser/tests/test_distribution_views.py (+192/-14)
lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt (+5/-0)
lib/lp/soyuz/browser/archive.py (+51/-18)
lib/lp/soyuz/model/archive.py (+10/-7)
lib/lp/soyuz/tests/test_archive.py (+16/-3)
lib/lp/translations/browser/distribution.py (+1/-0)
To merge this branch: bzr merge lp:~rvb/launchpad/virtuality-restricted-bug-837975
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Review via email: mp+74120@code.launchpad.net

Commit message

[r=gmb][bug=837975] Add two fields to distro's +add and +edit pages.

Description of the change

This branch adds two fields to distro's +add and +edit pages. They will be used to tweak the virtuality and the restricted architectures of the distro's main archive (http://people.canonical.com/~rvb/distro_edit.png). The main changes of this branch (apart from UI changes) are the changes made to archive to allow changing enabled_restricted_families for main archives if the archive is set virtualized (require_virtualized is True).

= Tests =

./bin/test -vvc test_distribution_views test_add_distro_default_value_require_virtualized
./bin/test -vvc test_distribution_views test_add_distro_init_value_enabled_restricted_families
./bin/test -vvc test_distribution_views test_add_distro_require_virtualized
./bin/test -vvc test_distribution_views test_add_distro_enabled_restricted_families
./bin/test -vvc test_distribution_views test_add_distro_enabled_restricted_families_error
./bin/test -vvc test_distribution_views test_edit_distro_init_value_require_virtualized
./bin/test -vvc test_distribution_views test_edit_distro_init_value_enabled_restricted_families
./bin/test -vvc test_distribution_views test_change_require_virtualized
./bin/test -vvc test_distribution_views test_change_enabled_restricted_families
./bin/test -vvc test_distribution_views test_cannot_change_enabled_restricted_families

./bin/test -vvc test_archive test_main_archive_can_not_be_restricted_not_virtualized
./bin/test -vvc test_archive test_main_virtualized_archive_can_be_restricted

= QA =

Create a new distro
https://dogfood.launchpad.net/distros/+add and make sure the new fields are there. Make sure that "Enabled restricted families" can only be changed if "Require virtualized builders" is checked. Same test for https://dogfood.launchpad.net/mydistro/+edit.

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/browser/distribution.py'
2--- lib/lp/registry/browser/distribution.py 2011-06-16 13:50:58 +0000
3+++ lib/lp/registry/browser/distribution.py 2011-09-07 09:26:38 +0000
4@@ -41,11 +41,13 @@
5 from collections import defaultdict
6 import datetime
7
8+from zope.app.form.browser.boolwidgets import CheckBoxWidget
9 from zope.component import getUtility
10 from zope.event import notify
11 from zope.formlib import form
12 from zope.interface import implements
13 from zope.lifecycleevent import ObjectCreatedEvent
14+from zope.schema import Bool
15 from zope.security.interfaces import Unauthorized
16
17 from canonical.launchpad.browser.feeds import FeedsMixin
18@@ -82,6 +84,7 @@
19 )
20 from lp.app.errors import NotFoundError
21 from lp.app.widgets.image import ImageChangeWidget
22+from lp.app.widgets.itemswidgets import LabeledMultiCheckBoxWidget
23 from lp.archivepublisher.interfaces.publisherconfig import (
24 IPublisherConfig,
25 IPublisherConfigSet,
26@@ -104,8 +107,8 @@
27 IRegistryCollectionNavigationMenu,
28 RegistryCollectionActionMenuBase,
29 )
30+from lp.registry.browser.objectreassignment import ObjectReassignmentView
31 from lp.registry.browser.pillar import PillarBugsMenu
32-from lp.registry.browser.objectreassignment import ObjectReassignmentView
33 from lp.registry.interfaces.distribution import (
34 IDerivativeDistribution,
35 IDistribution,
36@@ -123,9 +126,11 @@
37 request_country,
38 )
39 from lp.services.propertycache import cachedproperty
40+from lp.soyuz.browser.archive import EnableRestrictedFamiliesMixin
41 from lp.soyuz.browser.packagesearch import PackageSearchViewBase
42 from lp.soyuz.enums import ArchivePurpose
43 from lp.soyuz.interfaces.archive import IArchiveSet
44+from lp.soyuz.interfaces.processor import IProcessorFamilySet
45
46
47 class DistributionNavigation(
48@@ -772,7 +777,27 @@
49 return self.context.count()
50
51
52-class DistributionAddView(LaunchpadFormView):
53+class RequireVirtualizedBuildersMixin:
54+ """A mixin that provides require_virtualized field support"""
55+
56+ def createRequireVirtualized(self):
57+ return form.Fields(
58+ Bool(
59+ __name__='require_virtualized',
60+ title=u"Require virtualized builders",
61+ description=(
62+ u"Only build the distribution's packages on virtual "
63+ "builders."),
64+ required=True))
65+
66+ def updateRequireVirtualized(self, require_virtualized, archive):
67+ if archive.require_virtualized != require_virtualized:
68+ archive.require_virtualized = require_virtualized
69+
70+
71+class DistributionAddView(LaunchpadFormView,
72+ RequireVirtualizedBuildersMixin,
73+ EnableRestrictedFamiliesMixin):
74
75 schema = IDistribution
76 label = "Register a new distribution"
77@@ -789,17 +814,40 @@
78 "official_rosetta",
79 "answers_usage",
80 ]
81+ custom_widget('require_virtualized', CheckBoxWidget)
82+ custom_widget('enabled_restricted_families', LabeledMultiCheckBoxWidget)
83
84 @property
85 def page_title(self):
86 """The page title."""
87 return self.label
88
89+ def validate(self, data):
90+ self.validate_enabled_restricted_families(
91+ data, ENABLED_RESTRICTED_FAMILITES_ERROR_MSG)
92+
93+ @property
94+ def initial_values(self):
95+ proc_family_set = getUtility(IProcessorFamilySet)
96+ restricted_families = set(proc_family_set.getRestricted())
97+ return {
98+ 'enabled_restricted_families': restricted_families,
99+ 'require_virtualized': False,
100+ }
101+
102 @property
103 def cancel_url(self):
104 """See `LaunchpadFormView`."""
105 return canonical_url(self.context)
106
107+ def setUpFields(self):
108+ """See `LaunchpadFormView`."""
109+ LaunchpadFormView.setUpFields(self)
110+ self.form_fields += self.createRequireVirtualized()
111+ self.form_fields += self.createEnabledRestrictedFamilies(
112+ u'The restricted architecture families on which the '
113+ "distribution's main archive can build.")
114+
115 @action("Save", name='save')
116 def save_action(self, action, data):
117 distribution = getUtility(IDistributionSet).new(
118@@ -813,11 +861,25 @@
119 owner=self.user,
120 registrant=self.user,
121 )
122+ archive = distribution.main_archive
123+ self.updateRequireVirtualized(data['require_virtualized'], archive)
124+ if archive.require_virtualized is True:
125+ archive.enabled_restricted_families = (
126+ data['enabled_restricted_families'])
127+
128 notify(ObjectCreatedEvent(distribution))
129 self.next_url = canonical_url(distribution)
130
131
132-class DistributionEditView(RegistryEditFormView):
133+ENABLED_RESTRICTED_FAMILITES_ERROR_MSG = (
134+ u"This distribution's main archive can not be restricted to "
135+ 'certain architectures unless the archive is also set '
136+ 'to build on virtualized builders.')
137+
138+
139+class DistributionEditView(RegistryEditFormView,
140+ RequireVirtualizedBuildersMixin,
141+ EnableRestrictedFamiliesMixin):
142
143 schema = IDistribution
144 field_names = [
145@@ -841,12 +903,31 @@
146 custom_widget('icon', ImageChangeWidget, ImageChangeWidget.EDIT_STYLE)
147 custom_widget('logo', ImageChangeWidget, ImageChangeWidget.EDIT_STYLE)
148 custom_widget('mugshot', ImageChangeWidget, ImageChangeWidget.EDIT_STYLE)
149+ custom_widget('require_virtualized', CheckBoxWidget)
150+ custom_widget('enabled_restricted_families', LabeledMultiCheckBoxWidget)
151
152 @property
153 def label(self):
154 """See `LaunchpadFormView`."""
155 return 'Change %s details' % self.context.displayname
156
157+ def setUpFields(self):
158+ """See `LaunchpadFormView`."""
159+ RegistryEditFormView.setUpFields(self)
160+ self.form_fields += self.createRequireVirtualized()
161+ self.form_fields += self.createEnabledRestrictedFamilies(
162+ u'The restricted architecture families on which the '
163+ "distribution's main archive can build.")
164+
165+ @property
166+ def initial_values(self):
167+ return {
168+ 'require_virtualized':
169+ self.context.main_archive.require_virtualized,
170+ 'enabled_restricted_families':
171+ self.context.main_archive.enabled_restricted_families,
172+ }
173+
174 def validate(self, data):
175 """Constrain bug expiration to Launchpad Bugs tracker."""
176 # enable_bug_expiration is disabled by JavaScript when official_malone
177@@ -856,6 +937,32 @@
178 if not official_malone:
179 data['enable_bug_expiration'] = False
180
181+ # Validate enabled_restricted_families.
182+ self.validate_enabled_restricted_families(
183+ data,
184+ ENABLED_RESTRICTED_FAMILITES_ERROR_MSG)
185+
186+ def change_archive_fields(self, data):
187+ # Update context.main_archive.
188+ new_require_virtualized = data.get('require_virtualized')
189+ if new_require_virtualized is not None:
190+ self.updateRequireVirtualized(
191+ new_require_virtualized, self.context.main_archive)
192+ del(data['require_virtualized'])
193+ new_enabled_restricted_families = data.get(
194+ 'enabled_restricted_families')
195+ if new_enabled_restricted_families is not None:
196+ if (set(self.context.main_archive.enabled_restricted_families) !=
197+ set(new_enabled_restricted_families)):
198+ self.context.main_archive.enabled_restricted_families = (
199+ new_enabled_restricted_families)
200+ del(data['enabled_restricted_families'])
201+
202+ @action("Change", name='change')
203+ def change_action(self, action, data):
204+ self.change_archive_fields(data)
205+ self.updateContextFromData(data)
206+
207
208 class DistributionSeriesBaseView(LaunchpadView):
209 """A base view to list distroseries."""
210
211=== modified file 'lib/lp/registry/browser/tests/distribution-views.txt'
212--- lib/lp/registry/browser/tests/distribution-views.txt 2011-04-08 13:04:24 +0000
213+++ lib/lp/registry/browser/tests/distribution-views.txt 2011-09-07 09:26:38 +0000
214@@ -79,6 +79,8 @@
215 ... 'field.description': 'description',
216 ... 'field.domainname': 'youbuntu.me',
217 ... 'field.members': 'landscape-developers',
218+ ... 'field.require_virtualized': 'on',
219+ ... 'field.enabled_restricted_families': [],
220 ... 'field.actions.save': 'Save',
221 ... }
222 >>> view = create_initialized_view(distributionset, '+add', form=form)
223
224=== modified file 'lib/lp/registry/browser/tests/test_distribution_views.py'
225--- lib/lp/registry/browser/tests/test_distribution_views.py 2011-03-16 17:14:26 +0000
226+++ lib/lp/registry/browser/tests/test_distribution_views.py 2011-09-07 09:26:38 +0000
227@@ -12,6 +12,7 @@
228 from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfigSet
229 from lp.registry.browser.distribution import DistributionPublisherConfigView
230 from lp.registry.interfaces.distribution import IDistributionSet
231+from lp.soyuz.interfaces.processor import IProcessorFamilySet
232 from lp.testing import (
233 login_celebrity,
234 TestCaseWithFactory,
235@@ -83,7 +84,7 @@
236
237 def test_change_existing_config(self):
238 # Test POSTing to change existing config.
239- pubconf = self.factory.makePublisherConfig(
240+ self.factory.makePublisherConfig(
241 distribution=self.distro,
242 root_dir=u"random",
243 base_url=u"blah",
244@@ -102,13 +103,13 @@
245 self.owner = self.factory.makePerson()
246 self.registrant = self.factory.makePerson()
247 self.simple_user = self.factory.makePerson()
248+ self.admin = login_celebrity('admin')
249+ self.distributionset = getUtility(IDistributionSet)
250+ proc_family_set = getUtility(IProcessorFamilySet)
251+ self.restricted_families = proc_family_set.getRestricted()
252
253- def test_registrant_set_by_creation(self):
254- # The registrant field should be set to the Person creating
255- # the distribution.
256- admin = login_celebrity('admin')
257- distributionset = getUtility(IDistributionSet)
258- creation_form = {
259+ def getDefaultAddDict(self):
260+ return {
261 'field.name': 'newbuntu',
262 'field.displayname': 'newbuntu',
263 'field.title': 'newbuntu',
264@@ -116,14 +117,191 @@
265 'field.description': 'newbuntu',
266 'field.domainname': 'newbuntu',
267 'field.members': self.simple_user.name,
268+ 'field.require_virtualized': '',
269+ 'field.enabled_restricted_families': [family.name
270+ for family in self.restricted_families],
271 'field.actions.save': 'Save',
272 }
273- view = create_initialized_view(
274- distributionset, '+add', principal=admin,
275- method='POST', form=creation_form)
276- distribution = distributionset.getByName('newbuntu')
277- self.assertEqual(distribution.owner, admin)
278- self.assertEqual(distribution.registrant, admin)
279+
280+ def test_registrant_set_by_creation(self):
281+ # The registrant field should be set to the Person creating
282+ # the distribution.
283+ creation_form = self.getDefaultAddDict()
284+ create_initialized_view(
285+ self.distributionset, '+add', principal=self.admin,
286+ method='POST', form=creation_form)
287+ distribution = self.distributionset.getByName('newbuntu')
288+ self.assertEqual(distribution.owner, self.admin)
289+ self.assertEqual(distribution.registrant, self.admin)
290+
291+ def test_add_distro_default_value_require_virtualized(self):
292+ view = create_initialized_view(
293+ self.distributionset, '+add', principal=self.admin,
294+ method='GET')
295+
296+ widget = view.widgets['require_virtualized']
297+ self.assertEqual(False, widget._getCurrentValue())
298+
299+ def test_add_distro_init_value_enabled_restricted_families(self):
300+ view = create_initialized_view(
301+ self.distributionset, '+add', principal=self.admin,
302+ method='GET')
303+
304+ widget = view.widgets['enabled_restricted_families']
305+ self.assertContentEqual(
306+ self.restricted_families, widget._getCurrentValue())
307+ self.assertContentEqual(
308+ self.restricted_families,
309+ [item.value for item in widget.vocabulary])
310+
311+ def test_add_distro_require_virtualized(self):
312+ creation_form = self.getDefaultAddDict()
313+ creation_form['field.require_virtualized'] = ''
314+ create_initialized_view(
315+ self.distributionset, '+add', principal=self.admin,
316+ method='POST', form=creation_form)
317+
318+ distribution = self.distributionset.getByName('newbuntu')
319+ self.assertEqual(
320+ False,
321+ distribution.main_archive.require_virtualized)
322+
323+ def test_add_distro_enabled_restricted_families(self):
324+ creation_form = self.getDefaultAddDict()
325+ creation_form['field.enabled_restricted_families'] = []
326+ creation_form['field.require_virtualized'] = 'on'
327+ create_initialized_view(
328+ self.distributionset, '+add', principal=self.admin,
329+ method='POST', form=creation_form)
330+
331+ distribution = self.distributionset.getByName('newbuntu')
332+ self.assertEqual(
333+ True,
334+ distribution.main_archive.require_virtualized)
335+ self.assertContentEqual(
336+ [],
337+ distribution.main_archive.enabled_restricted_families)
338+
339+ def test_add_distro_enabled_restricted_families_error(self):
340+ # If require_virtualized is False, enabled_restricted_families
341+ # cannot be changed.
342+ creation_form = self.getDefaultAddDict()
343+ creation_form['field.enabled_restricted_families'] = []
344+ creation_form['field.require_virtualized'] = ''
345+ view = create_initialized_view(
346+ self.distributionset, '+add', principal=self.admin,
347+ method='POST', form=creation_form)
348+
349+ error_msg = (
350+ u"This distribution's main archive can not be restricted to "
351+ "certain architectures unless the archive is also set to build "
352+ "on virtualized builders.")
353+ self.assertEqual(
354+ error_msg,
355+ view.widget_errors.get('enabled_restricted_families'))
356+ self.assertEqual(
357+ error_msg,
358+ view.widget_errors.get('require_virtualized'))
359+
360+
361+class TestDistroEditView(TestCaseWithFactory):
362+ """Test the +edit page for a distribution."""
363+
364+ layer = DatabaseFunctionalLayer
365+
366+ def setUp(self):
367+ super(TestDistroEditView, self).setUp()
368+ self.admin = login_celebrity('admin')
369+ self.distribution = self.factory.makeDistribution()
370+ proc_family_set = getUtility(IProcessorFamilySet)
371+ self.restricted_families = proc_family_set.getRestricted()
372+
373+ def test_edit_distro_init_value_require_virtualized(self):
374+ view = create_initialized_view(
375+ self.distribution, '+edit', principal=self.admin,
376+ method='GET')
377+
378+ widget = view.widgets['require_virtualized']
379+ self.assertEqual(
380+ self.distribution.main_archive.require_virtualized,
381+ widget._getCurrentValue())
382+
383+ def test_edit_distro_init_value_enabled_restricted_families(self):
384+ self.distribution.main_archive.require_virtualized = False
385+ view = create_initialized_view(
386+ self.distribution, '+edit', principal=self.admin,
387+ method='GET')
388+
389+ widget = view.widgets['enabled_restricted_families']
390+ self.assertContentEqual(
391+ self.restricted_families, widget._getCurrentValue())
392+ self.assertContentEqual(
393+ self.restricted_families,
394+ [item.value for item in widget.vocabulary])
395+
396+ def getDefaultEditDict(self):
397+ return {
398+ 'field.displayname': 'newbuntu',
399+ 'field.title': 'newbuntu',
400+ 'field.summary': 'newbuntu',
401+ 'field.description': 'newbuntu',
402+ 'field.require_virtualized.used': u'',
403+ 'field.enabled_restricted_families': [family.name
404+ for family in self.restricted_families],
405+ 'field.actions.change': 'Change',
406+ }
407+
408+ def test_change_require_virtualized(self):
409+ edit_form = self.getDefaultEditDict()
410+ edit_form['field.require_virtualized'] = 'on'
411+
412+ self.distribution.main_archive.require_virtualized = False
413+ create_initialized_view(
414+ self.distribution, '+edit', principal=self.admin,
415+ method='POST', form=edit_form)
416+ self.assertEqual(
417+ True,
418+ self.distribution.main_archive.require_virtualized)
419+
420+ def test_change_enabled_restricted_families(self):
421+ # If require_virtualized is True, enabled_restricted_families
422+ # can be changed.
423+ edit_form = self.getDefaultEditDict()
424+ edit_form['field.require_virtualized'] = 'on'
425+ edit_form['field.enabled_restricted_families'] = []
426+
427+ self.distribution.main_archive.require_virtualized = False
428+ self.assertContentEqual(
429+ self.restricted_families,
430+ self.distribution.main_archive.enabled_restricted_families)
431+ create_initialized_view(
432+ self.distribution, '+edit', principal=self.admin,
433+ method='POST', form=edit_form)
434+
435+ self.assertContentEqual(
436+ [],
437+ self.distribution.main_archive.enabled_restricted_families)
438+
439+ def test_cannot_change_enabled_restricted_families(self):
440+ # If require_virtualized is False, enabled_restricted_families
441+ # cannot be changed.
442+ edit_form = self.getDefaultEditDict()
443+ edit_form['field.require_virtualized'] = ''
444+ edit_form['field.enabled_restricted_families'] = []
445+
446+ view = create_initialized_view(
447+ self.distribution, '+edit', principal=self.admin,
448+ method='POST', form=edit_form)
449+ error_msg = (
450+ u"This distribution's main archive can not be restricted to "
451+ "certain architectures unless the archive is also set to build "
452+ "on virtualized builders.")
453+ self.assertEqual(
454+ error_msg,
455+ view.widget_errors.get('enabled_restricted_families'))
456+ self.assertEqual(
457+ error_msg,
458+ view.widget_errors.get('require_virtualized'))
459
460
461 class TestDistroReassignView(TestCaseWithFactory):
462@@ -147,7 +325,7 @@
463 'field.existing': 'existing',
464 'field.actions.change': 'Change',
465 }
466- view = create_initialized_view(
467+ create_initialized_view(
468 distribution, '+reassign', principal=admin,
469 method='POST', form=reassign_form)
470 self.assertEqual(distribution.owner, self.simple_user)
471
472=== modified file 'lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt'
473--- lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt 2011-03-08 17:09:15 +0000
474+++ lib/lp/registry/stories/distribution/xx-distribution-launchpad-usage.txt 2011-09-07 09:26:38 +0000
475@@ -39,6 +39,11 @@
476 LAUNCHPAD
477 >>> print registrant.getControl(name='field.answers_usage').value[0]
478 LAUNCHPAD
479+ >>> print registrant.getControl(name='field.require_virtualized').value
480+ False
481+ >>> print registrant.getControl(
482+ ... name='field.enabled_restricted_families').value
483+ ['arm']
484
485 >>> registrant.getControl(name='field.official_rosetta').value = False
486 >>> registrant.getControl('Change', index=3).click()
487
488=== modified file 'lib/lp/soyuz/browser/archive.py'
489--- lib/lp/soyuz/browser/archive.py 2011-08-17 13:02:26 +0000
490+++ lib/lp/soyuz/browser/archive.py 2011-09-07 09:26:38 +0000
491@@ -22,6 +22,7 @@
492 'ArchivePackagesView',
493 'ArchiveView',
494 'ArchiveViewBase',
495+ 'EnableRestrictedFamiliesMixin',
496 'make_archive_vocabulary',
497 'PackageCopyingMixin',
498 'traverse_named_ppa',
499@@ -2033,7 +2034,39 @@
500 return 'Edit %s' % self.context.displayname
501
502
503-class ArchiveAdminView(BaseArchiveEditView):
504+class EnableRestrictedFamiliesMixin:
505+ """A mixin that provides enabled_restricted_families field support"""
506+
507+ def createEnabledRestrictedFamilies(self, description=None):
508+ """Creates the 'enabled_restricted_families' field.
509+
510+ """
511+ terms = []
512+ for family in getUtility(IProcessorFamilySet).getRestricted():
513+ terms.append(SimpleTerm(
514+ family, token=family.name, title=family.title))
515+ old_field = IArchive['enabled_restricted_families']
516+ return form.Fields(
517+ List(__name__=old_field.__name__,
518+ title=old_field.title,
519+ value_type=Choice(vocabulary=SimpleVocabulary(terms)),
520+ required=False,
521+ description=old_field.description if description is None
522+ else description),
523+ render_context=self.render_context)
524+
525+ def validate_enabled_restricted_families(self, data, error_msg):
526+ enabled_restricted_families = data['enabled_restricted_families']
527+ require_virtualized = data.get('require_virtualized', False)
528+ proc_family_set = getUtility(IProcessorFamilySet)
529+ if (not require_virtualized and
530+ set(enabled_restricted_families) !=
531+ set(proc_family_set.getRestricted())):
532+ self.setFieldError('enabled_restricted_families', error_msg)
533+ self.setFieldError('require_virtualized', error_msg)
534+
535+
536+class ArchiveAdminView(BaseArchiveEditView, EnableRestrictedFamiliesMixin):
537
538 field_names = ['enabled', 'private', 'commercial', 'require_virtualized',
539 'build_debug_symbols', 'buildd_secret', 'authorized_size',
540@@ -2097,6 +2130,16 @@
541 'commercial',
542 'Can only set commericial for private archives.')
543
544+ enabled_restricted_families = data.get('enabled_restricted_families')
545+ if (enabled_restricted_families and
546+ not self.context.canSetEnabledRestrictedFamilies(
547+ enabled_restricted_families)):
548+ self.setFieldError(
549+ 'enabled_restricted_families',
550+ 'Main archives can not be restricted to certain '
551+ 'architectures unless they are set to build on '
552+ 'virtualized builders.')
553+
554 @property
555 def owner_is_private_team(self):
556 """Is the owner a private team?
557@@ -2106,6 +2149,13 @@
558 """
559 return self.context.owner.visibility == PersonVisibility.PRIVATE
560
561+ @property
562+ def initial_values(self):
563+ return {
564+ 'enabled_restricted_families':
565+ self.context.enabled_restricted_families,
566+ }
567+
568 def setUpFields(self):
569 """Override `LaunchpadEditFormView`.
570
571@@ -2114,23 +2164,6 @@
572 super(ArchiveAdminView, self).setUpFields()
573 self.form_fields += self.createEnabledRestrictedFamilies()
574
575- def createEnabledRestrictedFamilies(self):
576- """Creates the 'enabled_restricted_families' field.
577-
578- """
579- terms = []
580- for family in getUtility(IProcessorFamilySet).getRestricted():
581- terms.append(SimpleTerm(
582- family, token=family.name, title=family.title))
583- old_field = IArchive['enabled_restricted_families']
584- return form.Fields(
585- List(__name__=old_field.__name__,
586- title=old_field.title,
587- value_type=Choice(vocabulary=SimpleVocabulary(terms)),
588- required=False,
589- description=old_field.description),
590- render_context=self.render_context)
591-
592
593 class ArchiveDeleteView(LaunchpadFormView):
594 """View class for deleting `IArchive`s"""
595
596=== modified file 'lib/lp/soyuz/model/archive.py'
597--- lib/lp/soyuz/model/archive.py 2011-08-25 11:29:29 +0000
598+++ lib/lp/soyuz/model/archive.py 2011-09-07 09:26:38 +0000
599@@ -1910,8 +1910,8 @@
600 """Retrieve the restricted architecture families this archive can
601 build on."""
602 # Main archives are always allowed to build on restricted
603- # architectures.
604- if self.is_main:
605+ # architectures if require_virtualized is False.
606+ if self.is_main and not self.require_virtualized:
607 return getUtility(IProcessorFamilySet).getRestricted()
608 archive_arch_set = getUtility(IArchiveArchSet)
609 restricted_families = archive_arch_set.getRestrictedFamilies(self)
610@@ -1921,13 +1921,16 @@
611 def _setEnabledRestrictedFamilies(self, value):
612 """Set the restricted architecture families this archive can
613 build on."""
614- # Main archives are always allowed to build on restricted
615- # architectures.
616- if self.is_main:
617+ # Main archives are not allowed to build on restricted
618+ # architectures unless they are set to build on virtualized
619+ # builders.
620+ if (self.is_main and not self.require_virtualized):
621 proc_family_set = getUtility(IProcessorFamilySet)
622 if set(value) != set(proc_family_set.getRestricted()):
623- raise CannotRestrictArchitectures("Main archives can not "
624- "be restricted to certain architectures")
625+ raise CannotRestrictArchitectures(
626+ "Main archives can not be restricted to certain "
627+ "architectures unless they are set to build on "
628+ "virtualized builders")
629 archive_arch_set = getUtility(IArchiveArchSet)
630 restricted_families = archive_arch_set.getRestrictedFamilies(self)
631 for (family, archive_arch) in restricted_families:
632
633=== modified file 'lib/lp/soyuz/tests/test_archive.py'
634--- lib/lp/soyuz/tests/test_archive.py 2011-08-29 19:28:47 +0000
635+++ lib/lp/soyuz/tests/test_archive.py 2011-09-07 09:26:38 +0000
636@@ -981,14 +981,17 @@
637
638 def test_main_archive_can_use_restricted(self):
639 # Main archives for distributions can always use restricted
640- # architectures.
641+ # architectures if they are not using virtual builders.
642 distro = self.factory.makeDistribution()
643+ distro.main_archive.require_virtualized = False
644 self.assertContentEqual([self.arm],
645 distro.main_archive.enabled_restricted_families)
646
647- def test_main_archive_can_not_be_restricted(self):
648- # A main archive can not be restricted to certain architectures.
649+ def test_main_archive_can_not_be_restricted_not_virtualized(self):
650+ # A main archive can not be restricted to certain architectures
651+ # (unless it's set to build on virtualized builders).
652 distro = self.factory.makeDistribution()
653+ distro.main_archive.require_virtualized = False
654 # Restricting to all restricted architectures is fine
655 distro.main_archive.enabled_restricted_families = [self.arm]
656
657@@ -997,6 +1000,16 @@
658
659 self.assertRaises(CannotRestrictArchitectures, restrict)
660
661+ def test_main_virtualized_archive_can_be_restricted(self):
662+ # A main archive can be restricted to certain architectures
663+ # if it's set to build on virtualized builders.
664+ distro = self.factory.makeDistribution()
665+ distro.main_archive.require_virtualized = True
666+
667+ # Restricting to architectures is fine.
668+ distro.main_archive.enabled_restricted_families = [self.arm]
669+ distro.main_archive.enabled_restricted_families = []
670+
671 def test_default(self):
672 """By default, ARM builds are not allowed as ARM is restricted."""
673 self.assertEquals(0,
674
675=== modified file 'lib/lp/translations/browser/distribution.py'
676--- lib/lp/translations/browser/distribution.py 2010-12-30 12:50:16 +0000
677+++ lib/lp/translations/browser/distribution.py 2011-09-07 09:26:38 +0000
678@@ -146,4 +146,5 @@
679
680 @action('Change', name='change')
681 def edit(self, action, data):
682+ self.change_archive_fields(data)
683 self.updateContextFromData(data)