Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / cyclades.py @ 56d84a4e

History | View | Annotate | Download (45.8 kB)

1 a494a741 Stavros Sachtouris
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2 7493ccb6 Stavros Sachtouris
#
3 7493ccb6 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 7493ccb6 Stavros Sachtouris
# without modification, are permitted provided that the following
5 7493ccb6 Stavros Sachtouris
# conditions are met:
6 7493ccb6 Stavros Sachtouris
#
7 7493ccb6 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 7493ccb6 Stavros Sachtouris
#      disclaimer.
10 7493ccb6 Stavros Sachtouris
#
11 7493ccb6 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 7493ccb6 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 7493ccb6 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 7493ccb6 Stavros Sachtouris
#      provided with the distribution.
15 7493ccb6 Stavros Sachtouris
#
16 7493ccb6 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7493ccb6 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7493ccb6 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7493ccb6 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7493ccb6 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7493ccb6 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7493ccb6 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7493ccb6 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7493ccb6 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7493ccb6 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7493ccb6 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7493ccb6 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 7493ccb6 Stavros Sachtouris
#
29 7493ccb6 Stavros Sachtouris
# The views and conclusions contained in the software and
30 7493ccb6 Stavros Sachtouris
# documentation are those of the authors and should not be
31 7493ccb6 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 7493ccb6 Stavros Sachtouris
# or implied, of GRNET S.A.
33 7493ccb6 Stavros Sachtouris
34 76f58e2e Stavros Sachtouris
from base64 import b64encode
35 d62cba24 Stavros Sachtouris
from os.path import exists, expanduser
36 76f58e2e Stavros Sachtouris
from io import StringIO
37 76f58e2e Stavros Sachtouris
from pydoc import pager
38 76f58e2e Stavros Sachtouris
39 f3e94e06 Stavros Sachtouris
from kamaki.cli import command
40 d486baec Stavros Sachtouris
from kamaki.cli.command_tree import CommandTree
41 76f58e2e Stavros Sachtouris
from kamaki.cli.utils import remove_from_items, filter_dicts_by_dict
42 c788a761 Stavros Sachtouris
from kamaki.cli.errors import (
43 c788a761 Stavros Sachtouris
    raiseCLIError, CLISyntaxError, CLIBaseUrlError, CLIInvalidArgument)
44 7493ccb6 Stavros Sachtouris
from kamaki.clients.cyclades import CycladesClient, ClientError
45 57d622b6 Stavros Sachtouris
from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
46 bd40efdf Stavros Sachtouris
from kamaki.cli.argument import ProgressBarArgument, DateArgument, IntArgument
47 b4f69041 Stavros Sachtouris
from kamaki.cli.commands import _command_init, errors, addLogSettings
48 6d190dd1 Stavros Sachtouris
from kamaki.cli.commands import (
49 6d190dd1 Stavros Sachtouris
    _optional_output_cmd, _optional_json, _name_filter, _id_filter)
50 5eae854d Stavros Sachtouris
51 234954d1 Stavros Sachtouris
52 a29d2f88 Stavros Sachtouris
server_cmds = CommandTree('server', 'Cyclades/Compute API server commands')
53 a29d2f88 Stavros Sachtouris
flavor_cmds = CommandTree('flavor', 'Cyclades/Compute API flavor commands')
54 a29d2f88 Stavros Sachtouris
network_cmds = CommandTree('network', 'Cyclades/Compute API network commands')
55 6489c38b Stavros Sachtouris
ip_cmds = CommandTree('ip', 'Cyclades/Compute API floating ip commands')
56 6489c38b Stavros Sachtouris
_commands = [server_cmds, flavor_cmds, network_cmds, ip_cmds]
57 234954d1 Stavros Sachtouris
58 7493ccb6 Stavros Sachtouris
59 c314fc10 Stavros Sachtouris
about_authentication = '\nUser Authentication:\
60 4018326d Stavros Sachtouris
    \n* to check authentication: /user authenticate\
61 9e5341f5 Stavros Sachtouris
    \n* to set authentication token: /config set cloud.<cloud>.token <token>'
62 18edacfe Stavros Sachtouris
63 d7259dd5 Stavros Sachtouris
howto_personality = [
64 2bd23362 Stavros Sachtouris
    'Defines a file to be injected to virtual servers file system.',
65 3185cd6d Stavros Sachtouris
    'syntax:  PATH,[SERVER_PATH,[OWNER,[GROUP,[MODE]]]]',
66 0fccd79b Stavros Sachtouris
    '  [local-path=]PATH: local file to be injected (relative or absolute)',
67 0fccd79b Stavros Sachtouris
    '  [server-path=]SERVER_PATH: destination location inside server Image',
68 0fccd79b Stavros Sachtouris
    '  [owner=]OWNER: virtual servers user id for the remote file',
69 0fccd79b Stavros Sachtouris
    '  [group=]GROUP: virtual servers group id or name for the remote file',
70 d62cba24 Stavros Sachtouris
    '  [mode=]MODE: permission in octal (e.g., 0777)',
71 0fccd79b Stavros Sachtouris
    'e.g., -p /tmp/my.file,owner=root,mode=0777']
72 d7259dd5 Stavros Sachtouris
73 18edacfe Stavros Sachtouris
74 3185cd6d Stavros Sachtouris
class _service_wait(object):
75 60c42f9f Stavros Sachtouris
76 60c42f9f Stavros Sachtouris
    wait_arguments = dict(
77 60c42f9f Stavros Sachtouris
        progress_bar=ProgressBarArgument(
78 3185cd6d Stavros Sachtouris
            'do not show progress bar', ('-N', '--no-progress-bar'), False)
79 60c42f9f Stavros Sachtouris
    )
80 60c42f9f Stavros Sachtouris
81 e9c73313 Stavros Sachtouris
    def _wait(
82 e9c73313 Stavros Sachtouris
            self, service, service_id, status_method, current_status,
83 8547cd19 Stavros Sachtouris
            countdown=True, timeout=60):
84 60c42f9f Stavros Sachtouris
        (progress_bar, wait_cb) = self._safe_progress_bar(
85 e9c73313 Stavros Sachtouris
            '%s %s: status is still %s' % (
86 e9c73313 Stavros Sachtouris
                service, service_id, current_status),
87 8547cd19 Stavros Sachtouris
            countdown=countdown, timeout=timeout)
88 60c42f9f Stavros Sachtouris
89 60c42f9f Stavros Sachtouris
        try:
90 3185cd6d Stavros Sachtouris
            new_mode = status_method(
91 8547cd19 Stavros Sachtouris
                service_id, current_status, max_wait=timeout, wait_cb=wait_cb)
92 a9598baf Stavros Sachtouris
            if new_mode:
93 e9c73313 Stavros Sachtouris
                self.error('%s %s: status is now %s' % (
94 a9598baf Stavros Sachtouris
                    service, service_id, new_mode))
95 a9598baf Stavros Sachtouris
            else:
96 8547cd19 Stavros Sachtouris
                self.error('%s %s: status is still %s' % (
97 e9c73313 Stavros Sachtouris
                    service, service_id, current_status))
98 a9598baf Stavros Sachtouris
        except KeyboardInterrupt:
99 a9598baf Stavros Sachtouris
            self.error('\n- canceled')
100 60c42f9f Stavros Sachtouris
        finally:
101 60c42f9f Stavros Sachtouris
            self._safe_progress_bar_finish(progress_bar)
102 60c42f9f Stavros Sachtouris
103 60c42f9f Stavros Sachtouris
104 3185cd6d Stavros Sachtouris
class _server_wait(_service_wait):
105 7b2e4bf1 Stavros Sachtouris
106 8547cd19 Stavros Sachtouris
    def _wait(self, server_id, current_status, timeout=60):
107 3185cd6d Stavros Sachtouris
        super(_server_wait, self)._wait(
108 e9c73313 Stavros Sachtouris
            'Server', server_id, self.client.wait_server, current_status,
109 8547cd19 Stavros Sachtouris
            countdown=(current_status not in ('BUILD', )),
110 8547cd19 Stavros Sachtouris
            timeout=timeout if current_status not in ('BUILD', ) else 100)
111 7b2e4bf1 Stavros Sachtouris
112 7b2e4bf1 Stavros Sachtouris
113 3185cd6d Stavros Sachtouris
class _network_wait(_service_wait):
114 3185cd6d Stavros Sachtouris
115 8547cd19 Stavros Sachtouris
    def _wait(self, net_id, current_status, timeout=60):
116 3185cd6d Stavros Sachtouris
        super(_network_wait, self)._wait(
117 8547cd19 Stavros Sachtouris
            'Network', net_id, self.client.wait_network, current_status,
118 8547cd19 Stavros Sachtouris
            timeout=timeout)
119 7b2e4bf1 Stavros Sachtouris
120 7b2e4bf1 Stavros Sachtouris
121 c788a761 Stavros Sachtouris
class _firewall_wait(_service_wait):
122 c788a761 Stavros Sachtouris
123 c788a761 Stavros Sachtouris
    def _wait(self, server_id, current_status, timeout=60):
124 c788a761 Stavros Sachtouris
        super(_firewall_wait, self)._wait(
125 c788a761 Stavros Sachtouris
            'Firewall of server',
126 c788a761 Stavros Sachtouris
            server_id, self.client.wait_firewall, current_status,
127 c788a761 Stavros Sachtouris
            timeout=timeout)
128 c788a761 Stavros Sachtouris
129 c788a761 Stavros Sachtouris
130 5eae854d Stavros Sachtouris
class _init_cyclades(_command_init):
131 b04288f7 Stavros Sachtouris
    @errors.generic.all
132 b4f69041 Stavros Sachtouris
    @addLogSettings
133 236e7d08 Stavros Sachtouris
    def _run(self, service='compute'):
134 b4f69041 Stavros Sachtouris
        if getattr(self, 'cloud', None):
135 3185cd6d Stavros Sachtouris
            base_url = self._custom_url(service) or self._custom_url(
136 3185cd6d Stavros Sachtouris
                'cyclades')
137 b4f69041 Stavros Sachtouris
            if base_url:
138 3185cd6d Stavros Sachtouris
                token = self._custom_token(service) or self._custom_token(
139 3185cd6d Stavros Sachtouris
                    'cyclades') or self.config.get_cloud('token')
140 3185cd6d Stavros Sachtouris
                self.client = CycladesClient(base_url=base_url, token=token)
141 b4f69041 Stavros Sachtouris
                return
142 b4f69041 Stavros Sachtouris
        else:
143 b4f69041 Stavros Sachtouris
            self.cloud = 'default'
144 8cec3671 Stavros Sachtouris
        if getattr(self, 'auth_base', False):
145 8cec3671 Stavros Sachtouris
            cyclades_endpoints = self.auth_base.get_service_endpoints(
146 b4f69041 Stavros Sachtouris
                self._custom_type('cyclades') or 'compute',
147 b4f69041 Stavros Sachtouris
                self._custom_version('cyclades') or '')
148 8cec3671 Stavros Sachtouris
            base_url = cyclades_endpoints['publicURL']
149 b4f69041 Stavros Sachtouris
            token = self.auth_base.token
150 b4f69041 Stavros Sachtouris
            self.client = CycladesClient(base_url=base_url, token=token)
151 8cec3671 Stavros Sachtouris
        else:
152 8cec3671 Stavros Sachtouris
            raise CLIBaseUrlError(service='cyclades')
153 8cec3671 Stavros Sachtouris
154 b04288f7 Stavros Sachtouris
    def main(self):
155 b04288f7 Stavros Sachtouris
        self._run()
156 236e7d08 Stavros Sachtouris
157 234954d1 Stavros Sachtouris
158 d486baec Stavros Sachtouris
@command(server_cmds)
159 6d190dd1 Stavros Sachtouris
class server_list(_init_cyclades, _optional_json, _name_filter, _id_filter):
160 f6822a26 Stavros Sachtouris
    """List virtual servers accessible by user
161 16d7b9ff Stavros Sachtouris
    Use filtering arguments (e.g., --name-like) to manage long server lists
162 f6822a26 Stavros Sachtouris
    """
163 18edacfe Stavros Sachtouris
164 89ea97e1 Stavros Sachtouris
    PERMANENTS = ('id', 'name')
165 89ea97e1 Stavros Sachtouris
166 e15d78e2 Stavros Sachtouris
    arguments = dict(
167 f40f0cb7 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
168 67469d65 Stavros Sachtouris
        since=DateArgument(
169 a382ea56 Stavros Sachtouris
            'show only items since date (\' d/m/Y H:M:S \')',
170 a4d0d88a Stavros Sachtouris
            '--since'),
171 2bd23362 Stavros Sachtouris
        limit=IntArgument(
172 2bd23362 Stavros Sachtouris
            'limit number of listed virtual servers', ('-n', '--number')),
173 a4d0d88a Stavros Sachtouris
        more=FlagArgument(
174 ddc0b290 Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
175 ed9af02c Stavros Sachtouris
            '--more'),
176 89ea97e1 Stavros Sachtouris
        enum=FlagArgument('Enumerate results', '--enumerate'),
177 89ea97e1 Stavros Sachtouris
        flavor_id=ValueArgument('filter by flavor id', ('--flavor-id')),
178 89ea97e1 Stavros Sachtouris
        image_id=ValueArgument('filter by image id', ('--image-id')),
179 d8ff7b56 Stavros Sachtouris
        user_id=ValueArgument('filter by user id', ('--user-id')),
180 d8ff7b56 Stavros Sachtouris
        user_name=ValueArgument('filter by user name', ('--user-name')),
181 d8ff7b56 Stavros Sachtouris
        status=ValueArgument(
182 d8ff7b56 Stavros Sachtouris
            'filter by status (ACTIVE, STOPPED, REBOOT, ERROR, etc.)',
183 d8ff7b56 Stavros Sachtouris
            ('--status')),
184 89ea97e1 Stavros Sachtouris
        meta=KeyValueArgument('filter by metadata key=values', ('--metadata')),
185 89ea97e1 Stavros Sachtouris
        meta_like=KeyValueArgument(
186 89ea97e1 Stavros Sachtouris
            'print only if in key=value, the value is part of actual value',
187 89ea97e1 Stavros Sachtouris
            ('--metadata-like')),
188 e15d78e2 Stavros Sachtouris
    )
189 e15d78e2 Stavros Sachtouris
190 f00db940 Stavros Sachtouris
    def _add_user_name(self, servers):
191 9d2f656a Stavros Sachtouris
        uuids = self._uuids2usernames(list(set(
192 9d2f656a Stavros Sachtouris
                [srv['user_id'] for srv in servers] +
193 9d2f656a Stavros Sachtouris
                [srv['tenant_id'] for srv in servers])))
194 f00db940 Stavros Sachtouris
        for srv in servers:
195 f00db940 Stavros Sachtouris
            srv['user_id'] += ' (%s)' % uuids[srv['user_id']]
196 9d2f656a Stavros Sachtouris
            srv['tenant_id'] += ' (%s)' % uuids[srv['tenant_id']]
197 f00db940 Stavros Sachtouris
        return servers
198 f00db940 Stavros Sachtouris
199 d8ff7b56 Stavros Sachtouris
    def _apply_common_filters(self, servers):
200 d8ff7b56 Stavros Sachtouris
        common_filters = dict()
201 d8ff7b56 Stavros Sachtouris
        if self['status']:
202 d8ff7b56 Stavros Sachtouris
            common_filters['status'] = self['status']
203 d8ff7b56 Stavros Sachtouris
        if self['user_id'] or self['user_name']:
204 d8ff7b56 Stavros Sachtouris
            uuid = self['user_id'] or self._username2uuid(self['user_name'])
205 d8ff7b56 Stavros Sachtouris
            common_filters['user_id'] = uuid
206 d8ff7b56 Stavros Sachtouris
        return filter_dicts_by_dict(servers, common_filters)
207 d8ff7b56 Stavros Sachtouris
208 6d190dd1 Stavros Sachtouris
    def _filter_by_image(self, servers):
209 89ea97e1 Stavros Sachtouris
        iid = self['image_id']
210 3185cd6d Stavros Sachtouris
        return [srv for srv in servers if srv['image']['id'] == iid]
211 89ea97e1 Stavros Sachtouris
212 6d190dd1 Stavros Sachtouris
    def _filter_by_flavor(self, servers):
213 89ea97e1 Stavros Sachtouris
        fid = self['flavor_id']
214 3185cd6d Stavros Sachtouris
        return [srv for srv in servers if (
215 3185cd6d Stavros Sachtouris
            '%s' % srv['image']['id'] == '%s' % fid)]
216 89ea97e1 Stavros Sachtouris
217 6d190dd1 Stavros Sachtouris
    def _filter_by_metadata(self, servers):
218 89ea97e1 Stavros Sachtouris
        new_servers = []
219 89ea97e1 Stavros Sachtouris
        for srv in servers:
220 89ea97e1 Stavros Sachtouris
            if not 'metadata' in srv:
221 89ea97e1 Stavros Sachtouris
                continue
222 89ea97e1 Stavros Sachtouris
            meta = [dict(srv['metadata'])]
223 89ea97e1 Stavros Sachtouris
            if self['meta']:
224 89ea97e1 Stavros Sachtouris
                meta = filter_dicts_by_dict(meta, self['meta'])
225 89ea97e1 Stavros Sachtouris
            if meta and self['meta_like']:
226 89ea97e1 Stavros Sachtouris
                meta = filter_dicts_by_dict(
227 89ea97e1 Stavros Sachtouris
                    meta, self['meta_like'], exact_match=False)
228 89ea97e1 Stavros Sachtouris
            if meta:
229 89ea97e1 Stavros Sachtouris
                new_servers.append(srv)
230 89ea97e1 Stavros Sachtouris
        return new_servers
231 89ea97e1 Stavros Sachtouris
232 b04288f7 Stavros Sachtouris
    @errors.generic.all
233 b04288f7 Stavros Sachtouris
    @errors.cyclades.connection
234 b04288f7 Stavros Sachtouris
    @errors.cyclades.date
235 b04288f7 Stavros Sachtouris
    def _run(self):
236 89ea97e1 Stavros Sachtouris
        withimage = bool(self['image_id'])
237 89ea97e1 Stavros Sachtouris
        withflavor = bool(self['flavor_id'])
238 89ea97e1 Stavros Sachtouris
        withmeta = bool(self['meta'] or self['meta_like'])
239 d8ff7b56 Stavros Sachtouris
        withcommons = bool(
240 d8ff7b56 Stavros Sachtouris
            self['status'] or self['user_id'] or self['user_name'])
241 d8ff7b56 Stavros Sachtouris
        detail = self['detail'] or (
242 d8ff7b56 Stavros Sachtouris
            withimage or withflavor or withmeta or withcommons)
243 89ea97e1 Stavros Sachtouris
        servers = self.client.list_servers(detail, self['since'])
244 89ea97e1 Stavros Sachtouris
245 6d190dd1 Stavros Sachtouris
        servers = self._filter_by_name(servers)
246 6d190dd1 Stavros Sachtouris
        servers = self._filter_by_id(servers)
247 d8ff7b56 Stavros Sachtouris
        servers = self._apply_common_filters(servers)
248 89ea97e1 Stavros Sachtouris
        if withimage:
249 6d190dd1 Stavros Sachtouris
            servers = self._filter_by_image(servers)
250 89ea97e1 Stavros Sachtouris
        if withflavor:
251 6d190dd1 Stavros Sachtouris
            servers = self._filter_by_flavor(servers)
252 89ea97e1 Stavros Sachtouris
        if withmeta:
253 6d190dd1 Stavros Sachtouris
            servers = self._filter_by_metadata(servers)
254 89ea97e1 Stavros Sachtouris
255 f76c6bbc Stavros Sachtouris
        if self['detail'] and not (
256 f76c6bbc Stavros Sachtouris
                self['json_output'] or self['output_format']):
257 f00db940 Stavros Sachtouris
            servers = self._add_user_name(servers)
258 f76c6bbc Stavros Sachtouris
        elif not (self['detail'] or (
259 f76c6bbc Stavros Sachtouris
                self['json_output'] or self['output_format'])):
260 7ba195e5 Stavros Sachtouris
            remove_from_items(servers, 'links')
261 89ea97e1 Stavros Sachtouris
        if detail and not self['detail']:
262 89ea97e1 Stavros Sachtouris
            for srv in servers:
263 89ea97e1 Stavros Sachtouris
                for key in set(srv).difference(self.PERMANENTS):
264 89ea97e1 Stavros Sachtouris
                    srv.pop(key)
265 545c6c29 Stavros Sachtouris
        kwargs = dict(with_enumeration=self['enum'])
266 a4d0d88a Stavros Sachtouris
        if self['more']:
267 6430d3a0 Stavros Sachtouris
            kwargs['out'] = StringIO()
268 6430d3a0 Stavros Sachtouris
            kwargs['title'] = ()
269 6430d3a0 Stavros Sachtouris
        if self['limit']:
270 545c6c29 Stavros Sachtouris
            servers = servers[:self['limit']]
271 545c6c29 Stavros Sachtouris
        self._print(servers, **kwargs)
272 6430d3a0 Stavros Sachtouris
        if self['more']:
273 6430d3a0 Stavros Sachtouris
            pager(kwargs['out'].getvalue())
274 7493ccb6 Stavros Sachtouris
275 b04288f7 Stavros Sachtouris
    def main(self):
276 b04288f7 Stavros Sachtouris
        super(self.__class__, self)._run()
277 b04288f7 Stavros Sachtouris
        self._run()
278 b04288f7 Stavros Sachtouris
279 234954d1 Stavros Sachtouris
280 d486baec Stavros Sachtouris
@command(server_cmds)
281 545c6c29 Stavros Sachtouris
class server_info(_init_cyclades, _optional_json):
282 67469d65 Stavros Sachtouris
    """Detailed information on a Virtual Machine
283 67469d65 Stavros Sachtouris
    Contains:
284 67469d65 Stavros Sachtouris
    - name, id, status, create/update dates
285 67469d65 Stavros Sachtouris
    - network interfaces
286 16d7b9ff Stavros Sachtouris
    - metadata (e.g., os, superuser) and diagnostics
287 67469d65 Stavros Sachtouris
    - hardware flavor and os image ids
288 67469d65 Stavros Sachtouris
    """
289 7493ccb6 Stavros Sachtouris
290 b04288f7 Stavros Sachtouris
    @errors.generic.all
291 b04288f7 Stavros Sachtouris
    @errors.cyclades.connection
292 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
293 b04288f7 Stavros Sachtouris
    def _run(self, server_id):
294 cf115aed Stavros Sachtouris
        vm = self.client.get_server_details(server_id)
295 cf115aed Stavros Sachtouris
        uuids = self._uuids2usernames([vm['user_id'], vm['tenant_id']])
296 cf115aed Stavros Sachtouris
        vm['user_id'] += ' (%s)' % uuids[vm['user_id']]
297 cf115aed Stavros Sachtouris
        vm['tenant_id'] += ' (%s)' % uuids[vm['tenant_id']]
298 76f58e2e Stavros Sachtouris
        self._print(vm, self.print_dict)
299 7493ccb6 Stavros Sachtouris
300 b04288f7 Stavros Sachtouris
    def main(self, server_id):
301 b04288f7 Stavros Sachtouris
        super(self.__class__, self)._run()
302 b04288f7 Stavros Sachtouris
        self._run(server_id=server_id)
303 b04288f7 Stavros Sachtouris
304 234954d1 Stavros Sachtouris
305 57d622b6 Stavros Sachtouris
class PersonalityArgument(KeyValueArgument):
306 0fccd79b Stavros Sachtouris
307 0fccd79b Stavros Sachtouris
    terms = (
308 0fccd79b Stavros Sachtouris
        ('local-path', 'contents'),
309 0fccd79b Stavros Sachtouris
        ('server-path', 'path'),
310 0fccd79b Stavros Sachtouris
        ('owner', 'owner'),
311 0fccd79b Stavros Sachtouris
        ('group', 'group'),
312 0fccd79b Stavros Sachtouris
        ('mode', 'mode'))
313 0fccd79b Stavros Sachtouris
314 234954d1 Stavros Sachtouris
    @property
315 f3e94e06 Stavros Sachtouris
    def value(self):
316 6c068db6 Stavros Sachtouris
        return getattr(self, '_value', [])
317 234954d1 Stavros Sachtouris
318 234954d1 Stavros Sachtouris
    @value.setter
319 f3e94e06 Stavros Sachtouris
    def value(self, newvalue):
320 f3e94e06 Stavros Sachtouris
        if newvalue == self.default:
321 f3e94e06 Stavros Sachtouris
            return self.value
322 0fccd79b Stavros Sachtouris
        self._value, input_dict = [], {}
323 57d622b6 Stavros Sachtouris
        for i, terms in enumerate(newvalue):
324 57d622b6 Stavros Sachtouris
            termlist = terms.split(',')
325 0fccd79b Stavros Sachtouris
            if len(termlist) > len(self.terms):
326 0fccd79b Stavros Sachtouris
                msg = 'Wrong number of terms (1<=terms<=%s)' % len(self.terms)
327 de73876b Stavros Sachtouris
                raiseCLIError(CLISyntaxError(msg), details=howto_personality)
328 0fccd79b Stavros Sachtouris
329 0fccd79b Stavros Sachtouris
            for k, v in self.terms:
330 0fccd79b Stavros Sachtouris
                prefix = '%s=' % k
331 0fccd79b Stavros Sachtouris
                for item in termlist:
332 0fccd79b Stavros Sachtouris
                    if item.lower().startswith(prefix):
333 0fccd79b Stavros Sachtouris
                        input_dict[k] = item[len(k) + 1:]
334 0fccd79b Stavros Sachtouris
                        break
335 0fccd79b Stavros Sachtouris
                    item = None
336 0fccd79b Stavros Sachtouris
                if item:
337 0fccd79b Stavros Sachtouris
                    termlist.remove(item)
338 0fccd79b Stavros Sachtouris
339 0fccd79b Stavros Sachtouris
            try:
340 0fccd79b Stavros Sachtouris
                path = input_dict['local-path']
341 0fccd79b Stavros Sachtouris
            except KeyError:
342 0fccd79b Stavros Sachtouris
                path = termlist.pop(0)
343 0fccd79b Stavros Sachtouris
                if not path:
344 0fccd79b Stavros Sachtouris
                    raise CLIInvalidArgument(
345 0fccd79b Stavros Sachtouris
                        '--personality: No local path specified',
346 0fccd79b Stavros Sachtouris
                        details=howto_personality)
347 0fccd79b Stavros Sachtouris
348 57d622b6 Stavros Sachtouris
            if not exists(path):
349 0fccd79b Stavros Sachtouris
                raise CLIInvalidArgument(
350 8194b51b Stavros Sachtouris
                    '--personality: File %s does not exist' % path,
351 0fccd79b Stavros Sachtouris
                    details=howto_personality)
352 0fccd79b Stavros Sachtouris
353 57d622b6 Stavros Sachtouris
            self._value.append(dict(path=path))
354 d62cba24 Stavros Sachtouris
            with open(expanduser(path)) as f:
355 57d622b6 Stavros Sachtouris
                self._value[i]['contents'] = b64encode(f.read())
356 0fccd79b Stavros Sachtouris
            for k, v in self.terms[1:]:
357 0fccd79b Stavros Sachtouris
                try:
358 0fccd79b Stavros Sachtouris
                    self._value[i][v] = input_dict[k]
359 0fccd79b Stavros Sachtouris
                except KeyError:
360 0fccd79b Stavros Sachtouris
                    try:
361 0fccd79b Stavros Sachtouris
                        self._value[i][v] = termlist.pop(0)
362 0fccd79b Stavros Sachtouris
                    except IndexError:
363 0fccd79b Stavros Sachtouris
                        continue
364 d62cba24 Stavros Sachtouris
                if k in ('mode', ) and self._value[i][v]:
365 d62cba24 Stavros Sachtouris
                    try:
366 d62cba24 Stavros Sachtouris
                        self._value[i][v] = int(self._value[i][v], 8)
367 d62cba24 Stavros Sachtouris
                    except ValueError as ve:
368 d62cba24 Stavros Sachtouris
                        raise CLIInvalidArgument(
369 d62cba24 Stavros Sachtouris
                            'Personality mode must be in octal', details=[
370 d62cba24 Stavros Sachtouris
                                '%s' % ve])
371 f3e94e06 Stavros Sachtouris
372 234954d1 Stavros Sachtouris
373 d486baec Stavros Sachtouris
@command(server_cmds)
374 60c42f9f Stavros Sachtouris
class server_create(_init_cyclades, _optional_json, _server_wait):
375 56d84a4e Stavros Sachtouris
    """Create a server (aka Virtual Machine)"""
376 7493ccb6 Stavros Sachtouris
377 93914390 Stavros Sachtouris
    arguments = dict(
378 56d84a4e Stavros Sachtouris
        server_name=ValueArgument('The name of the new server', '--name'),
379 56d84a4e Stavros Sachtouris
        flavor_id=IntArgument('The ID of the hardware flavor', '--flavor-id'),
380 56d84a4e Stavros Sachtouris
        image_id=IntArgument('The ID of the hardware image', '--image-id'),
381 93914390 Stavros Sachtouris
        personality=PersonalityArgument(
382 60c42f9f Stavros Sachtouris
            (80 * ' ').join(howto_personality), ('-p', '--personality')),
383 81c60832 Stavros Sachtouris
        wait=FlagArgument('Wait server to build', ('-w', '--wait')),
384 81c60832 Stavros Sachtouris
        cluster_size=IntArgument(
385 81c60832 Stavros Sachtouris
            'Create a cluster of servers of this size. In this case, the name'
386 81c60832 Stavros Sachtouris
            'parameter is the prefix of each server in the cluster (e.g.,'
387 81c60832 Stavros Sachtouris
            'srv1, srv2, etc.',
388 81c60832 Stavros Sachtouris
            '--cluster-size')
389 93914390 Stavros Sachtouris
    )
390 56d84a4e Stavros Sachtouris
    required = ('server_name', 'flavor_id', 'image_id')
391 f3e94e06 Stavros Sachtouris
392 81c60832 Stavros Sachtouris
    @errors.cyclades.cluster_size
393 81c60832 Stavros Sachtouris
    def _create_cluster(self, prefix, flavor_id, image_id, size):
394 81c60832 Stavros Sachtouris
        servers = [dict(
395 6c068db6 Stavros Sachtouris
            name='%s%s' % (prefix, i if size > 1 else ''),
396 81c60832 Stavros Sachtouris
            flavor_id=flavor_id,
397 81c60832 Stavros Sachtouris
            image_id=image_id,
398 40ddc207 Stavros Sachtouris
            personality=self['personality']) for i in range(1, 1 + size)]
399 81c60832 Stavros Sachtouris
        if size == 1:
400 81c60832 Stavros Sachtouris
            return [self.client.create_server(**servers[0])]
401 c2e8d493 Stavros Sachtouris
        try:
402 40ddc207 Stavros Sachtouris
            r = self.client.async_run(self.client.create_server, servers)
403 40ddc207 Stavros Sachtouris
            return r
404 c2e8d493 Stavros Sachtouris
        except Exception as e:
405 c2e8d493 Stavros Sachtouris
            if size == 1:
406 c2e8d493 Stavros Sachtouris
                raise e
407 c2e8d493 Stavros Sachtouris
            try:
408 c2e8d493 Stavros Sachtouris
                requested_names = [s['name'] for s in servers]
409 c2e8d493 Stavros Sachtouris
                spawned_servers = [dict(
410 c2e8d493 Stavros Sachtouris
                    name=s['name'],
411 c2e8d493 Stavros Sachtouris
                    id=s['id']) for s in self.client.list_servers() if (
412 c2e8d493 Stavros Sachtouris
                        s['name'] in requested_names)]
413 c2e8d493 Stavros Sachtouris
                self.error('Failed to build %s servers' % size)
414 40ddc207 Stavros Sachtouris
                self.error('Found %s matching servers:' % len(spawned_servers))
415 c2e8d493 Stavros Sachtouris
                self._print(spawned_servers, out=self._err)
416 c2e8d493 Stavros Sachtouris
                self.error('Check if any of these servers should be removed\n')
417 c2e8d493 Stavros Sachtouris
            except Exception as ne:
418 c2e8d493 Stavros Sachtouris
                self.error('Error (%s) while notifying about errors' % ne)
419 c2e8d493 Stavros Sachtouris
            finally:
420 c2e8d493 Stavros Sachtouris
                raise e
421 81c60832 Stavros Sachtouris
422 b04288f7 Stavros Sachtouris
    @errors.generic.all
423 b04288f7 Stavros Sachtouris
    @errors.cyclades.connection
424 b04288f7 Stavros Sachtouris
    @errors.plankton.id
425 b04288f7 Stavros Sachtouris
    @errors.cyclades.flavor_id
426 b04288f7 Stavros Sachtouris
    def _run(self, name, flavor_id, image_id):
427 81c60832 Stavros Sachtouris
        for r in self._create_cluster(
428 81c60832 Stavros Sachtouris
                name, flavor_id, image_id, size=self['cluster_size'] or 1):
429 c2e8d493 Stavros Sachtouris
            if not r:
430 c2e8d493 Stavros Sachtouris
                self.error('Create %s: server response was %s' % (name, r))
431 c2e8d493 Stavros Sachtouris
                continue
432 c2e8d493 Stavros Sachtouris
            usernames = self._uuids2usernames(
433 c2e8d493 Stavros Sachtouris
                [r['user_id'], r['tenant_id']])
434 81c60832 Stavros Sachtouris
            r['user_id'] += ' (%s)' % usernames[r['user_id']]
435 81c60832 Stavros Sachtouris
            r['tenant_id'] += ' (%s)' % usernames[r['tenant_id']]
436 81c60832 Stavros Sachtouris
            self._print(r, self.print_dict)
437 81c60832 Stavros Sachtouris
            if self['wait']:
438 81c60832 Stavros Sachtouris
                self._wait(r['id'], r['status'])
439 40ddc207 Stavros Sachtouris
            self.writeln(' ')
440 b04288f7 Stavros Sachtouris
441 56d84a4e Stavros Sachtouris
    def main(self):
442 b04288f7 Stavros Sachtouris
        super(self.__class__, self)._run()
443 56d84a4e Stavros Sachtouris
        self._run(
444 56d84a4e Stavros Sachtouris
            name=self['server_name'],
445 56d84a4e Stavros Sachtouris
            flavor_id=self['flavor_id'],
446 56d84a4e Stavros Sachtouris
            image_id=self['image_id'])
447 7493ccb6 Stavros Sachtouris
448 234954d1 Stavros Sachtouris
449 d486baec Stavros Sachtouris
@command(server_cmds)
450 56d84a4e Stavros Sachtouris
class server_modify(_init_cyclades, _optional_output_cmd):
451 56d84a4e Stavros Sachtouris
    """Modify attributes of a virtual server"""
452 56d84a4e Stavros Sachtouris
453 56d84a4e Stavros Sachtouris
    arguments = dict(
454 56d84a4e Stavros Sachtouris
        server_name=ValueArgument('The new name', '--name'),
455 56d84a4e Stavros Sachtouris
        flavor_id=IntArgument('Set a different flavor', '--flavor-id'),
456 56d84a4e Stavros Sachtouris
    )
457 56d84a4e Stavros Sachtouris
    required = ['server_name', 'flavor_id']
458 7493ccb6 Stavros Sachtouris
459 5a673575 Stavros Sachtouris
    @errors.generic.all
460 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
461 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
462 56d84a4e Stavros Sachtouris
    def _run(self, server_id):
463 56d84a4e Stavros Sachtouris
        if self['server_name']:
464 56d84a4e Stavros Sachtouris
            self.client.update_server_name((server_id), self['server_name'])
465 56d84a4e Stavros Sachtouris
        if self['flavor_id']:
466 56d84a4e Stavros Sachtouris
            self.client.resize_server(server_id, self['flavor_id'])
467 56d84a4e Stavros Sachtouris
        if self['with_output']:
468 56d84a4e Stavros Sachtouris
            self._optional_output(self.client.get_server_details(server_id))
469 5a673575 Stavros Sachtouris
470 56d84a4e Stavros Sachtouris
    def main(self, server_id):
471 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
472 56d84a4e Stavros Sachtouris
        self._run(server_id=server_id)
473 234954d1 Stavros Sachtouris
474 7493ccb6 Stavros Sachtouris
475 d486baec Stavros Sachtouris
@command(server_cmds)
476 60c42f9f Stavros Sachtouris
class server_delete(_init_cyclades, _optional_output_cmd, _server_wait):
477 2bd23362 Stavros Sachtouris
    """Delete a virtual server"""
478 7493ccb6 Stavros Sachtouris
479 60c42f9f Stavros Sachtouris
    arguments = dict(
480 81c60832 Stavros Sachtouris
        wait=FlagArgument('Wait server to be destroyed', ('-w', '--wait')),
481 81c60832 Stavros Sachtouris
        cluster=FlagArgument(
482 81c60832 Stavros Sachtouris
            '(DANGEROUS) Delete all virtual servers prefixed with the cluster '
483 81c60832 Stavros Sachtouris
            'prefix. In that case, the prefix replaces the server id',
484 81c60832 Stavros Sachtouris
            '--cluster')
485 60c42f9f Stavros Sachtouris
    )
486 60c42f9f Stavros Sachtouris
487 81c60832 Stavros Sachtouris
    def _server_ids(self, server_var):
488 81c60832 Stavros Sachtouris
        if self['cluster']:
489 81c60832 Stavros Sachtouris
            return [s['id'] for s in self.client.list_servers() if (
490 81c60832 Stavros Sachtouris
                s['name'].startswith(server_var))]
491 81c60832 Stavros Sachtouris
492 81c60832 Stavros Sachtouris
        @errors.cyclades.server_id
493 81c60832 Stavros Sachtouris
        def _check_server_id(self, server_id):
494 81c60832 Stavros Sachtouris
            return server_id
495 81c60832 Stavros Sachtouris
496 81c60832 Stavros Sachtouris
        return [_check_server_id(self, server_id=server_var), ]
497 81c60832 Stavros Sachtouris
498 5a673575 Stavros Sachtouris
    @errors.generic.all
499 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
500 81c60832 Stavros Sachtouris
    def _run(self, server_var):
501 81c60832 Stavros Sachtouris
        for server_id in self._server_ids(server_var):
502 60c42f9f Stavros Sachtouris
            if self['wait']:
503 60c42f9f Stavros Sachtouris
                details = self.client.get_server_details(server_id)
504 60c42f9f Stavros Sachtouris
                status = details['status']
505 60c42f9f Stavros Sachtouris
506 81c60832 Stavros Sachtouris
            r = self.client.delete_server(server_id)
507 60c42f9f Stavros Sachtouris
            self._optional_output(r)
508 60c42f9f Stavros Sachtouris
509 60c42f9f Stavros Sachtouris
            if self['wait']:
510 60c42f9f Stavros Sachtouris
                self._wait(server_id, status)
511 5a673575 Stavros Sachtouris
512 81c60832 Stavros Sachtouris
    def main(self, server_id_or_cluster_prefix):
513 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
514 81c60832 Stavros Sachtouris
        self._run(server_id_or_cluster_prefix)
515 234954d1 Stavros Sachtouris
516 7493ccb6 Stavros Sachtouris
517 d486baec Stavros Sachtouris
@command(server_cmds)
518 60c42f9f Stavros Sachtouris
class server_reboot(_init_cyclades, _optional_output_cmd, _server_wait):
519 2bd23362 Stavros Sachtouris
    """Reboot a virtual server"""
520 18edacfe Stavros Sachtouris
521 93914390 Stavros Sachtouris
    arguments = dict(
522 a1dc95ac Stavros Sachtouris
        hard=FlagArgument(
523 a1dc95ac Stavros Sachtouris
            'perform a hard reboot (deprecated)', ('-f', '--force')),
524 a1dc95ac Stavros Sachtouris
        type=ValueArgument('SOFT or HARD - default: SOFT', ('--type')),
525 60c42f9f Stavros Sachtouris
        wait=FlagArgument('Wait server to be destroyed', ('-w', '--wait'))
526 93914390 Stavros Sachtouris
    )
527 7493ccb6 Stavros Sachtouris
528 5a673575 Stavros Sachtouris
    @errors.generic.all
529 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
530 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
531 5a673575 Stavros Sachtouris
    def _run(self, server_id):
532 a1dc95ac Stavros Sachtouris
        hard_reboot = self['hard']
533 a1dc95ac Stavros Sachtouris
        if hard_reboot:
534 a1dc95ac Stavros Sachtouris
            self.error(
535 a1dc95ac Stavros Sachtouris
                'WARNING: -f/--force will be deprecated in version 0.12\n'
536 a1dc95ac Stavros Sachtouris
                '\tIn the future, please use --type=hard instead')
537 a1dc95ac Stavros Sachtouris
        if self['type']:
538 a1dc95ac Stavros Sachtouris
            if self['type'].lower() in ('soft', ):
539 a1dc95ac Stavros Sachtouris
                hard_reboot = False
540 a1dc95ac Stavros Sachtouris
            elif self['type'].lower() in ('hard', ):
541 a1dc95ac Stavros Sachtouris
                hard_reboot = True
542 a1dc95ac Stavros Sachtouris
            else:
543 a1dc95ac Stavros Sachtouris
                raise CLISyntaxError(
544 a1dc95ac Stavros Sachtouris
                    'Invalid reboot type %s' % self['type'],
545 a1dc95ac Stavros Sachtouris
                    importance=2, details=[
546 a1dc95ac Stavros Sachtouris
                        '--type values are either SOFT (default) or HARD'])
547 a1dc95ac Stavros Sachtouris
548 a1dc95ac Stavros Sachtouris
        r = self.client.reboot_server(int(server_id), hard_reboot)
549 60c42f9f Stavros Sachtouris
        self._optional_output(r)
550 60c42f9f Stavros Sachtouris
551 60c42f9f Stavros Sachtouris
        if self['wait']:
552 60c42f9f Stavros Sachtouris
            self._wait(server_id, 'REBOOT')
553 5a673575 Stavros Sachtouris
554 7493ccb6 Stavros Sachtouris
    def main(self, server_id):
555 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
556 5a673575 Stavros Sachtouris
        self._run(server_id=server_id)
557 234954d1 Stavros Sachtouris
558 7493ccb6 Stavros Sachtouris
559 d486baec Stavros Sachtouris
@command(server_cmds)
560 60c42f9f Stavros Sachtouris
class server_start(_init_cyclades, _optional_output_cmd, _server_wait):
561 2bd23362 Stavros Sachtouris
    """Start an existing virtual server"""
562 7493ccb6 Stavros Sachtouris
563 60c42f9f Stavros Sachtouris
    arguments = dict(
564 60c42f9f Stavros Sachtouris
        wait=FlagArgument('Wait server to be destroyed', ('-w', '--wait'))
565 60c42f9f Stavros Sachtouris
    )
566 60c42f9f Stavros Sachtouris
567 5a673575 Stavros Sachtouris
    @errors.generic.all
568 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
569 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
570 5a673575 Stavros Sachtouris
    def _run(self, server_id):
571 60c42f9f Stavros Sachtouris
        status = 'ACTIVE'
572 60c42f9f Stavros Sachtouris
        if self['wait']:
573 60c42f9f Stavros Sachtouris
            details = self.client.get_server_details(server_id)
574 60c42f9f Stavros Sachtouris
            status = details['status']
575 60c42f9f Stavros Sachtouris
            if status in ('ACTIVE', ):
576 60c42f9f Stavros Sachtouris
                return
577 60c42f9f Stavros Sachtouris
578 60c42f9f Stavros Sachtouris
        r = self.client.start_server(int(server_id))
579 60c42f9f Stavros Sachtouris
        self._optional_output(r)
580 60c42f9f Stavros Sachtouris
581 60c42f9f Stavros Sachtouris
        if self['wait']:
582 60c42f9f Stavros Sachtouris
            self._wait(server_id, status)
583 5a673575 Stavros Sachtouris
584 7493ccb6 Stavros Sachtouris
    def main(self, server_id):
585 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
586 5a673575 Stavros Sachtouris
        self._run(server_id=server_id)
587 234954d1 Stavros Sachtouris
588 7493ccb6 Stavros Sachtouris
589 d486baec Stavros Sachtouris
@command(server_cmds)
590 60c42f9f Stavros Sachtouris
class server_shutdown(_init_cyclades, _optional_output_cmd, _server_wait):
591 2bd23362 Stavros Sachtouris
    """Shutdown an active virtual server"""
592 7493ccb6 Stavros Sachtouris
593 60c42f9f Stavros Sachtouris
    arguments = dict(
594 60c42f9f Stavros Sachtouris
        wait=FlagArgument('Wait server to be destroyed', ('-w', '--wait'))
595 60c42f9f Stavros Sachtouris
    )
596 60c42f9f Stavros Sachtouris
597 5a673575 Stavros Sachtouris
    @errors.generic.all
598 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
599 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
600 5a673575 Stavros Sachtouris
    def _run(self, server_id):
601 60c42f9f Stavros Sachtouris
        status = 'STOPPED'
602 60c42f9f Stavros Sachtouris
        if self['wait']:
603 60c42f9f Stavros Sachtouris
            details = self.client.get_server_details(server_id)
604 60c42f9f Stavros Sachtouris
            status = details['status']
605 60c42f9f Stavros Sachtouris
            if status in ('STOPPED', ):
606 60c42f9f Stavros Sachtouris
                return
607 60c42f9f Stavros Sachtouris
608 60c42f9f Stavros Sachtouris
        r = self.client.shutdown_server(int(server_id))
609 60c42f9f Stavros Sachtouris
        self._optional_output(r)
610 60c42f9f Stavros Sachtouris
611 60c42f9f Stavros Sachtouris
        if self['wait']:
612 60c42f9f Stavros Sachtouris
            self._wait(server_id, status)
613 5a673575 Stavros Sachtouris
614 7493ccb6 Stavros Sachtouris
    def main(self, server_id):
615 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
616 5a673575 Stavros Sachtouris
        self._run(server_id=server_id)
617 234954d1 Stavros Sachtouris
618 7493ccb6 Stavros Sachtouris
619 d486baec Stavros Sachtouris
@command(server_cmds)
620 545c6c29 Stavros Sachtouris
class server_console(_init_cyclades, _optional_json):
621 2bd23362 Stavros Sachtouris
    """Get a VNC console to access an existing virtual server
622 22b6f063 Stavros Sachtouris
    Console connection information provided (at least):
623 439826ec Stavros Sachtouris
    - host: (url or address) a VNC host
624 2bd23362 Stavros Sachtouris
    - port: (int) the gateway to enter virtual server on host
625 439826ec Stavros Sachtouris
    - password: for VNC authorization
626 22b6f063 Stavros Sachtouris
    """
627 7493ccb6 Stavros Sachtouris
628 5a673575 Stavros Sachtouris
    @errors.generic.all
629 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
630 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
631 5a673575 Stavros Sachtouris
    def _run(self, server_id):
632 bcef3ac9 Stavros Sachtouris
        self._print(
633 76f58e2e Stavros Sachtouris
            self.client.get_server_console(int(server_id)), self.print_dict)
634 5a673575 Stavros Sachtouris
635 7493ccb6 Stavros Sachtouris
    def main(self, server_id):
636 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
637 5a673575 Stavros Sachtouris
        self._run(server_id=server_id)
638 7493ccb6 Stavros Sachtouris
639 234954d1 Stavros Sachtouris
640 d486baec Stavros Sachtouris
@command(server_cmds)
641 7493ccb6 Stavros Sachtouris
class server_firewall(_init_cyclades):
642 2bd23362 Stavros Sachtouris
    """Manage virtual server firewall profiles for public networks"""
643 cd295a1d Stavros Sachtouris
644 cd295a1d Stavros Sachtouris
645 cd295a1d Stavros Sachtouris
@command(server_cmds)
646 c788a761 Stavros Sachtouris
class server_firewall_set(
647 c788a761 Stavros Sachtouris
        _init_cyclades, _optional_output_cmd, _firewall_wait):
648 2bd23362 Stavros Sachtouris
    """Set the firewall profile on virtual server public network
649 22b6f063 Stavros Sachtouris
    Values for profile:
650 439826ec Stavros Sachtouris
    - DISABLED: Shutdown firewall
651 439826ec Stavros Sachtouris
    - ENABLED: Firewall in normal mode
652 439826ec Stavros Sachtouris
    - PROTECTED: Firewall in secure mode
653 22b6f063 Stavros Sachtouris
    """
654 7493ccb6 Stavros Sachtouris
655 c788a761 Stavros Sachtouris
    arguments = dict(
656 c788a761 Stavros Sachtouris
        wait=FlagArgument('Wait server firewall to build', ('-w', '--wait')),
657 c788a761 Stavros Sachtouris
        timeout=IntArgument(
658 c788a761 Stavros Sachtouris
            'Set wait timeout in seconds (default: 60)', '--timeout',
659 c788a761 Stavros Sachtouris
            default=60)
660 c788a761 Stavros Sachtouris
    )
661 c788a761 Stavros Sachtouris
662 5a673575 Stavros Sachtouris
    @errors.generic.all
663 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
664 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
665 5a673575 Stavros Sachtouris
    @errors.cyclades.firewall
666 5a673575 Stavros Sachtouris
    def _run(self, server_id, profile):
667 c788a761 Stavros Sachtouris
        if self['timeout'] and not self['wait']:
668 c788a761 Stavros Sachtouris
            raise CLIInvalidArgument('Invalid use of --timeout', details=[
669 c788a761 Stavros Sachtouris
                'Timeout is used only along with -w/--wait'])
670 c788a761 Stavros Sachtouris
        old_profile = self.client.get_firewall_profile(server_id)
671 c788a761 Stavros Sachtouris
        if old_profile.lower() == profile.lower():
672 c788a761 Stavros Sachtouris
            self.error('Firewall of server %s: allready in status %s' % (
673 c788a761 Stavros Sachtouris
                server_id, old_profile))
674 c788a761 Stavros Sachtouris
        else:
675 c788a761 Stavros Sachtouris
            self._optional_output(self.client.set_firewall_profile(
676 c788a761 Stavros Sachtouris
                server_id=int(server_id), profile=('%s' % profile).upper()))
677 c788a761 Stavros Sachtouris
            if self['wait']:
678 c788a761 Stavros Sachtouris
                self._wait(server_id, old_profile, timeout=self['timeout'])
679 5a673575 Stavros Sachtouris
680 7493ccb6 Stavros Sachtouris
    def main(self, server_id, profile):
681 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
682 5a673575 Stavros Sachtouris
        self._run(server_id=server_id, profile=profile)
683 234954d1 Stavros Sachtouris
684 f3e94e06 Stavros Sachtouris
685 d486baec Stavros Sachtouris
@command(server_cmds)
686 cd295a1d Stavros Sachtouris
class server_firewall_get(_init_cyclades):
687 2bd23362 Stavros Sachtouris
    """Get the firewall profile for a virtual servers' public network"""
688 cd295a1d Stavros Sachtouris
689 cd295a1d Stavros Sachtouris
    @errors.generic.all
690 cd295a1d Stavros Sachtouris
    @errors.cyclades.connection
691 cd295a1d Stavros Sachtouris
    @errors.cyclades.server_id
692 cd295a1d Stavros Sachtouris
    def _run(self, server_id):
693 3185cd6d Stavros Sachtouris
        self.writeln(self.client.get_firewall_profile(server_id))
694 cd295a1d Stavros Sachtouris
695 cd295a1d Stavros Sachtouris
    def main(self, server_id):
696 cd295a1d Stavros Sachtouris
        super(self.__class__, self)._run()
697 cd295a1d Stavros Sachtouris
        self._run(server_id=server_id)
698 cd295a1d Stavros Sachtouris
699 cd295a1d Stavros Sachtouris
700 cd295a1d Stavros Sachtouris
@command(server_cmds)
701 545c6c29 Stavros Sachtouris
class server_addr(_init_cyclades, _optional_json):
702 2bd23362 Stavros Sachtouris
    """List the addresses of all network interfaces on a virtual server"""
703 7493ccb6 Stavros Sachtouris
704 cd295a1d Stavros Sachtouris
    arguments = dict(
705 545c6c29 Stavros Sachtouris
        enum=FlagArgument('Enumerate results', '--enumerate')
706 cd295a1d Stavros Sachtouris
    )
707 cd295a1d Stavros Sachtouris
708 5a673575 Stavros Sachtouris
    @errors.generic.all
709 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
710 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
711 5a673575 Stavros Sachtouris
    def _run(self, server_id):
712 5a673575 Stavros Sachtouris
        reply = self.client.list_server_nics(int(server_id))
713 3185cd6d Stavros Sachtouris
        self._print(reply, with_enumeration=self['enum'] and (reply) > 1)
714 7493ccb6 Stavros Sachtouris
715 5a673575 Stavros Sachtouris
    def main(self, server_id):
716 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
717 5a673575 Stavros Sachtouris
        self._run(server_id=server_id)
718 5a673575 Stavros Sachtouris
719 234954d1 Stavros Sachtouris
720 d486baec Stavros Sachtouris
@command(server_cmds)
721 cd295a1d Stavros Sachtouris
class server_metadata(_init_cyclades):
722 cd295a1d Stavros Sachtouris
    """Manage Server metadata (key:value pairs of server attributes)"""
723 cd295a1d Stavros Sachtouris
724 cd295a1d Stavros Sachtouris
725 cd295a1d Stavros Sachtouris
@command(server_cmds)
726 545c6c29 Stavros Sachtouris
class server_metadata_list(_init_cyclades, _optional_json):
727 cd295a1d Stavros Sachtouris
    """Get server metadata"""
728 7493ccb6 Stavros Sachtouris
729 5a673575 Stavros Sachtouris
    @errors.generic.all
730 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
731 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
732 5a673575 Stavros Sachtouris
    @errors.cyclades.metadata
733 5a673575 Stavros Sachtouris
    def _run(self, server_id, key=''):
734 545c6c29 Stavros Sachtouris
        self._print(
735 76f58e2e Stavros Sachtouris
            self.client.get_server_metadata(int(server_id), key),
736 76f58e2e Stavros Sachtouris
            self.print_dict)
737 5a673575 Stavros Sachtouris
738 a34888b4 Stavros Sachtouris
    def main(self, server_id, key=''):
739 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
740 5a673575 Stavros Sachtouris
        self._run(server_id=server_id, key=key)
741 7493ccb6 Stavros Sachtouris
742 234954d1 Stavros Sachtouris
743 d486baec Stavros Sachtouris
@command(server_cmds)
744 545c6c29 Stavros Sachtouris
class server_metadata_set(_init_cyclades, _optional_json):
745 2bd23362 Stavros Sachtouris
    """Set / update virtual server metadata
746 cd295a1d Stavros Sachtouris
    Metadata should be given in key/value pairs in key=value format
747 9dc6159f Stavros Sachtouris
    For example: /server metadata set <server id> key1=value1 key2=value2
748 cd295a1d Stavros Sachtouris
    Old, unreferenced metadata will remain intact
749 22b6f063 Stavros Sachtouris
    """
750 7493ccb6 Stavros Sachtouris
751 5a673575 Stavros Sachtouris
    @errors.generic.all
752 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
753 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
754 cd295a1d Stavros Sachtouris
    def _run(self, server_id, keyvals):
755 545c6c29 Stavros Sachtouris
        assert keyvals, 'Please, add some metadata ( key=value)'
756 cd295a1d Stavros Sachtouris
        metadata = dict()
757 cd295a1d Stavros Sachtouris
        for keyval in keyvals:
758 cd295a1d Stavros Sachtouris
            k, sep, v = keyval.partition('=')
759 cd295a1d Stavros Sachtouris
            if sep and k:
760 cd295a1d Stavros Sachtouris
                metadata[k] = v
761 cd295a1d Stavros Sachtouris
            else:
762 cd295a1d Stavros Sachtouris
                raiseCLIError(
763 cd295a1d Stavros Sachtouris
                    'Invalid piece of metadata %s' % keyval,
764 cd295a1d Stavros Sachtouris
                    importance=2, details=[
765 cd295a1d Stavros Sachtouris
                        'Correct metadata format: key=val',
766 cd295a1d Stavros Sachtouris
                        'For example:',
767 cd295a1d Stavros Sachtouris
                        '/server metadata set <server id>'
768 cd295a1d Stavros Sachtouris
                        'key1=value1 key2=value2'])
769 545c6c29 Stavros Sachtouris
        self._print(
770 bcef3ac9 Stavros Sachtouris
            self.client.update_server_metadata(int(server_id), **metadata),
771 76f58e2e Stavros Sachtouris
            self.print_dict)
772 cd295a1d Stavros Sachtouris
773 cd295a1d Stavros Sachtouris
    def main(self, server_id, *key_equals_val):
774 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
775 cd295a1d Stavros Sachtouris
        self._run(server_id=server_id, keyvals=key_equals_val)
776 7493ccb6 Stavros Sachtouris
777 234954d1 Stavros Sachtouris
778 d486baec Stavros Sachtouris
@command(server_cmds)
779 cd295a1d Stavros Sachtouris
class server_metadata_delete(_init_cyclades, _optional_output_cmd):
780 2bd23362 Stavros Sachtouris
    """Delete virtual server metadata"""
781 7493ccb6 Stavros Sachtouris
782 5a673575 Stavros Sachtouris
    @errors.generic.all
783 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
784 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
785 5a673575 Stavros Sachtouris
    @errors.cyclades.metadata
786 5a673575 Stavros Sachtouris
    def _run(self, server_id, key):
787 cd295a1d Stavros Sachtouris
        self._optional_output(
788 cd295a1d Stavros Sachtouris
            self.client.delete_server_metadata(int(server_id), key))
789 5a673575 Stavros Sachtouris
790 7493ccb6 Stavros Sachtouris
    def main(self, server_id, key):
791 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
792 5a673575 Stavros Sachtouris
        self._run(server_id=server_id, key=key)
793 234954d1 Stavros Sachtouris
794 7493ccb6 Stavros Sachtouris
795 d486baec Stavros Sachtouris
@command(server_cmds)
796 545c6c29 Stavros Sachtouris
class server_stats(_init_cyclades, _optional_json):
797 2bd23362 Stavros Sachtouris
    """Get virtual server statistics"""
798 7493ccb6 Stavros Sachtouris
799 5a673575 Stavros Sachtouris
    @errors.generic.all
800 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
801 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
802 5a673575 Stavros Sachtouris
    def _run(self, server_id):
803 76f58e2e Stavros Sachtouris
        self._print(
804 76f58e2e Stavros Sachtouris
            self.client.get_server_stats(int(server_id)), self.print_dict)
805 5a673575 Stavros Sachtouris
806 7493ccb6 Stavros Sachtouris
    def main(self, server_id):
807 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
808 5a673575 Stavros Sachtouris
        self._run(server_id=server_id)
809 7493ccb6 Stavros Sachtouris
810 234954d1 Stavros Sachtouris
811 d486baec Stavros Sachtouris
@command(server_cmds)
812 60c42f9f Stavros Sachtouris
class server_wait(_init_cyclades, _server_wait):
813 fd1f1d96 Stavros Sachtouris
    """Wait for server to finish [BUILD, STOPPED, REBOOT, ACTIVE]"""
814 fd1f1d96 Stavros Sachtouris
815 8547cd19 Stavros Sachtouris
    arguments = dict(
816 8547cd19 Stavros Sachtouris
        timeout=IntArgument(
817 8547cd19 Stavros Sachtouris
            'Wait limit in seconds (default: 60)', '--timeout', default=60)
818 8547cd19 Stavros Sachtouris
    )
819 8547cd19 Stavros Sachtouris
820 5a673575 Stavros Sachtouris
    @errors.generic.all
821 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
822 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
823 e9c73313 Stavros Sachtouris
    def _run(self, server_id, current_status):
824 e9c73313 Stavros Sachtouris
        r = self.client.get_server_details(server_id)
825 e9c73313 Stavros Sachtouris
        if r['status'].lower() == current_status.lower():
826 8547cd19 Stavros Sachtouris
            self._wait(server_id, current_status, timeout=self['timeout'])
827 e9c73313 Stavros Sachtouris
        else:
828 e9c73313 Stavros Sachtouris
            self.error(
829 e9c73313 Stavros Sachtouris
                'Server %s: Cannot wait for status %s, '
830 e9c73313 Stavros Sachtouris
                'status is already %s' % (
831 e9c73313 Stavros Sachtouris
                    server_id, current_status, r['status']))
832 fd1f1d96 Stavros Sachtouris
833 e9c73313 Stavros Sachtouris
    def main(self, server_id, current_status='BUILD'):
834 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
835 e9c73313 Stavros Sachtouris
        self._run(server_id=server_id, current_status=current_status)
836 5a673575 Stavros Sachtouris
837 fd1f1d96 Stavros Sachtouris
838 d486baec Stavros Sachtouris
@command(flavor_cmds)
839 6d190dd1 Stavros Sachtouris
class flavor_list(_init_cyclades, _optional_json, _name_filter, _id_filter):
840 bd40efdf Stavros Sachtouris
    """List available hardware flavors"""
841 7493ccb6 Stavros Sachtouris
842 d8ff7b56 Stavros Sachtouris
    PERMANENTS = ('id', 'name')
843 d8ff7b56 Stavros Sachtouris
844 93914390 Stavros Sachtouris
    arguments = dict(
845 f40f0cb7 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
846 f40f0cb7 Stavros Sachtouris
        limit=IntArgument('limit # of listed flavors', ('-n', '--number')),
847 bd40efdf Stavros Sachtouris
        more=FlagArgument(
848 de73876b Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
849 ed9af02c Stavros Sachtouris
            '--more'),
850 d8ff7b56 Stavros Sachtouris
        enum=FlagArgument('Enumerate results', '--enumerate'),
851 d8ff7b56 Stavros Sachtouris
        ram=ValueArgument('filter by ram', ('--ram')),
852 d8ff7b56 Stavros Sachtouris
        vcpus=ValueArgument('filter by number of VCPUs', ('--vcpus')),
853 d8ff7b56 Stavros Sachtouris
        disk=ValueArgument('filter by disk size in GB', ('--disk')),
854 d8ff7b56 Stavros Sachtouris
        disk_template=ValueArgument(
855 d8ff7b56 Stavros Sachtouris
            'filter by disk_templace', ('--disk-template'))
856 93914390 Stavros Sachtouris
    )
857 7493ccb6 Stavros Sachtouris
858 d8ff7b56 Stavros Sachtouris
    def _apply_common_filters(self, flavors):
859 d8ff7b56 Stavros Sachtouris
        common_filters = dict()
860 d8ff7b56 Stavros Sachtouris
        if self['ram']:
861 d8ff7b56 Stavros Sachtouris
            common_filters['ram'] = self['ram']
862 d8ff7b56 Stavros Sachtouris
        if self['vcpus']:
863 d8ff7b56 Stavros Sachtouris
            common_filters['vcpus'] = self['vcpus']
864 d8ff7b56 Stavros Sachtouris
        if self['disk']:
865 d8ff7b56 Stavros Sachtouris
            common_filters['disk'] = self['disk']
866 d8ff7b56 Stavros Sachtouris
        if self['disk_template']:
867 d8ff7b56 Stavros Sachtouris
            common_filters['SNF:disk_template'] = self['disk_template']
868 d8ff7b56 Stavros Sachtouris
        return filter_dicts_by_dict(flavors, common_filters)
869 d8ff7b56 Stavros Sachtouris
870 5a673575 Stavros Sachtouris
    @errors.generic.all
871 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
872 5a673575 Stavros Sachtouris
    def _run(self):
873 d8ff7b56 Stavros Sachtouris
        withcommons = self['ram'] or self['vcpus'] or (
874 d8ff7b56 Stavros Sachtouris
            self['disk'] or self['disk_template'])
875 d8ff7b56 Stavros Sachtouris
        detail = self['detail'] or withcommons
876 d8ff7b56 Stavros Sachtouris
        flavors = self.client.list_flavors(detail)
877 6d190dd1 Stavros Sachtouris
        flavors = self._filter_by_name(flavors)
878 6d190dd1 Stavros Sachtouris
        flavors = self._filter_by_id(flavors)
879 d8ff7b56 Stavros Sachtouris
        if withcommons:
880 d8ff7b56 Stavros Sachtouris
            flavors = self._apply_common_filters(flavors)
881 f76c6bbc Stavros Sachtouris
        if not (self['detail'] or (
882 f76c6bbc Stavros Sachtouris
                self['json_output'] or self['output_format'])):
883 7ba195e5 Stavros Sachtouris
            remove_from_items(flavors, 'links')
884 d8ff7b56 Stavros Sachtouris
        if detail and not self['detail']:
885 d8ff7b56 Stavros Sachtouris
            for flv in flavors:
886 d8ff7b56 Stavros Sachtouris
                for key in set(flv).difference(self.PERMANENTS):
887 d8ff7b56 Stavros Sachtouris
                    flv.pop(key)
888 6430d3a0 Stavros Sachtouris
        kwargs = dict(out=StringIO(), title=()) if self['more'] else {}
889 545c6c29 Stavros Sachtouris
        self._print(
890 ed9af02c Stavros Sachtouris
            flavors,
891 6430d3a0 Stavros Sachtouris
            with_redundancy=self['detail'], with_enumeration=self['enum'],
892 6430d3a0 Stavros Sachtouris
            **kwargs)
893 6430d3a0 Stavros Sachtouris
        if self['more']:
894 6430d3a0 Stavros Sachtouris
            pager(kwargs['out'].getvalue())
895 5a673575 Stavros Sachtouris
896 7493ccb6 Stavros Sachtouris
    def main(self):
897 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
898 5a673575 Stavros Sachtouris
        self._run()
899 7493ccb6 Stavros Sachtouris
900 234954d1 Stavros Sachtouris
901 d486baec Stavros Sachtouris
@command(flavor_cmds)
902 545c6c29 Stavros Sachtouris
class flavor_info(_init_cyclades, _optional_json):
903 769dbf53 Stavros Sachtouris
    """Detailed information on a hardware flavor
904 ddc0b290 Stavros Sachtouris
    To get a list of available flavors and flavor ids, try /flavor list
905 ddc0b290 Stavros Sachtouris
    """
906 7493ccb6 Stavros Sachtouris
907 5a673575 Stavros Sachtouris
    @errors.generic.all
908 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
909 5a673575 Stavros Sachtouris
    @errors.cyclades.flavor_id
910 5a673575 Stavros Sachtouris
    def _run(self, flavor_id):
911 bcef3ac9 Stavros Sachtouris
        self._print(
912 76f58e2e Stavros Sachtouris
            self.client.get_flavor_details(int(flavor_id)), self.print_dict)
913 7493ccb6 Stavros Sachtouris
914 5a673575 Stavros Sachtouris
    def main(self, flavor_id):
915 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
916 5a673575 Stavros Sachtouris
        self._run(flavor_id=flavor_id)
917 5a673575 Stavros Sachtouris
918 234954d1 Stavros Sachtouris
919 cf115aed Stavros Sachtouris
def _add_name(self, net):
920 cf115aed Stavros Sachtouris
        user_id, tenant_id, uuids = net['user_id'], net['tenant_id'], []
921 cf115aed Stavros Sachtouris
        if user_id:
922 cf115aed Stavros Sachtouris
            uuids.append(user_id)
923 cf115aed Stavros Sachtouris
        if tenant_id:
924 cf115aed Stavros Sachtouris
            uuids.append(tenant_id)
925 cf115aed Stavros Sachtouris
        if uuids:
926 cf115aed Stavros Sachtouris
            usernames = self._uuids2usernames(uuids)
927 cf115aed Stavros Sachtouris
            if user_id:
928 cf115aed Stavros Sachtouris
                net['user_id'] += ' (%s)' % usernames[user_id]
929 cf115aed Stavros Sachtouris
            if tenant_id:
930 cf115aed Stavros Sachtouris
                net['tenant_id'] += ' (%s)' % usernames[tenant_id]
931 cf115aed Stavros Sachtouris
932 cf115aed Stavros Sachtouris
933 d486baec Stavros Sachtouris
@command(network_cmds)
934 545c6c29 Stavros Sachtouris
class network_info(_init_cyclades, _optional_json):
935 ddc0b290 Stavros Sachtouris
    """Detailed information on a network
936 ddc0b290 Stavros Sachtouris
    To get a list of available networks and network ids, try /network list
937 ddc0b290 Stavros Sachtouris
    """
938 c17b8bc0 Stavros Sachtouris
939 5a673575 Stavros Sachtouris
    @errors.generic.all
940 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
941 5a673575 Stavros Sachtouris
    @errors.cyclades.network_id
942 5a673575 Stavros Sachtouris
    def _run(self, network_id):
943 5a673575 Stavros Sachtouris
        network = self.client.get_network_details(int(network_id))
944 cf115aed Stavros Sachtouris
        _add_name(self, network)
945 76f58e2e Stavros Sachtouris
        self._print(network, self.print_dict, exclude=('id'))
946 5a673575 Stavros Sachtouris
947 c17b8bc0 Stavros Sachtouris
    def main(self, network_id):
948 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
949 5a673575 Stavros Sachtouris
        self._run(network_id=network_id)
950 c17b8bc0 Stavros Sachtouris
951 c17b8bc0 Stavros Sachtouris
952 c17b8bc0 Stavros Sachtouris
@command(network_cmds)
953 6d190dd1 Stavros Sachtouris
class network_list(_init_cyclades, _optional_json, _name_filter, _id_filter):
954 7493ccb6 Stavros Sachtouris
    """List networks"""
955 7493ccb6 Stavros Sachtouris
956 c79faeb5 Stavros Sachtouris
    PERMANENTS = ('id', 'name')
957 c79faeb5 Stavros Sachtouris
958 93914390 Stavros Sachtouris
    arguments = dict(
959 f40f0cb7 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
960 f40f0cb7 Stavros Sachtouris
        limit=IntArgument('limit # of listed networks', ('-n', '--number')),
961 ddc0b290 Stavros Sachtouris
        more=FlagArgument(
962 ddc0b290 Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
963 ed9af02c Stavros Sachtouris
            '--more'),
964 c79faeb5 Stavros Sachtouris
        enum=FlagArgument('Enumerate results', '--enumerate'),
965 c79faeb5 Stavros Sachtouris
        status=ValueArgument('filter by status', ('--status')),
966 c79faeb5 Stavros Sachtouris
        public=FlagArgument('only public networks', ('--public')),
967 c79faeb5 Stavros Sachtouris
        private=FlagArgument('only private networks', ('--private')),
968 c79faeb5 Stavros Sachtouris
        dhcp=FlagArgument('show networks with dhcp', ('--with-dhcp')),
969 c79faeb5 Stavros Sachtouris
        no_dhcp=FlagArgument('show networks without dhcp', ('--without-dhcp')),
970 c79faeb5 Stavros Sachtouris
        user_id=ValueArgument('filter by user id', ('--user-id')),
971 c79faeb5 Stavros Sachtouris
        user_name=ValueArgument('filter by user name', ('--user-name')),
972 c79faeb5 Stavros Sachtouris
        gateway=ValueArgument('filter by gateway (IPv4)', ('--gateway')),
973 c79faeb5 Stavros Sachtouris
        gateway6=ValueArgument('filter by gateway (IPv6)', ('--gateway6')),
974 c79faeb5 Stavros Sachtouris
        cidr=ValueArgument('filter by cidr (IPv4)', ('--cidr')),
975 c79faeb5 Stavros Sachtouris
        cidr6=ValueArgument('filter by cidr (IPv6)', ('--cidr6')),
976 c79faeb5 Stavros Sachtouris
        type=ValueArgument('filter by type', ('--type')),
977 93914390 Stavros Sachtouris
    )
978 7493ccb6 Stavros Sachtouris
979 c79faeb5 Stavros Sachtouris
    def _apply_common_filters(self, networks):
980 c79faeb5 Stavros Sachtouris
        common_filter = dict()
981 c79faeb5 Stavros Sachtouris
        if self['public']:
982 c79faeb5 Stavros Sachtouris
            if self['private']:
983 c79faeb5 Stavros Sachtouris
                return []
984 c79faeb5 Stavros Sachtouris
            common_filter['public'] = self['public']
985 c79faeb5 Stavros Sachtouris
        elif self['private']:
986 c79faeb5 Stavros Sachtouris
            common_filter['public'] = False
987 c79faeb5 Stavros Sachtouris
        if self['dhcp']:
988 c79faeb5 Stavros Sachtouris
            if self['no_dhcp']:
989 c79faeb5 Stavros Sachtouris
                return []
990 c79faeb5 Stavros Sachtouris
            common_filter['dhcp'] = True
991 c79faeb5 Stavros Sachtouris
        elif self['no_dhcp']:
992 c79faeb5 Stavros Sachtouris
            common_filter['dhcp'] = False
993 c79faeb5 Stavros Sachtouris
        if self['user_id'] or self['user_name']:
994 c79faeb5 Stavros Sachtouris
            uuid = self['user_id'] or self._username2uuid(self['user_name'])
995 c79faeb5 Stavros Sachtouris
            common_filter['user_id'] = uuid
996 c79faeb5 Stavros Sachtouris
        for term in ('status', 'gateway', 'gateway6', 'cidr', 'cidr6', 'type'):
997 c79faeb5 Stavros Sachtouris
            if self[term]:
998 c79faeb5 Stavros Sachtouris
                common_filter[term] = self[term]
999 c79faeb5 Stavros Sachtouris
        return filter_dicts_by_dict(networks, common_filter)
1000 c79faeb5 Stavros Sachtouris
1001 c79faeb5 Stavros Sachtouris
    def _add_name(self, networks, key='user_id'):
1002 c79faeb5 Stavros Sachtouris
        uuids = self._uuids2usernames(
1003 c79faeb5 Stavros Sachtouris
            list(set([net[key] for net in networks])))
1004 c79faeb5 Stavros Sachtouris
        for net in networks:
1005 c79faeb5 Stavros Sachtouris
            v = net.get(key, None)
1006 c79faeb5 Stavros Sachtouris
            if v:
1007 3185cd6d Stavros Sachtouris
                net[key] += ' (%s)' % uuids[v]
1008 c79faeb5 Stavros Sachtouris
        return networks
1009 c79faeb5 Stavros Sachtouris
1010 5a673575 Stavros Sachtouris
    @errors.generic.all
1011 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
1012 5a673575 Stavros Sachtouris
    def _run(self):
1013 c79faeb5 Stavros Sachtouris
        withcommons = False
1014 c79faeb5 Stavros Sachtouris
        for term in (
1015 c79faeb5 Stavros Sachtouris
                'status', 'public', 'private', 'user_id', 'user_name', 'type',
1016 c79faeb5 Stavros Sachtouris
                'gateway', 'gateway6', 'cidr', 'cidr6', 'dhcp', 'no_dhcp'):
1017 c79faeb5 Stavros Sachtouris
            if self[term]:
1018 c79faeb5 Stavros Sachtouris
                withcommons = True
1019 c79faeb5 Stavros Sachtouris
                break
1020 c79faeb5 Stavros Sachtouris
        detail = self['detail'] or withcommons
1021 c79faeb5 Stavros Sachtouris
        networks = self.client.list_networks(detail)
1022 6d190dd1 Stavros Sachtouris
        networks = self._filter_by_name(networks)
1023 6d190dd1 Stavros Sachtouris
        networks = self._filter_by_id(networks)
1024 c79faeb5 Stavros Sachtouris
        if withcommons:
1025 c79faeb5 Stavros Sachtouris
            networks = self._apply_common_filters(networks)
1026 f76c6bbc Stavros Sachtouris
        if not (self['detail'] or (
1027 f76c6bbc Stavros Sachtouris
                self['json_output'] or self['output_format'])):
1028 7ba195e5 Stavros Sachtouris
            remove_from_items(networks, 'links')
1029 c79faeb5 Stavros Sachtouris
        if detail and not self['detail']:
1030 c79faeb5 Stavros Sachtouris
            for net in networks:
1031 c79faeb5 Stavros Sachtouris
                for key in set(net).difference(self.PERMANENTS):
1032 c79faeb5 Stavros Sachtouris
                    net.pop(key)
1033 f76c6bbc Stavros Sachtouris
        if self['detail'] and not (
1034 f76c6bbc Stavros Sachtouris
                self['json_output'] or self['output_format']):
1035 c79faeb5 Stavros Sachtouris
            self._add_name(networks)
1036 c79faeb5 Stavros Sachtouris
            self._add_name(networks, 'tenant_id')
1037 545c6c29 Stavros Sachtouris
        kwargs = dict(with_enumeration=self['enum'])
1038 ddc0b290 Stavros Sachtouris
        if self['more']:
1039 6430d3a0 Stavros Sachtouris
            kwargs['out'] = StringIO()
1040 6430d3a0 Stavros Sachtouris
            kwargs['title'] = ()
1041 6430d3a0 Stavros Sachtouris
        if self['limit']:
1042 545c6c29 Stavros Sachtouris
            networks = networks[:self['limit']]
1043 545c6c29 Stavros Sachtouris
        self._print(networks, **kwargs)
1044 6430d3a0 Stavros Sachtouris
        if self['more']:
1045 6430d3a0 Stavros Sachtouris
            pager(kwargs['out'].getvalue())
1046 7493ccb6 Stavros Sachtouris
1047 5a673575 Stavros Sachtouris
    def main(self):
1048 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
1049 5a673575 Stavros Sachtouris
        self._run()
1050 5a673575 Stavros Sachtouris
1051 234954d1 Stavros Sachtouris
1052 d486baec Stavros Sachtouris
@command(network_cmds)
1053 77df3d4a Stavros Sachtouris
class network_create(_init_cyclades, _optional_json, _network_wait):
1054 0e806947 Stavros Sachtouris
    """Create an (unconnected) network"""
1055 7493ccb6 Stavros Sachtouris
1056 93914390 Stavros Sachtouris
    arguments = dict(
1057 0e806947 Stavros Sachtouris
        cidr=ValueArgument('explicitly set cidr', '--with-cidr'),
1058 0e806947 Stavros Sachtouris
        gateway=ValueArgument('explicitly set gateway', '--with-gateway'),
1059 9d1db11e Stavros Sachtouris
        dhcp=FlagArgument('Use dhcp (default: off)', '--with-dhcp'),
1060 f6f81cd3 Stavros Sachtouris
        type=ValueArgument(
1061 f6f81cd3 Stavros Sachtouris
            'Valid network types are '
1062 f6f81cd3 Stavros Sachtouris
            'CUSTOM, IP_LESS_ROUTED, MAC_FILTERED (default), PHYSICAL_VLAN',
1063 f6f81cd3 Stavros Sachtouris
            '--with-type',
1064 77df3d4a Stavros Sachtouris
            default='MAC_FILTERED'),
1065 77df3d4a Stavros Sachtouris
        wait=FlagArgument('Wait network to build', ('-w', '--wait'))
1066 93914390 Stavros Sachtouris
    )
1067 7493ccb6 Stavros Sachtouris
1068 5a673575 Stavros Sachtouris
    @errors.generic.all
1069 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
1070 5a673575 Stavros Sachtouris
    @errors.cyclades.network_max
1071 5a673575 Stavros Sachtouris
    def _run(self, name):
1072 77df3d4a Stavros Sachtouris
        r = self.client.create_network(
1073 de73876b Stavros Sachtouris
            name,
1074 5a673575 Stavros Sachtouris
            cidr=self['cidr'],
1075 5a673575 Stavros Sachtouris
            gateway=self['gateway'],
1076 5a673575 Stavros Sachtouris
            dhcp=self['dhcp'],
1077 77df3d4a Stavros Sachtouris
            type=self['type'])
1078 cf115aed Stavros Sachtouris
        _add_name(self, r)
1079 76f58e2e Stavros Sachtouris
        self._print(r, self.print_dict)
1080 e9c73313 Stavros Sachtouris
        if self['wait'] and r['status'] in ('PENDING', ):
1081 77df3d4a Stavros Sachtouris
            self._wait(r['id'], 'PENDING')
1082 5a673575 Stavros Sachtouris
1083 7493ccb6 Stavros Sachtouris
    def main(self, name):
1084 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
1085 5a673575 Stavros Sachtouris
        self._run(name)
1086 7493ccb6 Stavros Sachtouris
1087 234954d1 Stavros Sachtouris
1088 d486baec Stavros Sachtouris
@command(network_cmds)
1089 1b73b4c1 Stavros Sachtouris
class network_rename(_init_cyclades, _optional_output_cmd):
1090 0e806947 Stavros Sachtouris
    """Set the name of a network"""
1091 7493ccb6 Stavros Sachtouris
1092 5a673575 Stavros Sachtouris
    @errors.generic.all
1093 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
1094 5a673575 Stavros Sachtouris
    @errors.cyclades.network_id
1095 5a673575 Stavros Sachtouris
    def _run(self, network_id, new_name):
1096 1b73b4c1 Stavros Sachtouris
        self._optional_output(
1097 1b73b4c1 Stavros Sachtouris
                self.client.update_network_name(int(network_id), new_name))
1098 5a673575 Stavros Sachtouris
1099 7493ccb6 Stavros Sachtouris
    def main(self, network_id, new_name):
1100 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
1101 5a673575 Stavros Sachtouris
        self._run(network_id=network_id, new_name=new_name)
1102 7493ccb6 Stavros Sachtouris
1103 234954d1 Stavros Sachtouris
1104 d486baec Stavros Sachtouris
@command(network_cmds)
1105 77df3d4a Stavros Sachtouris
class network_delete(_init_cyclades, _optional_output_cmd, _network_wait):
1106 7493ccb6 Stavros Sachtouris
    """Delete a network"""
1107 7493ccb6 Stavros Sachtouris
1108 77df3d4a Stavros Sachtouris
    arguments = dict(
1109 77df3d4a Stavros Sachtouris
        wait=FlagArgument('Wait network to build', ('-w', '--wait'))
1110 77df3d4a Stavros Sachtouris
    )
1111 77df3d4a Stavros Sachtouris
1112 5a673575 Stavros Sachtouris
    @errors.generic.all
1113 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
1114 5a673575 Stavros Sachtouris
    @errors.cyclades.network_in_use
1115 ef3488a7 Stavros Sachtouris
    @errors.cyclades.network_id
1116 5a673575 Stavros Sachtouris
    def _run(self, network_id):
1117 77df3d4a Stavros Sachtouris
        status = 'DELETED'
1118 77df3d4a Stavros Sachtouris
        if self['wait']:
1119 77df3d4a Stavros Sachtouris
            r = self.client.get_network_details(network_id)
1120 77df3d4a Stavros Sachtouris
            status = r['status']
1121 77df3d4a Stavros Sachtouris
            if status in ('DELETED', ):
1122 77df3d4a Stavros Sachtouris
                return
1123 77df3d4a Stavros Sachtouris
1124 77df3d4a Stavros Sachtouris
        r = self.client.delete_network(int(network_id))
1125 77df3d4a Stavros Sachtouris
        self._optional_output(r)
1126 77df3d4a Stavros Sachtouris
1127 77df3d4a Stavros Sachtouris
        if self['wait']:
1128 77df3d4a Stavros Sachtouris
            self._wait(network_id, status)
1129 5a673575 Stavros Sachtouris
1130 7493ccb6 Stavros Sachtouris
    def main(self, network_id):
1131 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
1132 5a673575 Stavros Sachtouris
        self._run(network_id=network_id)
1133 7493ccb6 Stavros Sachtouris
1134 234954d1 Stavros Sachtouris
1135 d486baec Stavros Sachtouris
@command(network_cmds)
1136 1b73b4c1 Stavros Sachtouris
class network_connect(_init_cyclades, _optional_output_cmd):
1137 7493ccb6 Stavros Sachtouris
    """Connect a server to a network"""
1138 7493ccb6 Stavros Sachtouris
1139 5a673575 Stavros Sachtouris
    @errors.generic.all
1140 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
1141 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
1142 5a673575 Stavros Sachtouris
    @errors.cyclades.network_id
1143 5a673575 Stavros Sachtouris
    def _run(self, server_id, network_id):
1144 1b73b4c1 Stavros Sachtouris
        self._optional_output(
1145 1b73b4c1 Stavros Sachtouris
                self.client.connect_server(int(server_id), int(network_id)))
1146 5a673575 Stavros Sachtouris
1147 7493ccb6 Stavros Sachtouris
    def main(self, server_id, network_id):
1148 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
1149 5a673575 Stavros Sachtouris
        self._run(server_id=server_id, network_id=network_id)
1150 7493ccb6 Stavros Sachtouris
1151 234954d1 Stavros Sachtouris
1152 d486baec Stavros Sachtouris
@command(network_cmds)
1153 7493ccb6 Stavros Sachtouris
class network_disconnect(_init_cyclades):
1154 0e806947 Stavros Sachtouris
    """Disconnect a nic that connects a server to a network
1155 0e806947 Stavros Sachtouris
    Nic ids are listed as "attachments" in detailed network information
1156 439826ec Stavros Sachtouris
    To get detailed network information: /network info <network id>
1157 0e806947 Stavros Sachtouris
    """
1158 7493ccb6 Stavros Sachtouris
1159 5a673575 Stavros Sachtouris
    @errors.cyclades.nic_format
1160 5a673575 Stavros Sachtouris
    def _server_id_from_nic(self, nic_id):
1161 5a673575 Stavros Sachtouris
        return nic_id.split('-')[1]
1162 5a673575 Stavros Sachtouris
1163 5a673575 Stavros Sachtouris
    @errors.generic.all
1164 5a673575 Stavros Sachtouris
    @errors.cyclades.connection
1165 5a673575 Stavros Sachtouris
    @errors.cyclades.server_id
1166 5a673575 Stavros Sachtouris
    @errors.cyclades.nic_id
1167 5a673575 Stavros Sachtouris
    def _run(self, nic_id, server_id):
1168 1b73b4c1 Stavros Sachtouris
        num_of_disconnected = self.client.disconnect_server(server_id, nic_id)
1169 1b73b4c1 Stavros Sachtouris
        if not num_of_disconnected:
1170 5a673575 Stavros Sachtouris
            raise ClientError(
1171 5a673575 Stavros Sachtouris
                'Network Interface %s not found on server %s' % (
1172 3185cd6d Stavros Sachtouris
                    nic_id, server_id),
1173 5a673575 Stavros Sachtouris
                status=404)
1174 1b73b4c1 Stavros Sachtouris
        print('Disconnected %s connections' % num_of_disconnected)
1175 5a673575 Stavros Sachtouris
1176 7493ccb6 Stavros Sachtouris
    def main(self, nic_id):
1177 5a673575 Stavros Sachtouris
        super(self.__class__, self)._run()
1178 5a673575 Stavros Sachtouris
        server_id = self._server_id_from_nic(nic_id=nic_id)
1179 5a673575 Stavros Sachtouris
        self._run(nic_id=nic_id, server_id=server_id)
1180 9b47150e Stavros Sachtouris
1181 9b47150e Stavros Sachtouris
1182 7b2e4bf1 Stavros Sachtouris
@command(network_cmds)
1183 7b2e4bf1 Stavros Sachtouris
class network_wait(_init_cyclades, _network_wait):
1184 7b2e4bf1 Stavros Sachtouris
    """Wait for server to finish [PENDING, ACTIVE, DELETED]"""
1185 7b2e4bf1 Stavros Sachtouris
1186 8547cd19 Stavros Sachtouris
    arguments = dict(
1187 8547cd19 Stavros Sachtouris
        timeout=IntArgument(
1188 8547cd19 Stavros Sachtouris
            'Wait limit in seconds (default: 60)', '--timeout', default=60)
1189 8547cd19 Stavros Sachtouris
    )
1190 8547cd19 Stavros Sachtouris
1191 7b2e4bf1 Stavros Sachtouris
    @errors.generic.all
1192 7b2e4bf1 Stavros Sachtouris
    @errors.cyclades.connection
1193 7b2e4bf1 Stavros Sachtouris
    @errors.cyclades.network_id
1194 e9c73313 Stavros Sachtouris
    def _run(self, network_id, current_status):
1195 e9c73313 Stavros Sachtouris
        net = self.client.get_network_details(network_id)
1196 e9c73313 Stavros Sachtouris
        if net['status'].lower() == current_status.lower():
1197 8547cd19 Stavros Sachtouris
            self._wait(network_id, current_status, timeout=self['timeout'])
1198 e9c73313 Stavros Sachtouris
        else:
1199 e9c73313 Stavros Sachtouris
            self.error(
1200 e9c73313 Stavros Sachtouris
                'Network %s: Cannot wait for status %s, '
1201 e9c73313 Stavros Sachtouris
                'status is already %s' % (
1202 e9c73313 Stavros Sachtouris
                    network_id, current_status, net['status']))
1203 7b2e4bf1 Stavros Sachtouris
1204 e9c73313 Stavros Sachtouris
    def main(self, network_id, current_status='PENDING'):
1205 7b2e4bf1 Stavros Sachtouris
        super(self.__class__, self)._run()
1206 e9c73313 Stavros Sachtouris
        self._run(network_id=network_id, current_status=current_status)
1207 7b2e4bf1 Stavros Sachtouris
1208 7b2e4bf1 Stavros Sachtouris
1209 6489c38b Stavros Sachtouris
@command(ip_cmds)
1210 6489c38b Stavros Sachtouris
class ip_pools(_init_cyclades, _optional_json):
1211 6489c38b Stavros Sachtouris
    """List pools of floating IPs"""
1212 9b47150e Stavros Sachtouris
1213 9b47150e Stavros Sachtouris
    @errors.generic.all
1214 9b47150e Stavros Sachtouris
    @errors.cyclades.connection
1215 9b47150e Stavros Sachtouris
    def _run(self):
1216 9b47150e Stavros Sachtouris
        r = self.client.get_floating_ip_pools()
1217 f76c6bbc Stavros Sachtouris
        self._print(r if self['json_output'] or self['output_format'] else r[
1218 f76c6bbc Stavros Sachtouris
            'floating_ip_pools'])
1219 9b47150e Stavros Sachtouris
1220 9b47150e Stavros Sachtouris
    def main(self):
1221 9b47150e Stavros Sachtouris
        super(self.__class__, self)._run()
1222 9b47150e Stavros Sachtouris
        self._run()
1223 9b47150e Stavros Sachtouris
1224 9b47150e Stavros Sachtouris
1225 6489c38b Stavros Sachtouris
@command(ip_cmds)
1226 6489c38b Stavros Sachtouris
class ip_list(_init_cyclades, _optional_json):
1227 6489c38b Stavros Sachtouris
    """List reserved floating IPs"""
1228 9b47150e Stavros Sachtouris
1229 9b47150e Stavros Sachtouris
    @errors.generic.all
1230 9b47150e Stavros Sachtouris
    @errors.cyclades.connection
1231 9b47150e Stavros Sachtouris
    def _run(self):
1232 9b47150e Stavros Sachtouris
        r = self.client.get_floating_ips()
1233 f76c6bbc Stavros Sachtouris
        self._print(r if self['json_output'] or self['output_format'] else r[
1234 f76c6bbc Stavros Sachtouris
            'floating_ips'])
1235 9b47150e Stavros Sachtouris
1236 9b47150e Stavros Sachtouris
    def main(self):
1237 9b47150e Stavros Sachtouris
        super(self.__class__, self)._run()
1238 9b47150e Stavros Sachtouris
        self._run()
1239 9b47150e Stavros Sachtouris
1240 9b47150e Stavros Sachtouris
1241 6489c38b Stavros Sachtouris
@command(ip_cmds)
1242 6489c38b Stavros Sachtouris
class ip_info(_init_cyclades, _optional_json):
1243 6489c38b Stavros Sachtouris
    """Details for an IP"""
1244 9b47150e Stavros Sachtouris
1245 9b47150e Stavros Sachtouris
    @errors.generic.all
1246 9b47150e Stavros Sachtouris
    @errors.cyclades.connection
1247 9b47150e Stavros Sachtouris
    def _run(self, ip):
1248 76f58e2e Stavros Sachtouris
        self._print(self.client.get_floating_ip(ip), self.print_dict)
1249 9b47150e Stavros Sachtouris
1250 6489c38b Stavros Sachtouris
    def main(self, IP):
1251 9b47150e Stavros Sachtouris
        super(self.__class__, self)._run()
1252 6489c38b Stavros Sachtouris
        self._run(ip=IP)
1253 9b47150e Stavros Sachtouris
1254 9b47150e Stavros Sachtouris
1255 6489c38b Stavros Sachtouris
@command(ip_cmds)
1256 6489c38b Stavros Sachtouris
class ip_reserve(_init_cyclades, _optional_json):
1257 6489c38b Stavros Sachtouris
    """Reserve a floating IP
1258 6489c38b Stavros Sachtouris
    An IP is reserved from an IP pool. The default IP pool is chosen
1259 6489c38b Stavros Sachtouris
    automatically, but there is the option if specifying an explicit IP pool.
1260 6489c38b Stavros Sachtouris
    """
1261 9b47150e Stavros Sachtouris
1262 3185cd6d Stavros Sachtouris
    arguments = dict(pool=ValueArgument('Source IP pool', ('--pool'), None))
1263 9b47150e Stavros Sachtouris
1264 9b47150e Stavros Sachtouris
    @errors.generic.all
1265 9b47150e Stavros Sachtouris
    @errors.cyclades.connection
1266 9b47150e Stavros Sachtouris
    def _run(self, ip=None):
1267 2e6e03da Stavros Sachtouris
        self._print([self.client.alloc_floating_ip(self['pool'], ip)])
1268 9b47150e Stavros Sachtouris
1269 6489c38b Stavros Sachtouris
    def main(self, requested_IP=None):
1270 9b47150e Stavros Sachtouris
        super(self.__class__, self)._run()
1271 6489c38b Stavros Sachtouris
        self._run(ip=requested_IP)
1272 9b47150e Stavros Sachtouris
1273 9b47150e Stavros Sachtouris
1274 6489c38b Stavros Sachtouris
@command(ip_cmds)
1275 6489c38b Stavros Sachtouris
class ip_release(_init_cyclades, _optional_output_cmd):
1276 6489c38b Stavros Sachtouris
    """Release a floating IP
1277 6489c38b Stavros Sachtouris
    The release IP is "returned" to the IP pool it came from.
1278 6489c38b Stavros Sachtouris
    """
1279 9b47150e Stavros Sachtouris
1280 9b47150e Stavros Sachtouris
    @errors.generic.all
1281 9b47150e Stavros Sachtouris
    @errors.cyclades.connection
1282 9b47150e Stavros Sachtouris
    def _run(self, ip):
1283 9b47150e Stavros Sachtouris
        self._optional_output(self.client.delete_floating_ip(ip))
1284 9b47150e Stavros Sachtouris
1285 6489c38b Stavros Sachtouris
    def main(self, IP):
1286 9b47150e Stavros Sachtouris
        super(self.__class__, self)._run()
1287 6489c38b Stavros Sachtouris
        self._run(ip=IP)
1288 9b47150e Stavros Sachtouris
1289 9b47150e Stavros Sachtouris
1290 6489c38b Stavros Sachtouris
@command(ip_cmds)
1291 6489c38b Stavros Sachtouris
class ip_attach(_init_cyclades, _optional_output_cmd):
1292 6489c38b Stavros Sachtouris
    """Attach a floating IP to a server
1293 9b47150e Stavros Sachtouris
    """
1294 9b47150e Stavros Sachtouris
1295 9b47150e Stavros Sachtouris
    @errors.generic.all
1296 9b47150e Stavros Sachtouris
    @errors.cyclades.connection
1297 9b47150e Stavros Sachtouris
    @errors.cyclades.server_id
1298 9b47150e Stavros Sachtouris
    def _run(self, server_id, ip):
1299 9b47150e Stavros Sachtouris
        self._optional_output(self.client.attach_floating_ip(server_id, ip))
1300 9b47150e Stavros Sachtouris
1301 6489c38b Stavros Sachtouris
    def main(self, server_id, IP):
1302 9b47150e Stavros Sachtouris
        super(self.__class__, self)._run()
1303 6489c38b Stavros Sachtouris
        self._run(server_id=server_id, ip=IP)
1304 9b47150e Stavros Sachtouris
1305 9b47150e Stavros Sachtouris
1306 6489c38b Stavros Sachtouris
@command(ip_cmds)
1307 6489c38b Stavros Sachtouris
class ip_detach(_init_cyclades, _optional_output_cmd):
1308 6489c38b Stavros Sachtouris
    """Detach a floating IP from a server
1309 9b47150e Stavros Sachtouris
    """
1310 9b47150e Stavros Sachtouris
1311 9b47150e Stavros Sachtouris
    @errors.generic.all
1312 9b47150e Stavros Sachtouris
    @errors.cyclades.connection
1313 9b47150e Stavros Sachtouris
    @errors.cyclades.server_id
1314 9b47150e Stavros Sachtouris
    def _run(self, server_id, ip):
1315 9b47150e Stavros Sachtouris
        self._optional_output(self.client.detach_floating_ip(server_id, ip))
1316 9b47150e Stavros Sachtouris
1317 6489c38b Stavros Sachtouris
    def main(self, server_id, IP):
1318 9b47150e Stavros Sachtouris
        super(self.__class__, self)._run()
1319 6489c38b Stavros Sachtouris
        self._run(server_id=server_id, ip=IP)