Merge lp:~jpds/launchpad/fix_515388 into lp:launchpad

Proposed by Jonathan Davies
Status: Merged
Approved by: Graham Binns
Approved revision: not available
Merged at revision: 10252
Proposed branch: lp:~jpds/launchpad/fix_515388
Merge into: lp:launchpad
Diff against target: 354 lines (+164/-36)
5 files modified
lib/canonical/launchpad/interfaces/_schema_circular_imports.py (+5/-0)
lib/lp/registry/interfaces/distribution.py (+16/-7)
lib/lp/registry/interfaces/distributionmirror.py (+41/-29)
lib/lp/registry/stories/webservice/xx-distribution-mirror.txt (+75/-0)
lib/lp/registry/stories/webservice/xx-distribution.txt (+27/-0)
To merge this branch: bzr merge lp:~jpds/launchpad/fix_515388
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Review via email: mp+18413@code.launchpad.net

Commit message

Added DistributionMirrors to the Launchpad API.

To post a comment you must log in.
Revision history for this message
Jonathan Davies (jpds) wrote :

= Summary =

Distribution mirrors should be exposed via the Launchpad API. This branch makes the necessary changes to make this a reality.

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/canonical/launchpad/interfaces/_schema_circular_imports.py'
2--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-01-15 01:59:08 +0000
3+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-02-01 23:20:32 +0000
4@@ -44,6 +44,7 @@
5 from lp.code.interfaces.diff import IPreviewDiff
6 from lp.code.interfaces.hasbranches import IHasBranches, IHasMergeProposals
7 from lp.registry.interfaces.distribution import IDistribution
8+from lp.registry.interfaces.distributionmirror import IDistributionMirror
9 from lp.registry.interfaces.distributionsourcepackage import (
10 IDistributionSourcePackage)
11 from lp.registry.interfaces.distroseries import IDistroSeries
12@@ -261,6 +262,10 @@
13 IDistribution['all_distro_archives'].value_type.schema = IArchive
14
15
16+# IDistributionMirror
17+IDistributionMirror['distribution'].schema = IDistribution
18+
19+
20 # IDistroSeries
21 patch_entry_return_type(
22 IDistroSeries, 'getDistroArchSeries', IDistroArchSeries)
23
24=== modified file 'lib/lp/registry/interfaces/distribution.py'
25--- lib/lp/registry/interfaces/distribution.py 2009-12-09 14:55:02 +0000
26+++ lib/lp/registry/interfaces/distribution.py 2010-02-01 23:20:32 +0000
27@@ -20,7 +20,7 @@
28 'NoSuchDistribution',
29 ]
30
31-from zope.schema import Bool, Choice, Datetime, List, Text, TextLine
32+from zope.schema import Bool, Choice, Datetime, List, Object, Text, TextLine
33 from zope.interface import Attribute, Interface
34
35 from lazr.restful.fields import CollectionField, Reference
36@@ -39,6 +39,7 @@
37 IStructuralSubscriptionTarget)
38 from lp.app.interfaces.headings import IRootContext
39 from lp.registry.interfaces.announcement import IMakesAnnouncements
40+from lp.registry.interfaces.distributionmirror import IDistributionMirror
41 from lp.bugs.interfaces.bugtarget import (
42 IBugTarget, IOfficialBugTagTargetPublic, IOfficialBugTagTargetRestricted)
43 from lp.soyuz.interfaces.buildrecords import IHasBuildRecords
44@@ -184,18 +185,22 @@
45 title=_("Members"),
46 description=_("The distro's members team."), required=True,
47 vocabulary='ValidPersonOrTeam')
48- mirror_admin = PublicPersonChoice(
49+ mirror_admin = exported(PublicPersonChoice(
50 title=_("Mirror Administrator"),
51 description=_("The person or team that has the rights to review and "
52 "mark this distribution's mirrors as official."),
53- required=True, vocabulary='ValidPersonOrTeam')
54+ required=True, vocabulary='ValidPersonOrTeam'))
55 lucilleconfig = TextLine(
56 title=_("Lucille Config"),
57 description=_("The Lucille Config."), required=False)
58- archive_mirrors = Attribute(
59- "All enabled and official ARCHIVE mirrors of this Distribution.")
60- cdimage_mirrors = Attribute(
61- "All enabled and official RELEASE mirrors of this Distribution.")
62+ archive_mirrors = exported(CollectionField(
63+ description=_("All enabled and official ARCHIVE mirrors of this "
64+ "Distribution."),
65+ readonly=True, value_type=Object(schema=IDistributionMirror)))
66+ cdimage_mirrors = exported(CollectionField(
67+ description=_("All enabled and official RELEASE mirrors of this "
68+ "Distribution."),
69+ readonly=True, value_type=Object(schema=IDistributionMirror)))
70 disabled_mirrors = Attribute(
71 "All disabled and official mirrors of this Distribution.")
72 unofficial_mirrors = Attribute(
73@@ -304,6 +309,10 @@
74 `IDistroSeries.version`.
75 """
76
77+ @operation_parameters(
78+ name=TextLine(title=_("Name"), required=True))
79+ @operation_returns_entry(IDistributionMirror)
80+ @export_read_operation()
81 def getMirrorByName(name):
82 """Return the mirror with the given name for this distribution or None
83 if it's not found.
84
85=== modified file 'lib/lp/registry/interfaces/distributionmirror.py'
86--- lib/lp/registry/interfaces/distributionmirror.py 2009-10-26 18:40:04 +0000
87+++ lib/lp/registry/interfaces/distributionmirror.py 2010-02-01 23:20:32 +0000
88@@ -27,6 +27,9 @@
89 from zope.interface.interface import invariant
90 from zope.component import getUtility
91 from lazr.enum import DBEnumeratedType, DBItem
92+from lazr.restful.declarations import (
93+ export_as_webservice_entry, export_read_operation, exported)
94+from lazr.restful.fields import Reference
95
96 from canonical.launchpad import _
97 from canonical.launchpad.fields import (
98@@ -280,61 +283,68 @@
99
100 class IDistributionMirror(Interface):
101 """A mirror of a given distribution."""
102+ export_as_webservice_entry()
103
104 id = Int(title=_('The unique id'), required=True, readonly=True)
105- owner = PublicPersonChoice(
106+ owner = exported(PublicPersonChoice(
107 title=_('Owner'), required=False, readonly=True,
108- vocabulary='ValidOwner')
109+ vocabulary='ValidOwner'))
110 reviewer = PublicPersonChoice(
111 title=_('Reviewer'), required=False, readonly=False,
112 vocabulary='ValidPersonOrTeam')
113- distribution = Attribute(_("The distribution that is mirrored"))
114- name = DistributionMirrorNameField(
115+ distribution = exported(
116+ Reference(
117+ Interface,
118+ # Really IDistribution, circular import fixed in
119+ # _schema_circular_imports.
120+ title=_("Distribution"), required=True,
121+ description=_("The distribution that is mirrored")))
122+ name = exported(DistributionMirrorNameField(
123 title=_('Name'), required=True, readonly=False,
124 description=_('A short and unique name for this mirror.'),
125- constraint=name_validator)
126- displayname = TextLine(
127+ constraint=name_validator))
128+ displayname = exported(TextLine(
129 title=_('Organisation'), required=False, readonly=False,
130- description=_('The name of the organization hosting this mirror.'))
131- description = TextLine(
132- title=_('Description'), required=False, readonly=False)
133- http_base_url = DistroMirrorHTTPURIField(
134+ description=_('The name of the organization hosting this mirror.')))
135+ description = exported(TextLine(
136+ title=_('Description'), required=False, readonly=False))
137+ http_base_url = exported(DistroMirrorHTTPURIField(
138 title=_('HTTP URL'), required=False, readonly=False,
139 allowed_schemes=['http'], allow_userinfo=False,
140 allow_query=False, allow_fragment=False, trailing_slash=True,
141- description=_('e.g.: http://archive.ubuntu.com/ubuntu/'))
142- ftp_base_url = DistroMirrorFTPURIField(
143+ description=_('e.g.: http://archive.ubuntu.com/ubuntu/')))
144+ ftp_base_url = exported(DistroMirrorFTPURIField(
145 title=_('FTP URL'), required=False, readonly=False,
146 allowed_schemes=['ftp'], allow_userinfo=False,
147 allow_query=False, allow_fragment=False, trailing_slash=True,
148- description=_('e.g.: ftp://archive.ubuntu.com/ubuntu/'))
149- rsync_base_url = DistroMirrorRsyncURIField(
150+ description=_('e.g.: ftp://archive.ubuntu.com/ubuntu/')))
151+ rsync_base_url = exported(DistroMirrorRsyncURIField(
152 title=_('Rsync URL'), required=False, readonly=False,
153 allowed_schemes=['rsync'], allow_userinfo=False,
154 allow_query=False, allow_fragment=False, trailing_slash=True,
155- description=_('e.g.: rsync://archive.ubuntu.com/ubuntu/'))
156- enabled = Bool(
157+ description=_('e.g.: rsync://archive.ubuntu.com/ubuntu/')))
158+ enabled = exported(Bool(
159 title=_('This mirror was probed successfully.'),
160- required=False, readonly=False, default=False)
161- speed = Choice(
162+ required=False, readonly=False, default=False))
163+ speed = exported(Choice(
164 title=_('Link Speed'), required=True, readonly=False,
165- vocabulary=MirrorSpeed)
166+ vocabulary=MirrorSpeed))
167 country = Choice(
168 title=_('Location'), required=True, readonly=False,
169 vocabulary='CountryName')
170- content = Choice(
171+ content = exported(Choice(
172 title=_('Content'), required=True, readonly=False,
173 description=_(
174 'Choose "CD Image" if this mirror contains CD images of '
175 'this distribution. Choose "Archive" if this is a '
176 'mirror of packages for this distribution.'),
177- vocabulary=MirrorContent)
178- official_candidate = Bool(
179+ vocabulary=MirrorContent))
180+ official_candidate = exported(Bool(
181 title=_('Apply to be an official mirror of this distribution'),
182- required=False, readonly=False, default=True)
183- status = Choice(
184+ required=False, readonly=False, default=True))
185+ status = exported(Choice(
186 title=_('Status'), required=True, readonly=False,
187- vocabulary=MirrorStatus)
188+ vocabulary=MirrorStatus))
189
190 title = Attribute('The title of this mirror')
191 cdimage_series = Attribute(
192@@ -345,11 +355,11 @@
193 last_probe_record = Attribute(
194 'The last MirrorProbeRecord for this mirror.')
195 all_probe_records = Attribute('All MirrorProbeRecords for this mirror.')
196- has_ftp_or_rsync_base_url = Bool(
197- title=_('Does this mirror have a ftp or rsync base URL?'))
198+ has_ftp_or_rsync_base_url = exported(Bool(
199+ title=_('Does this mirror have a ftp or rsync base URL?')))
200 base_url = Attribute('The HTTP or FTP base URL of this mirror')
201- date_created = Datetime(
202- title=_('Date Created'), required=True, readonly=True)
203+ date_created = exported(Datetime(
204+ title=_('Date Created'), required=True, readonly=True))
205 date_reviewed = Datetime(
206 title=_('Date reviewed'), required=False, readonly=False)
207 whiteboard = Whiteboard(
208@@ -380,6 +390,7 @@
209 each distro_arch_series of this distribution mirror.
210 """
211
212+ @export_read_operation()
213 def getOverallFreshness():
214 """Return this mirror's overall freshness.
215
216@@ -392,6 +403,7 @@
217 contain one or more ISO images.
218 """
219
220+ @export_read_operation()
221 def isOfficial():
222 """Return True if this is an official mirror."""
223
224
225=== added file 'lib/lp/registry/stories/webservice/xx-distribution-mirror.txt'
226--- lib/lp/registry/stories/webservice/xx-distribution-mirror.txt 1970-01-01 00:00:00 +0000
227+++ lib/lp/registry/stories/webservice/xx-distribution-mirror.txt 2010-02-01 23:20:32 +0000
228@@ -0,0 +1,75 @@
229+= Distribution Mirrors =
230+
231+For every mirror of distribution we publish most of its attributes. For archive
232+mirrors:
233+
234+ >>> from lazr.restful.testing.webservice import pprint_entry
235+ >>> distros = webservice.get("/distros").jsonBody()
236+ >>> distro = distros['entries'][0]
237+ >>> ubuntu = webservice.get(distro['self_link']).jsonBody()
238+ >>> ubuntu_archive_mirrors = webservice.get(ubuntu['archive_mirrors_collection_link']).jsonBody()
239+ >>> canonical_archive = ubuntu_archive_mirrors['entries'][0]
240+ >>> canonical_archive_json = webservice.get(canonical_archive['self_link']).jsonBody()
241+ >>> pprint_entry(canonical_archive_json)
242+ content: u'Archive'
243+ date_created: u'2006-10-16T18:31:43.434567+00:00'
244+ description: None
245+ displayname: None
246+ distribution_link: u'http://.../ubuntu'
247+ enabled: True
248+ ftp_base_url: None
249+ has_ftp_or_rsync_base_url: False
250+ http_base_url: u'http://archive.ubuntu.com/ubuntu/'
251+ name: u'canonical-archive'
252+ official_candidate: True
253+ owner_link: u'http://.../~mark'
254+ resource_type_link: u'http://.../#distribution_mirror'
255+ rsync_base_url: None
256+ self_link: u'http://.../ubuntu/+mirror/canonical-archive'
257+ speed: u'100 Mbps'
258+ status: u'Official'
259+
260+And CD image mirrors:
261+
262+ >>> ubuntu_cd_mirrors = webservice.get(ubuntu['cdimage_mirrors_collection_link']).jsonBody()
263+ >>> canonical_releases = ubuntu_cd_mirrors['entries'][0]
264+ >>> canonical_releases_json = webservice.get(canonical_releases['self_link']).jsonBody()
265+ >>> pprint_entry(canonical_releases_json)
266+ content: u'CD Image'
267+ date_created: u'2006-10-16T18:31:43.434567+00:00'
268+ description: None
269+ displayname: None
270+ distribution_link: u'http://.../ubuntu'
271+ enabled: True
272+ ftp_base_url: None
273+ has_ftp_or_rsync_base_url: False
274+ http_base_url: u'http://releases.ubuntu.com/'
275+ name: u'canonical-releases'
276+ official_candidate: True
277+ owner_link: u'http://.../~mark'
278+ resource_type_link: u'http://.../#distribution_mirror'
279+ rsync_base_url: None
280+ self_link: u'http://.../ubuntu/+mirror/canonical-releases'
281+ speed: u'100 Mbps'
282+ status: u'Official'
283+
284+= Distribution Mirror Custom Operations =
285+
286+DistributionMirror has some custom operations.
287+
288+"isOfficial" returns a boolean result on whether a mirror is an official mirror
289+or not.
290+
291+ >>> is_official_mirror = webservice.named_get(canonical_releases['self_link'],
292+ ... 'isOfficial').jsonBody()
293+ >>> print is_official_mirror
294+ True
295+
296+"getOverallFreshness" returns the freshness of the mirror determined by the
297+mirror prober from the mirror's last probe.
298+
299+ >>> releases_mirror2 = ubuntu_cd_mirrors['entries'][2]
300+ >>> freshness = webservice.named_get(releases_mirror2['self_link'],
301+ ... 'getOverallFreshness').jsonBody()
302+ >>> print freshness
303+ Up to date
304
305=== modified file 'lib/lp/registry/stories/webservice/xx-distribution.txt'
306--- lib/lp/registry/stories/webservice/xx-distribution.txt 2009-05-08 20:20:40 +0000
307+++ lib/lp/registry/stories/webservice/xx-distribution.txt 2010-02-01 23:20:32 +0000
308@@ -21,8 +21,10 @@
309 active: True
310 active_milestones_collection_link: u'http://.../ubuntu/active_milestones'
311 all_milestones_collection_link: u'http://.../ubuntu/all_milestones'
312+ archive_mirrors_collection_link: u'http://.../ubuntu/archive_mirrors'
313 archives_collection_link: u'http://.../ubuntu/archives'
314 bug_reporting_guidelines: None
315+ cdimage_mirrors_collection_link: u'http://.../ubuntu/cdimage_mirrors'
316 current_series_link: u'http://.../ubuntu/hoary'
317 date_created: u'2006-10-16T18:31:43.415195+00:00'
318 description: u'Ubuntu is a new approach...'
319@@ -33,6 +35,7 @@
320 icon_link: u'http://.../ubuntu/icon'
321 logo_link: u'http://.../ubuntu/logo'
322 main_archive_link: u'http://.../ubuntu/+archive/primary'
323+ mirror_admin_link: u'http://.../~ubuntu-mirror-admins'
324 mugshot_link: u'http://.../ubuntu/mugshot'
325 name: u'ubuntu'
326 official_bug_tags: []
327@@ -112,3 +115,27 @@
328 http://.../ubuntu/+source/alsa-utils
329 http://.../ubuntu/+source/foobar
330 http://.../ubuntu/+source/commercialpackage
331+
332+"getMirrorByName" returns a mirror by its unique name.
333+
334+ >>> canonical_releases = webservice.named_get(
335+ ... ubuntu['self_link'], 'getMirrorByName',
336+ ... name='canonical-releases').jsonBody()
337+ >>> pprint_entry(canonical_releases)
338+ content: u'CD Image'
339+ date_created: u'2006-10-16T18:31:43.434567+00:00'
340+ description: None
341+ displayname: None
342+ distribution_link: u'http://.../ubuntu'
343+ enabled: True
344+ ftp_base_url: None
345+ has_ftp_or_rsync_base_url: False
346+ http_base_url: u'http://releases.ubuntu.com/'
347+ name: u'canonical-releases'
348+ official_candidate: True
349+ owner_link: u'http://.../~mark'
350+ resource_type_link: u'http://.../#distribution_mirror'
351+ rsync_base_url: None
352+ self_link: u'http://.../ubuntu/+mirror/canonical-releases'
353+ speed: u'100 Mbps'
354+ status: u'Official'