Project

General

Profile

Download (8.43 KB) Statistics
| Branch: | Tag: | Revision:

root / wcsinst / wcsinstd / deploy.py @ 48cf5b37

1
import cPickle
2
import os
3
import zipfile
4
import subprocess
5
from urlparse import urlparse
6

    
7
from cStringIO import StringIO
8
import xml.etree.ElementTree as ET
9

    
10
from django.conf import settings
11

    
12
import psycopg2
13

    
14
from . import app_settings
15

    
16

    
17
def get_provider_key(provider_id):
18
    return provider_id.replace('://', '-').replace('/', '-').replace('?', '-').replace(':', '-')
19

    
20

    
21
class DeployInstance(object):
22
    skeleton = 'default'
23

    
24
    skel_dir = None
25
    collectivity_install_dir = None
26

    
27
    def __init__(self, domain, title, site_options_cfg):
28
        self.domain = domain.encode('utf-8')
29
        self.title = title.encode('utf-8')
30
        self.site_options_cfg = site_options_cfg
31

    
32
    def make(self):
33
        self.skel_dir = os.path.join(settings.MEDIA_ROOT, 'skeletons', self.skeleton)
34

    
35
        url_template = app_settings.URL_TEMPLATE
36
        self.url = str(url_template % {'domain': self.domain})
37

    
38
        host, path = urlparse(self.url)[1:3]
39
        if path.endswith('/'):
40
            path = path[:-1]
41

    
42
        coldir = host
43
        if path:
44
            coldir += path.replace('/', '+')
45

    
46
        self.collectivity_install_dir = os.path.join(app_settings.WCS_APP_DIR, coldir)
47

    
48
        if os.path.exists(self.collectivity_install_dir):
49
            # site exists, let's update it
50
            pass
51
            anew = False
52
        else:
53
            anew = True
54
            os.mkdir(self.collectivity_install_dir)
55

    
56
        z = zipfile.ZipFile(os.path.join(self.skel_dir, 'export.wcs'), 'r')
57

    
58
        for f in z.namelist():
59
            path = os.path.join(self.collectivity_install_dir, f)
60
            data = z.read(f)
61
            if not os.path.exists(os.path.dirname(path)):
62
                os.mkdir(os.path.dirname(path))
63
            if not f.endswith('/'):
64
                open(path, 'w').write(data)
65
        z.close()
66

    
67
        config_file = os.path.join(self.collectivity_install_dir, 'config.pck')
68
        if os.path.exists(config_file):
69
            wcs_cfg = cPickle.load(file(os.path.join(self.collectivity_install_dir, 'config.pck')))
70
        else:
71
            wcs_cfg = {}
72

    
73
        has_sql = self.make_sql_config(wcs_cfg)
74
        self.make_sso_config(wcs_cfg)
75
        self.make_site_options()
76

    
77
        cPickle.dump(wcs_cfg, file(config_file, 'w'))
78

    
79
        if has_sql:
80
            self.make_sql_tables(wcs_cfg)
81

    
82
        self.make_apache_vhost()
83
        self.reload_apache()
84

    
85

    
86
    def make_sql_config(self, wcs_cfg):
87
        if not wcs_cfg.get('postgresql'):
88
            # this is not a site configured to use SQL
89
            return False
90

    
91
        database_name = wcs_cfg['postgresql'].get('database', 'wcs')
92
        domain_table_name = self.domain.replace('-', '_').replace('.', '_')
93
        if '_' in database_name:
94
            database_name = '%s_%s' % (database_name.split('_')[0], domain_table_name)
95
        else:
96
            database_name = '%s_%s' % (database_name, domain_table_name)
97

    
98
        postgresql_cfg = {}
99
        for k, v in wcs_cfg['postgresql'].items():
100
            if v:
101
                postgresql_cfg[k] = v
102
        try:
103
            pgconn = psycopg2.connect(**postgresql_cfg)
104
        except psycopg2.Error:
105
            # XXX: log
106
            raise
107

    
108
        pgconn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
109
        cur = pgconn.cursor()
110
        try:
111
            cur.execute('''CREATE DATABASE %s''' % database_name)
112
        except psycopg2.Error as e:
113
            print 'got psycopg2 error:', e
114
        cur.close()
115

    
116
        wcs_cfg['postgresql']['database'] = database_name
117

    
118
        return True
119

    
120
    def make_sql_tables(self, wcs_cfg):
121
        params = []
122
        for param in ('database', 'user', 'password', 'host', 'port'):
123
            if wcs_cfg.get('postgresql').get(param):
124
                if param == 'database':
125
                    params.append('--dbname')
126
                else:
127
                    params.append('--' + param)
128
                params.append(wcs_cfg.get('postgresql').get(param))
129
        os.system('%s convert-to-sql %s %s' % (app_settings.WCSCTL_SCRIPT, ' '.join(params),
130
            os.path.basename(self.collectivity_install_dir)))
131

    
132
    def make_sso_config(self, wcs_cfg):
133
        has_idff = False
134
        has_saml2 = False
135

    
136
        service_provider_configuration = {}
137

    
138
        if self.url.endswith('/'):
139
            url_stripped = self.url[:-1]
140
        else:
141
            url_stripped = self.url
142

    
143
        if os.path.exists(os.path.join(self.skel_dir, 'idff-metadata-template')):
144
            # there's a ID-FF metadata template, so we do the ID-FF stuff
145
            has_idff = True
146
            service_provider_configuration.update({
147
                'base_url': '%s/liberty' % url_stripped,
148
                'metadata': 'metadata.xml',
149
                'providerid': '%s/liberty/metadata' % url_stripped,
150
                })
151

    
152
            idff_metadata_template = file(
153
                    os.path.join(self.skel_dir, 'idff-metadata-template')).read()
154
            file(os.path.join(self.collectivity_install_dir, 'metadata.xml'), 'w').write(
155
                    idff_metadata_template.format(url=url_stripped))
156

    
157
        if os.path.exists(os.path.join(self.skel_dir, 'saml2-metadata-template')):
158
            # there's a SAMLv2 metadata template, so we do the SAMLv2 stuff
159
            has_saml2 = True
160
            service_provider_configuration.update({
161
                'saml2_base_url': '%s/saml' % url_stripped,
162
                'saml2_metadata': 'saml2-metadata.xml',
163
                'saml2_providerid': '%s/saml/metadata' % url_stripped
164
                })
165

    
166
            saml2_metadata_template = file(
167
                    os.path.join(self.skel_dir, 'saml2-metadata-template')).read()
168
            file(os.path.join(self.collectivity_install_dir, 'saml2-metadata.xml'), 'w').write(
169
                    saml2_metadata_template.format(url=url_stripped))
170

    
171
        if has_idff or has_saml2:
172
            idp_metadata = ET.parse(file(os.path.join(self.skel_dir, 'idp-metadata.xml')))
173
            entity_id = idp_metadata.getroot().attrib['entityID']
174
            idp_key = get_provider_key(entity_id)
175
            title = self.title
176

    
177
            wcs_cfg['identification'] = {'methods': ['idp']}
178
            wcs_cfg['idp'] = {
179
                    idp_key: {
180
                        'metadata': 'provider-%s-metadata.xml' % idp_key,
181
                        'metadata_url': entity_id,
182
                        'publickey_url': None,
183
                        'admin-attributes': { 'role': title + ' - Administrateur' },
184
                        'role': 2}}
185
            wcs_cfg['sp'] = {
186
                    'common_domain': None,
187
                    'idp-manage-user-attributes': True,
188
                    'common_domain_getter_url': None,
189
                    'organization_name': title,
190
                    'privatekey': 'private-key.pem',
191
                    'publickey': 'public-key.pem'}
192
            wcs_cfg['sp'].update(service_provider_configuration)
193

    
194
            file(os.path.join(self.collectivity_install_dir, 'provider-%s-metadata.xml' % idp_key), 'w').write(
195
                    file(os.path.join(self.skel_dir, 'idp-metadata.xml')).read())
196
            file(os.path.join(self.collectivity_install_dir, 'public-key.pem'), 'w').write(
197
                    file(os.path.join(self.skel_dir, 'public-key.pem')).read())
198
            file(os.path.join(self.collectivity_install_dir, 'private-key.pem'), 'w').write(
199
                    file(os.path.join(self.skel_dir, 'private-key.pem')).read())
200
        else:
201
            wcs_cfg['identification'] = {'methods': ['password']}
202

    
203

    
204
    def make_site_options(self):
205
        options_template_path = os.path.join(self.skel_dir, 'site-options.cfg')
206
        if not os.path.exists(options_template_path):
207
            return
208
        options_template = file(options_template_path).read()
209
        file(os.path.join(self.collectivity_install_dir, 'site-options.cfg'), 'w').write(
210
                options_template.format(domain=self.domain,
211
                    options=self.site_options_cfg))
212

    
213

    
214
    def make_apache_vhost(self):
215
        apache_vhost_template_path = os.path.join(self.skel_dir, 'apache-vhost.conf')
216
        if not os.path.exists(apache_vhost_template_path):
217
            return
218
        apache_vhost_template = file(apache_vhost_template_path).read()
219
        apache_dir = os.path.join(settings.MEDIA_ROOT, 'vhosts.d')
220
        if not os.path.exists(apache_dir):
221
            os.mkdir(apache_dir)
222
        file(os.path.join(apache_dir, '%s.conf' % self.domain), 'w').write(
223
                apache_vhost_template.format(domain=self.domain))
224

    
225

    
226
    def reload_apache(self):
227
        os.system('sudo -n /etc/init.d/apache2 reload')
(3-3/6)