1""" Webaccelerator commands module """
2
3from gandi.cli.core.base import GandiModule
4from gandi.cli.modules.datacenter import Datacenter
5
6
7class Webacc(GandiModule):
8
9    """ Module to handle CLI commands.
10
11    $ gandi webacc list
12    $ gandi webacc info
13    $ gandi webacc create
14    $ gandi webacc add
15    $ gandi webacc delete
16    $ gandi webacc enable
17    $ gandi webacc disable
18    $ gandi webacc probe
19
20    """
21
22    @classmethod
23    def list(cls, options=None):
24        """ List all webaccelerator """
25        if not options:
26            options = {}
27        return cls.call('hosting.rproxy.list', options)
28
29    @classmethod
30    def info(cls, id):
31        """ Get information about a Webaccelerator """
32        return cls.call('hosting.rproxy.info', cls.usable_id(id))
33
34    @classmethod
35    def create(cls, name, datacenter, backends, vhosts, algorithm,
36               ssl_enable, zone_alter):
37        """ Create a webaccelerator """
38        datacenter_id_ = int(Datacenter.usable_id(datacenter))
39        params = {
40            'datacenter_id': datacenter_id_,
41            'name': name,
42            'lb': {'algorithm': algorithm},
43            'override': True,
44            'ssl_enable': ssl_enable,
45            'zone_alter': zone_alter
46        }
47        if vhosts:
48            params['vhosts'] = vhosts
49        if backends:
50            params['servers'] = backends
51        try:
52            result = cls.call('hosting.rproxy.create', params)
53            cls.echo('Creating your webaccelerator %s' % params['name'])
54            cls.display_progress(result)
55            cls.echo('Your webaccelerator have been created')
56            return result
57        except Exception as err:
58            if err.code == 580142:
59                for vhost in params['vhosts']:
60                    dns_entry = cls.call(
61                        'hosting.rproxy.vhost.get_dns_entries',
62                        {'datacenter': datacenter_id_, 'vhost': vhost})
63                    txt_record = "@ 3600 IN TXT \"%s=%s\"" % (dns_entry['key'],
64                                                              dns_entry['txt'])
65
66                    cname_record = "%s 3600 IN CNAME %s" % (dns_entry['key'],
67                                                            dns_entry['cname'])
68
69                    cls.echo('The domain %s don\'t use Gandi DNS or you have'
70                             ' not sufficient right to alter the zone file. '
71                             'Edit your zone file adding this TXT and CNAME '
72                             'record and try again :' % vhost)
73                    cls.echo(txt_record)
74                    cls.echo(cname_record)
75                    cls.echo('\nOr add a file containing %s at :\n'
76                             'http://%s/%s.txt\n' % (dns_entry['txt'],
77                                                     dns_entry['domain'],
78                                                     dns_entry['txt']))
79                    cls.separator_line('-', 4)
80            else:
81                cls.echo(err)
82
83    @classmethod
84    def update(cls, resource, new_name, algorithm, ssl_enable, ssl_disable):
85        """ Update a webaccelerator"""
86        params = {}
87        if new_name:
88            params['name'] = new_name
89        if algorithm:
90            params['lb'] = {'algorithm': algorithm}
91        if ssl_enable:
92            params['ssl_enable'] = ssl_enable
93        if ssl_disable:
94            params['ssl_enable'] = False
95
96        result = cls.call('hosting.rproxy.update', cls.usable_id(resource),
97                          params)
98        cls.echo('Updating your webaccelerator')
99        cls.display_progress(result)
100        cls.echo('The webaccelerator have been udated')
101        return result
102
103    @classmethod
104    def delete(cls, name):
105        """ Delete a webaccelerator """
106        result = cls.call('hosting.rproxy.delete', cls.usable_id(name))
107        cls.echo('Deleting your webaccelerator named %s' % name)
108        cls.display_progress(result)
109        cls.echo('Webaccelerator have been deleted')
110        return result
111
112    @classmethod
113    def backend_list(cls, options):
114        """ List all servers used by webaccelerator """
115        return cls.call('hosting.rproxy.server.list', options)
116
117    @classmethod
118    def backend_add(cls, name, backend):
119        """ Add a backend into a webaccelerator """
120        oper = cls.call(
121            'hosting.rproxy.server.create', cls.usable_id(name), backend)
122        cls.echo('Adding backend %s:%s into webaccelerator' %
123                 (backend['ip'], backend['port']))
124        cls.display_progress(oper)
125        cls.echo('Backend added')
126        return oper
127
128    @classmethod
129    def backend_remove(cls, backend):
130        """ Remove a backend on a webaccelerator """
131        server = cls.backend_list(backend)
132        if server:
133            oper = cls.call('hosting.rproxy.server.delete', server[0]['id'])
134            cls.echo('Removing backend %s:%s into webaccelerator' %
135                     (backend['ip'], backend['port']))
136            cls.display_progress(oper)
137            cls.echo('Your backend have been removed')
138            return oper
139        else:
140            return cls.echo('No backend found')
141
142    @classmethod
143    def backend_enable(cls, backend):
144        """ Enable a backend for a server """
145        server = cls.backend_list(backend)
146        if server:
147            oper = cls.call('hosting.rproxy.server.enable', server[0]['id'])
148            cls.echo('Activating backend %s' % server[0]['ip'])
149            cls.display_progress(oper)
150            cls.echo('Backend activated')
151            return oper
152        else:
153            return cls.echo('No backend found')
154
155    @classmethod
156    def backend_disable(cls, backend):
157        """ Disable a backend for a server """
158        server = cls.backend_list(backend)
159        oper = cls.call('hosting.rproxy.server.disable',
160                        server[0]['id'])
161        cls.echo('Desactivating backend on server %s' %
162                 server[0]['ip'])
163        cls.display_progress(oper)
164        cls.echo('Backend desactivated')
165        return oper
166
167    @classmethod
168    def vhost_list(cls):
169        """ List all vhosts used by webaccelerator """
170        return cls.call('hosting.rproxy.vhost.list')
171
172    @classmethod
173    def vhost_add(cls, resource, params):
174        """ Add a vhost into a webaccelerator """
175        try:
176            oper = cls.call(
177                'hosting.rproxy.vhost.create', cls.usable_id(resource), params)
178            cls.echo('Adding your virtual host (%s) into %s' %
179                     (params['vhost'], resource))
180            cls.display_progress(oper)
181            cls.echo('Your virtual host habe been added')
182            return oper
183        except Exception as err:
184            if err.code == 580142:
185                dc = cls.info(resource)
186                dns_entry = cls.call('hosting.rproxy.vhost.get_dns_entries',
187                                     {'datacenter': dc['datacenter']['id'],
188                                      'vhost': params['vhost']})
189                txt_record = "%s 3600 IN TXT \"%s=%s\"" % (dns_entry['key'],
190                                                           dns_entry['key'],
191                                                           dns_entry['txt'])
192
193                cname_record = "%s 3600 IN CNAME %s" % (dns_entry['key'],
194                                                        dns_entry['cname'])
195
196                cls.echo('The domain don\'t use Gandi DNS or you have not'
197                         ' sufficient right to alter the zone file. '
198                         'Edit your zone file adding this TXT and CNAME '
199                         'record and try again :')
200                cls.echo(txt_record)
201                cls.echo(cname_record)
202                cls.echo('\nOr add a file containing %s at :\n'
203                         'http://%s/%s.txt\n' % (dns_entry['txt'],
204                                                 dns_entry['domain'],
205                                                 dns_entry['txt']))
206
207            else:
208                cls.echo(err)
209
210    @classmethod
211    def vhost_remove(cls, name):
212        """ Delete a vhost in a webaccelerator """
213        oper = cls.call('hosting.rproxy.vhost.delete', name)
214        cls.echo('Deleting your virtual host %s' % name)
215        cls.display_progress(oper)
216        cls.echo('Your virtual host have been removed')
217        return oper
218
219    @classmethod
220    def probe(cls, resource, enable, disable, test, host, interval,
221              http_method, http_response, threshold, timeout, url, window):
222        """ Set a probe for a webaccelerator """
223        params = {
224            'host': host,
225            'interval': interval,
226            'method': http_method,
227            'response': http_response,
228            'threshold': threshold,
229            'timeout': timeout,
230            'url': url,
231            'window': window
232        }
233        if enable:
234            params['enable'] = True
235        elif disable:
236            params['enable'] = False
237        if test:
238            result = cls.call(
239                'hosting.rproxy.probe.test', cls.usable_id(resource), params)
240        else:
241            result = cls.call(
242                'hosting.rproxy.probe.update', cls.usable_id(resource), params)
243            cls.display_progress(result)
244        return result
245
246    @classmethod
247    def probe_enable(cls, resource):
248        """ Activate a probe on a webaccelerator """
249        oper = cls.call('hosting.rproxy.probe.enable', cls.usable_id(resource))
250        cls.echo('Activating probe on %s' % resource)
251        cls.display_progress(oper)
252        cls.echo('The probe have been activated')
253        return oper
254
255    @classmethod
256    def probe_disable(cls, resource):
257        """ Disable a probe on a webaccelerator """
258        oper = cls.call('hosting.rproxy.probe.disable',
259                        cls.usable_id(resource))
260        cls.echo('Desactivating probe on %s' % resource)
261        cls.display_progress(oper)
262        cls.echo('The probe have been desactivated')
263        return oper
264
265    @classmethod
266    def usable_id(cls, id):
267        """ Retrieve id from input which can be hostname, vhost, id. """
268        try:
269            # id is maybe a hostname
270            qry_id = cls.from_name(id)
271            if not qry_id:
272                # id is maybe an ip
273                qry_id = cls.from_ip(id)
274            if not qry_id:
275                qry_id = cls.from_vhost(id)
276        except Exception:
277            qry_id = None
278
279        if not qry_id:
280            msg = 'unknown identifier %s' % id
281            cls.error(msg)
282
283        return qry_id
284
285    @classmethod
286    def from_name(cls, name):
287        """Retrieve webacc id associated to a webacc name."""
288        result = cls.list({'items_per_page': 500})
289        webaccs = {}
290        for webacc in result:
291            webaccs[webacc['name']] = webacc['id']
292        return webaccs.get(name)
293
294    @classmethod
295    def from_ip(cls, ip):
296        """Retrieve webacc id associated to a webacc ip"""
297        result = cls.list({'items_per_page': 500})
298        webaccs = {}
299        for webacc in result:
300            for server in webacc['servers']:
301                webaccs[server['ip']] = webacc['id']
302        return webaccs.get(ip)
303
304    @classmethod
305    def from_vhost(cls, vhost):
306        """Retrieve webbacc id associated to a webacc vhost"""
307        result = cls.list({'items_per_page': 500})
308        webaccs = {}
309        for webacc in result:
310            for vhost in webacc['vhosts']:
311                webaccs[vhost['name']] = webacc['id']
312        return webaccs.get(vhost)
313