~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to scripts/dyson-run.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2005-06-27 17:32:32 UTC
  • mfrom: (unknown (missing))
  • Revision ID: Arch-1:rocketfuel@canonical.com%launchpad--devel--0--patch-1946
dyson product release creator [r=dsilvers]
Patches applied:

 * scott@canonical.com--2005/launchpad--dyson--0--base-0
   tag of rocketfuel@canonical.com/launchpad--devel--0--patch-1898

 * scott@canonical.com--2005/launchpad--dyson--0--patch-1
   add releaseroot field to Product

 * scott@canonical.com--2005/launchpad--dyson--0--patch-2
   add releaseroot product field to interface and sqlobject

 * scott@canonical.com--2005/launchpad--dyson--0--patch-3
   add ProductRelease function to add a ProductReleaseFile link to LibraryFileAlias

 * scott@canonical.com--2005/launchpad--dyson--0--patch-4
   dyson module (contains the non-specific code)

 * scott@canonical.com--2005/launchpad--dyson--0--patch-5
   add dyson script that does the job with config changes to configure it

 * scott@canonical.com--2005/launchpad--dyson--0--patch-6
   typo

 * scott@canonical.com--2005/launchpad--dyson--0--patch-7
   add dyson user to security.cfg

 * scott@canonical.com--2005/launchpad--dyson--0--patch-8
   use lp scripts to do logging options and stuff

 * scott@canonical.com--2005/launchpad--dyson--0--patch-9
   add required comment

 * scott@canonical.com--2005/launchpad--dyson--0--patch-10
   rename patch-17-77-0 to patch-17-29-0

 * scott@canonical.com--2005/launchpad--dyson--0--patch-11
   fix the revision in my patch

 * scott@canonical.com--2005/launchpad--dyson--0--patch-12
   merge and resolve conflicts

 * scott@canonical.com--2005/launchpad--dyson--0--patch-13
   review comments from Kinnison

 * scott@canonical.com--2005/launchpad--dyson--0--patch-14
   review comments

 * scott@canonical.com--2005/launchpad--dyson--0--patch-15
   keep one cache for life and use a save() method rather than __del__()

 * scott@canonical.com--2005/launchpad--dyson--0--patch-16
   bracket-space facism

 * scott@canonical.com--2005/launchpad--dyson--0--patch-17
   fix up the test suite

 * scott@canonical.com--2005/launchpad--dyson--0--patch-18
   comment that the http walker only goes down

 * scott@canonical.com--2005/launchpad--dyson--0--patch-19
   add not-implemented functions in WalkerBase

 * scott@canonical.com--2005/launchpad--dyson--0--patch-20
   ketchup

 * scott@canonical.com--2005/launchpad--dyson--0--patch-21
   add missing register(__name__) line

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
"""Dyson.
 
3
 
 
4
Scan FTP and HTTP sites specified for each ProductSeries in the database
 
5
to identify files and create new ProductRelease records for them.
 
6
"""
 
7
 
 
8
import os
 
9
import mimetypes
 
10
 
 
11
from urllib import urlretrieve
 
12
from urlparse import urlsplit
 
13
from optparse import OptionParser
 
14
 
 
15
from zope.component import getUtility
 
16
 
 
17
from canonical.dyson.hose import Hose
 
18
from canonical.dyson.filter import Cache
 
19
from canonical.launchpad.interfaces import IProductSet, IProductReleaseSet
 
20
from canonical.librarian.interfaces import IFileUploadClient
 
21
from canonical.lp import initZopeless
 
22
from canonical.config import config
 
23
from canonical.launchpad.scripts import (execute_zcml_for_scripts,
 
24
                                         logger, logger_options)
 
25
 
 
26
from hct.util import path
 
27
 
 
28
 
 
29
def main():
 
30
    # Parse command-line arguments
 
31
    parser = OptionParser()
 
32
    logger_options(parser)
 
33
    (options, args) = parser.parse_args()
 
34
 
 
35
    global log
 
36
    log = logger(options, "dyson")
 
37
    ztm = initZopeless(dbuser=config.dyson.dbuser, implicitBegin=False)
 
38
 
 
39
    cache = Cache(config.dyson.cache_path, log_parent=log)
 
40
    try:
 
41
        for product_name, filters in get_filters(ztm):
 
42
            hose = Hose(filters, cache)
 
43
            for series_name, url in hose:
 
44
                if series_name is not None:
 
45
                    new_release(ztm, product_name, series_name, url)
 
46
                else:
 
47
                    log.warning("File in %s found that matched no glob: %s",
 
48
                                product_name, url)
 
49
    finally:
 
50
        cache.save()
 
51
 
 
52
def get_filters(ztm):
 
53
    """Build the list of products and filters.
 
54
 
 
55
    Returns a list of (product_name, filters) for each product in the database,
 
56
    where the filter keys are series names.
 
57
    """
 
58
    todo = []
 
59
 
 
60
    ztm.begin()
 
61
    products = getUtility(IProductSet)
 
62
    for product in products:
 
63
        filters = {}
 
64
 
 
65
        for series in product.serieslist:
 
66
            if series.releasefileglob is None or series.releasefileglob == "":
 
67
                continue
 
68
            else:
 
69
                releasefileglob = series.releasefileglob
 
70
 
 
71
            if series.releaseroot is None or series.releaseroot == "":
 
72
                if product.releaseroot is None or product.releaseroot == "":
 
73
                    continue
 
74
                else:
 
75
                    releaseroot = product.releaseroot
 
76
            else:
 
77
                releaseroot = series.releaseroot
 
78
 
 
79
            filters[series.name] = (releaseroot, releasefileglob)
 
80
 
 
81
        if not len(filters):
 
82
            continue
 
83
 
 
84
        log.info("%s has %d series with information", product.name,
 
85
                 len(filters))
 
86
 
 
87
        todo.append((product.name, filters))
 
88
    ztm.abort()
 
89
 
 
90
    return todo
 
91
 
 
92
def new_release(ztm, product_name, series_name, url):
 
93
    """Create a new ProductRelease.
 
94
 
 
95
    Downloads the file and creates a new ProductRelease associated with
 
96
    the series.
 
97
    """
 
98
    filename = urlsplit(url)[2]
 
99
    slash = filename.rfind("/")
 
100
    if slash != -1:
 
101
        filename = filename[slash + 1:]
 
102
    log.debug("Filename portion is %s", filename)
 
103
 
 
104
    version = path.split_version(path.name(filename))[1]
 
105
    log.debug("Version is %s", version)
 
106
    if version is None:
 
107
        log.error("Unable to parse version from %s", url)
 
108
        return
 
109
 
 
110
    (mimetype, encoding) = mimetypes.guess_type(url)
 
111
    log.debug("Mime Type is %s", mimetype)
 
112
    if mimetype is None:
 
113
        mimetype = "application/octet-stream"
 
114
 
 
115
    log.debug("Downloading %s", url)
 
116
    try:
 
117
        (local, headers) = urlretrieve(url)
 
118
        stat = os.stat(local)
 
119
    except IOError:
 
120
        log.error("Download of %s failed, can't create release")
 
121
        return
 
122
    except OSError:
 
123
        log.error("Unable to stat downloaded file, can't create release")
 
124
        return
 
125
 
 
126
    open_file = open(local, "r")
 
127
    os.unlink(local)
 
128
    try:
 
129
        ztm.begin()
 
130
        try:
 
131
            product = getUtility(IProductSet)[product_name]
 
132
            series = product.getSeries(series_name)
 
133
            log.info("Creating new release %s for %s %s",
 
134
                     version, product.name, series.name)
 
135
 
 
136
            release = getUtility(IProductReleaseSet).\
 
137
                      new(version, series, product.owner)
 
138
            log.debug("Created ProductRelease %d", release.id)
 
139
 
 
140
            alias_id = getUtility(IFileUploadClient).\
 
141
                       addFile(filename, stat.st_size, open_file, mimetype)
 
142
            log.debug("Created LibraryFileAlias %d", alias_id)
 
143
 
 
144
            release.addFileAlias(alias_id)
 
145
            ztm.commit()
 
146
        except:
 
147
            ztm.abort()
 
148
    finally:
 
149
        open_file.close()
 
150
 
 
151
 
 
152
if __name__ == "__main__":
 
153
    execute_zcml_for_scripts()
 
154
 
 
155
    main()