~nuage-canonical/charms/trusty/nuage-vsd/trunk

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/fetch/archiveurl.py

  • Committer: Subbarayudu Mukkamala
  • Date: 2014-10-19 23:13:25 UTC
  • Revision ID: smukkamala@nuagenetworks.net-20141019231325-bu5f2dtlb7noru38
create nuage-vsd charm

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import os
 
2
import urllib2
 
3
from urllib import urlretrieve
 
4
import urlparse
 
5
import hashlib
 
6
 
 
7
from charmhelpers.fetch import (
 
8
    BaseFetchHandler,
 
9
    UnhandledSource
 
10
)
 
11
from charmhelpers.payload.archive import (
 
12
    get_archive_handler,
 
13
    extract,
 
14
)
 
15
from charmhelpers.core.host import mkdir, check_hash
 
16
 
 
17
 
 
18
class ArchiveUrlFetchHandler(BaseFetchHandler):
 
19
    """
 
20
    Handler to download archive files from arbitrary URLs.
 
21
 
 
22
    Can fetch from http, https, ftp, and file URLs.
 
23
 
 
24
    Can install either tarballs (.tar, .tgz, .tbz2, etc) or zip files.
 
25
 
 
26
    Installs the contents of the archive in $CHARM_DIR/fetched/.
 
27
    """
 
28
    def can_handle(self, source):
 
29
        url_parts = self.parse_url(source)
 
30
        if url_parts.scheme not in ('http', 'https', 'ftp', 'file'):
 
31
            return "Wrong source type"
 
32
        if get_archive_handler(self.base_url(source)):
 
33
            return True
 
34
        return False
 
35
 
 
36
    def download(self, source, dest):
 
37
        """
 
38
        Download an archive file.
 
39
 
 
40
        :param str source: URL pointing to an archive file.
 
41
        :param str dest: Local path location to download archive file to.
 
42
        """
 
43
        # propogate all exceptions
 
44
        # URLError, OSError, etc
 
45
        proto, netloc, path, params, query, fragment = urlparse.urlparse(source)
 
46
        if proto in ('http', 'https'):
 
47
            auth, barehost = urllib2.splituser(netloc)
 
48
            if auth is not None:
 
49
                source = urlparse.urlunparse((proto, barehost, path, params, query, fragment))
 
50
                username, password = urllib2.splitpasswd(auth)
 
51
                passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
 
52
                # Realm is set to None in add_password to force the username and password
 
53
                # to be used whatever the realm
 
54
                passman.add_password(None, source, username, password)
 
55
                authhandler = urllib2.HTTPBasicAuthHandler(passman)
 
56
                opener = urllib2.build_opener(authhandler)
 
57
                urllib2.install_opener(opener)
 
58
        response = urllib2.urlopen(source)
 
59
        try:
 
60
            with open(dest, 'w') as dest_file:
 
61
                dest_file.write(response.read())
 
62
        except Exception as e:
 
63
            if os.path.isfile(dest):
 
64
                os.unlink(dest)
 
65
            raise e
 
66
 
 
67
    # Mandatory file validation via Sha1 or MD5 hashing.
 
68
    def download_and_validate(self, url, hashsum, validate="sha1"):
 
69
        tempfile, headers = urlretrieve(url)
 
70
        check_hash(tempfile, hashsum, validate)
 
71
        return tempfile
 
72
 
 
73
    def install(self, source, dest=None, checksum=None, hash_type='sha1'):
 
74
        """
 
75
        Download and install an archive file, with optional checksum validation.
 
76
 
 
77
        The checksum can also be given on the `source` URL's fragment.
 
78
        For example::
 
79
 
 
80
            handler.install('http://example.com/file.tgz#sha1=deadbeef')
 
81
 
 
82
        :param str source: URL pointing to an archive file.
 
83
        :param str dest: Local destination path to install to. If not given,
 
84
            installs to `$CHARM_DIR/archives/archive_file_name`.
 
85
        :param str checksum: If given, validate the archive file after download.
 
86
        :param str hash_type: Algorithm used to generate `checksum`.
 
87
            Can be any hash alrgorithm supported by :mod:`hashlib`,
 
88
            such as md5, sha1, sha256, sha512, etc.
 
89
 
 
90
        """
 
91
        url_parts = self.parse_url(source)
 
92
        dest_dir = os.path.join(os.environ.get('CHARM_DIR'), 'fetched')
 
93
        if not os.path.exists(dest_dir):
 
94
            mkdir(dest_dir, perms=0755)
 
95
        dld_file = os.path.join(dest_dir, os.path.basename(url_parts.path))
 
96
        try:
 
97
            self.download(source, dld_file)
 
98
        except urllib2.URLError as e:
 
99
            raise UnhandledSource(e.reason)
 
100
        except OSError as e:
 
101
            raise UnhandledSource(e.strerror)
 
102
        options = urlparse.parse_qs(url_parts.fragment)
 
103
        for key, value in options.items():
 
104
            if key in hashlib.algorithms:
 
105
                check_hash(dld_file, value, key)
 
106
        if checksum:
 
107
            check_hash(dld_file, checksum, hash_type)
 
108
        return extract(dld_file, dest)