Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / network.py @ 38a79780

History | View | Annotate | Download (26.9 kB)

1 d18e6439 Stavros Sachtouris
# Copyright 2011-2013 GRNET S.A. All rights reserved.
2 d18e6439 Stavros Sachtouris
#
3 d18e6439 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 d18e6439 Stavros Sachtouris
# without modification, are permitted provided that the following
5 d18e6439 Stavros Sachtouris
# conditions are met:
6 d18e6439 Stavros Sachtouris
#
7 d18e6439 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 d18e6439 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 d18e6439 Stavros Sachtouris
#      disclaimer.
10 d18e6439 Stavros Sachtouris
#
11 d18e6439 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 d18e6439 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 d18e6439 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 d18e6439 Stavros Sachtouris
#      provided with the distribution.
15 d18e6439 Stavros Sachtouris
#
16 d18e6439 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 d18e6439 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 d18e6439 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 d18e6439 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 d18e6439 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 d18e6439 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 d18e6439 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 d18e6439 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 d18e6439 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 d18e6439 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 d18e6439 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 d18e6439 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 d18e6439 Stavros Sachtouris
#
29 d18e6439 Stavros Sachtouris
# The views and conclusions contained in the software and
30 d18e6439 Stavros Sachtouris
# documentation are those of the authors and should not be
31 d18e6439 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 d18e6439 Stavros Sachtouris
# or implied, of GRNET S.A.
33 d18e6439 Stavros Sachtouris
34 d18e6439 Stavros Sachtouris
from io import StringIO
35 d18e6439 Stavros Sachtouris
from pydoc import pager
36 d18e6439 Stavros Sachtouris
37 d18e6439 Stavros Sachtouris
from kamaki.cli import command
38 d18e6439 Stavros Sachtouris
from kamaki.cli.command_tree import CommandTree
39 62c6652f Stavros Sachtouris
from kamaki.cli.errors import (
40 fd981f77 Stavros Sachtouris
    CLIBaseUrlError, CLIInvalidArgument, raiseCLIError)
41 f3740b99 Stavros Sachtouris
from kamaki.clients.cyclades import CycladesNetworkClient, ClientError
42 6f2b87c1 Stavros Sachtouris
from kamaki.cli.argument import (
43 c3d42104 Stavros Sachtouris
    FlagArgument, ValueArgument, RepeatableArgument, IntArgument,
44 c3d42104 Stavros Sachtouris
    StatusArgument)
45 d18e6439 Stavros Sachtouris
from kamaki.cli.commands import _command_init, errors, addLogSettings
46 d18e6439 Stavros Sachtouris
from kamaki.cli.commands import (
47 d18e6439 Stavros Sachtouris
    _optional_output_cmd, _optional_json, _name_filter, _id_filter)
48 6f2b87c1 Stavros Sachtouris
from kamaki.cli.commands.cyclades import _service_wait
49 d18e6439 Stavros Sachtouris
50 d18e6439 Stavros Sachtouris
51 609471e9 Stavros Sachtouris
network_cmds = CommandTree('network', 'Network API network commands')
52 609471e9 Stavros Sachtouris
port_cmds = CommandTree('port', 'Network API port commands')
53 609471e9 Stavros Sachtouris
subnet_cmds = CommandTree('subnet', 'Network API subnet commands')
54 609471e9 Stavros Sachtouris
ip_cmds = CommandTree('ip', 'Network API floatingip commands')
55 d1bced10 Stavros Sachtouris
_commands = [network_cmds, port_cmds, subnet_cmds, ip_cmds]
56 d18e6439 Stavros Sachtouris
57 d18e6439 Stavros Sachtouris
58 d18e6439 Stavros Sachtouris
about_authentication = '\nUser Authentication:\
59 7a3c66e1 Stavros Sachtouris
    \n  to check authentication: [kamaki] ]user authenticate\
60 7a3c66e1 Stavros Sachtouris
    \n  to set authentication token: \
61 7a3c66e1 Stavros Sachtouris
    [kamaki] config set cloud.<CLOUD>.token <TOKEN>'
62 d18e6439 Stavros Sachtouris
63 c3d42104 Stavros Sachtouris
port_states = ('BUILD', 'ACTIVE', 'DOWN', 'ERROR')
64 c3d42104 Stavros Sachtouris
65 d18e6439 Stavros Sachtouris
66 c6afee48 Stavros Sachtouris
class _port_wait(_service_wait):
67 c6afee48 Stavros Sachtouris
68 c6afee48 Stavros Sachtouris
    def _wait(self, port_id, current_status, timeout=60):
69 c6afee48 Stavros Sachtouris
        super(_port_wait, self)._wait(
70 c6afee48 Stavros Sachtouris
            'Port', port_id, self.client.wait_port, current_status,
71 c6afee48 Stavros Sachtouris
            timeout=timeout)
72 c6afee48 Stavros Sachtouris
73 c6afee48 Stavros Sachtouris
74 5c433331 Stavros Sachtouris
class _init_network(_command_init):
75 bc4662d8 Stavros Sachtouris
    @errors.generic.all
76 bc4662d8 Stavros Sachtouris
    @addLogSettings
77 bc4662d8 Stavros Sachtouris
    def _run(self, service='network'):
78 bc4662d8 Stavros Sachtouris
        if getattr(self, 'cloud', None):
79 bc4662d8 Stavros Sachtouris
            base_url = self._custom_url(service) or self._custom_url(
80 264a13f7 Stavros Sachtouris
                'network')
81 bc4662d8 Stavros Sachtouris
            if base_url:
82 bc4662d8 Stavros Sachtouris
                token = self._custom_token(service) or self._custom_token(
83 264a13f7 Stavros Sachtouris
                    'network') or self.config.get_cloud('token')
84 cd0927f7 Stavros Sachtouris
                self.client = CycladesNetworkClient(
85 bc4662d8 Stavros Sachtouris
                  base_url=base_url, token=token)
86 bc4662d8 Stavros Sachtouris
                return
87 bc4662d8 Stavros Sachtouris
        else:
88 bc4662d8 Stavros Sachtouris
            self.cloud = 'default'
89 bc4662d8 Stavros Sachtouris
        if getattr(self, 'auth_base', False):
90 cec2dfcd Stavros Sachtouris
            network_endpoints = self.auth_base.get_service_endpoints(
91 264a13f7 Stavros Sachtouris
                self._custom_type('network') or 'network',
92 264a13f7 Stavros Sachtouris
                self._custom_version('network') or '')
93 cec2dfcd Stavros Sachtouris
            base_url = network_endpoints['publicURL']
94 bc4662d8 Stavros Sachtouris
            token = self.auth_base.token
95 cd0927f7 Stavros Sachtouris
            self.client = CycladesNetworkClient(base_url=base_url, token=token)
96 bc4662d8 Stavros Sachtouris
        else:
97 bc4662d8 Stavros Sachtouris
            raise CLIBaseUrlError(service='network')
98 bc4662d8 Stavros Sachtouris
99 f3740b99 Stavros Sachtouris
    def _filter_by_user_id(self, nets):
100 f3740b99 Stavros Sachtouris
        return [net for net in nets if net['user_id'] == self['user_id']] if (
101 f3740b99 Stavros Sachtouris
            self['user_id']) else nets
102 f3740b99 Stavros Sachtouris
103 bc4662d8 Stavros Sachtouris
    def main(self):
104 bc4662d8 Stavros Sachtouris
        self._run()
105 d18e6439 Stavros Sachtouris
106 d18e6439 Stavros Sachtouris
107 d18e6439 Stavros Sachtouris
@command(network_cmds)
108 5c433331 Stavros Sachtouris
class network_list(_init_network, _optional_json, _name_filter, _id_filter):
109 d18e6439 Stavros Sachtouris
    """List networks
110 d18e6439 Stavros Sachtouris
    Use filtering arguments (e.g., --name-like) to manage long server lists
111 d18e6439 Stavros Sachtouris
    """
112 d18e6439 Stavros Sachtouris
113 d18e6439 Stavros Sachtouris
    arguments = dict(
114 d18e6439 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
115 cd40143a Stavros Sachtouris
        more=FlagArgument(
116 cd40143a Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
117 cd40143a Stavros Sachtouris
            '--more'),
118 7e57e590 Stavros Sachtouris
        user_id=ValueArgument(
119 7e57e590 Stavros Sachtouris
            'show only networks belonging to user with this id', '--user-id')
120 d18e6439 Stavros Sachtouris
    )
121 d18e6439 Stavros Sachtouris
122 d18e6439 Stavros Sachtouris
    @errors.generic.all
123 d18e6439 Stavros Sachtouris
    @errors.cyclades.connection
124 d18e6439 Stavros Sachtouris
    def _run(self):
125 c77131f4 Stavros Sachtouris
        nets = self.client.list_networks(detail=True)
126 7e57e590 Stavros Sachtouris
        nets = self._filter_by_user_id(nets)
127 77bf75fe Stavros Sachtouris
        nets = self._filter_by_name(nets)
128 77bf75fe Stavros Sachtouris
        nets = self._filter_by_id(nets)
129 c77131f4 Stavros Sachtouris
        if not self['detail']:
130 7e57e590 Stavros Sachtouris
            nets = [dict(
131 c77131f4 Stavros Sachtouris
                _0_id=n['id'],
132 c77131f4 Stavros Sachtouris
                _1_name=n['name'],
133 7fbda4e5 Dionysis Grigoropoulos
                _2_public='( %s )' % ('public' if (
134 7fbda4e5 Dionysis Grigoropoulos
                    n.get('public', None)) else 'private')) for n in nets]
135 c77131f4 Stavros Sachtouris
            kwargs = dict(title=('_0_id', '_1_name', '_2_public'))
136 c77131f4 Stavros Sachtouris
        else:
137 c77131f4 Stavros Sachtouris
            kwargs = dict()
138 cd40143a Stavros Sachtouris
        if self['more']:
139 cd40143a Stavros Sachtouris
            kwargs['out'] = StringIO()
140 cd40143a Stavros Sachtouris
            kwargs['title'] = ()
141 cd40143a Stavros Sachtouris
        self._print(nets, **kwargs)
142 cd40143a Stavros Sachtouris
        if self['more']:
143 cd40143a Stavros Sachtouris
            pager(kwargs['out'].getvalue())
144 d18e6439 Stavros Sachtouris
145 d18e6439 Stavros Sachtouris
    def main(self):
146 d18e6439 Stavros Sachtouris
        super(self.__class__, self)._run()
147 d18e6439 Stavros Sachtouris
        self._run()
148 cd40143a Stavros Sachtouris
149 cd40143a Stavros Sachtouris
150 cd40143a Stavros Sachtouris
@command(network_cmds)
151 5c433331 Stavros Sachtouris
class network_info(_init_network, _optional_json):
152 cd40143a Stavros Sachtouris
    """Get details about a network"""
153 cd40143a Stavros Sachtouris
154 cd40143a Stavros Sachtouris
    @errors.generic.all
155 cd40143a Stavros Sachtouris
    @errors.cyclades.connection
156 cd40143a Stavros Sachtouris
    @errors.cyclades.network_id
157 cd40143a Stavros Sachtouris
    def _run(self, network_id):
158 cd40143a Stavros Sachtouris
        net = self.client.get_network_details(network_id)
159 cd40143a Stavros Sachtouris
        self._print(net, self.print_dict)
160 cd40143a Stavros Sachtouris
161 cd40143a Stavros Sachtouris
    def main(self, network_id):
162 cd40143a Stavros Sachtouris
        super(self.__class__, self)._run()
163 cd40143a Stavros Sachtouris
        self._run(network_id=network_id)
164 49413939 Stavros Sachtouris
165 49413939 Stavros Sachtouris
166 264a13f7 Stavros Sachtouris
class NetworkTypeArgument(ValueArgument):
167 264a13f7 Stavros Sachtouris
168 1c366ac9 Stavros Sachtouris
    types = ('MAC_FILTERED', 'CUSTOM', 'IP_LESS_ROUTED', 'PHYSICAL_VLAN')
169 264a13f7 Stavros Sachtouris
170 264a13f7 Stavros Sachtouris
    @property
171 264a13f7 Stavros Sachtouris
    def value(self):
172 1c366ac9 Stavros Sachtouris
        return getattr(self, '_value', self.types[0])
173 264a13f7 Stavros Sachtouris
174 264a13f7 Stavros Sachtouris
    @value.setter
175 264a13f7 Stavros Sachtouris
    def value(self, new_value):
176 264a13f7 Stavros Sachtouris
        if new_value and new_value.upper() in self.types:
177 264a13f7 Stavros Sachtouris
            self._value = new_value.upper()
178 264a13f7 Stavros Sachtouris
        elif new_value:
179 264a13f7 Stavros Sachtouris
            raise CLIInvalidArgument(
180 264a13f7 Stavros Sachtouris
                'Invalid network type %s' % new_value, details=[
181 264a13f7 Stavros Sachtouris
                    'Valid types: %s' % ', '.join(self.types), ])
182 264a13f7 Stavros Sachtouris
183 264a13f7 Stavros Sachtouris
184 49413939 Stavros Sachtouris
@command(network_cmds)
185 67dfe4a2 Stavros Sachtouris
class network_create(_init_network, _optional_json):
186 1c366ac9 Stavros Sachtouris
    """Create a new network (default type: MAC_FILTERED)"""
187 49413939 Stavros Sachtouris
188 cd0927f7 Stavros Sachtouris
    arguments = dict(
189 cd0927f7 Stavros Sachtouris
        name=ValueArgument('Network name', '--name'),
190 cd0927f7 Stavros Sachtouris
        shared=FlagArgument(
191 264a13f7 Stavros Sachtouris
            'Make network shared (special privileges required)', '--shared'),
192 264a13f7 Stavros Sachtouris
        network_type=NetworkTypeArgument(
193 264a13f7 Stavros Sachtouris
            'Valid network types: %s' % (', '.join(NetworkTypeArgument.types)),
194 67dfe4a2 Stavros Sachtouris
            '--type')
195 49413939 Stavros Sachtouris
    )
196 49413939 Stavros Sachtouris
197 49413939 Stavros Sachtouris
    @errors.generic.all
198 49413939 Stavros Sachtouris
    @errors.cyclades.connection
199 cd0927f7 Stavros Sachtouris
    @errors.cyclades.network_type
200 cd0927f7 Stavros Sachtouris
    def _run(self, network_type):
201 49413939 Stavros Sachtouris
        net = self.client.create_network(
202 cd0927f7 Stavros Sachtouris
            network_type, name=self['name'], shared=self['shared'])
203 49413939 Stavros Sachtouris
        self._print(net, self.print_dict)
204 49413939 Stavros Sachtouris
205 264a13f7 Stavros Sachtouris
    def main(self):
206 49413939 Stavros Sachtouris
        super(self.__class__, self)._run()
207 264a13f7 Stavros Sachtouris
        self._run(network_type=self['network_type'])
208 aef3fa1f Stavros Sachtouris
209 aef3fa1f Stavros Sachtouris
210 aef3fa1f Stavros Sachtouris
@command(network_cmds)
211 5c433331 Stavros Sachtouris
class network_delete(_init_network, _optional_output_cmd):
212 aef3fa1f Stavros Sachtouris
    """Delete a network"""
213 aef3fa1f Stavros Sachtouris
214 aef3fa1f Stavros Sachtouris
    @errors.generic.all
215 aef3fa1f Stavros Sachtouris
    @errors.cyclades.connection
216 58602137 Stavros Sachtouris
    @errors.cyclades.network_id
217 aef3fa1f Stavros Sachtouris
    def _run(self, network_id):
218 aef3fa1f Stavros Sachtouris
        r = self.client.delete_network(network_id)
219 aef3fa1f Stavros Sachtouris
        self._optional_output(r)
220 aef3fa1f Stavros Sachtouris
221 aef3fa1f Stavros Sachtouris
    def main(self, network_id):
222 aef3fa1f Stavros Sachtouris
        super(self.__class__, self)._run()
223 aef3fa1f Stavros Sachtouris
        self._run(network_id=network_id)
224 58602137 Stavros Sachtouris
225 58602137 Stavros Sachtouris
226 58602137 Stavros Sachtouris
@command(network_cmds)
227 264a13f7 Stavros Sachtouris
class network_modify(_init_network, _optional_json):
228 264a13f7 Stavros Sachtouris
    """Modify network attributes"""
229 58602137 Stavros Sachtouris
230 264a13f7 Stavros Sachtouris
    arguments = dict(new_name=ValueArgument('Rename the network', '--name'))
231 264a13f7 Stavros Sachtouris
    required = ['new_name', ]
232 58602137 Stavros Sachtouris
233 58602137 Stavros Sachtouris
    @errors.generic.all
234 58602137 Stavros Sachtouris
    @errors.cyclades.connection
235 58602137 Stavros Sachtouris
    @errors.cyclades.network_id
236 58602137 Stavros Sachtouris
    def _run(self, network_id):
237 264a13f7 Stavros Sachtouris
        r = self.client.update_network(network_id, name=self['new_name'])
238 58602137 Stavros Sachtouris
        self._print(r, self.print_dict)
239 58602137 Stavros Sachtouris
240 58602137 Stavros Sachtouris
    def main(self, network_id):
241 58602137 Stavros Sachtouris
        super(self.__class__, self)._run()
242 58602137 Stavros Sachtouris
        self._run(network_id=network_id)
243 62c6652f Stavros Sachtouris
244 62c6652f Stavros Sachtouris
245 62c6652f Stavros Sachtouris
@command(subnet_cmds)
246 62c6652f Stavros Sachtouris
class subnet_list(_init_network, _optional_json, _name_filter, _id_filter):
247 62c6652f Stavros Sachtouris
    """List subnets
248 62c6652f Stavros Sachtouris
    Use filtering arguments (e.g., --name-like) to manage long server lists
249 62c6652f Stavros Sachtouris
    """
250 62c6652f Stavros Sachtouris
251 62c6652f Stavros Sachtouris
    arguments = dict(
252 62c6652f Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
253 62c6652f Stavros Sachtouris
        more=FlagArgument(
254 62c6652f Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
255 5c5eb675 Stavros Sachtouris
            '--more')
256 62c6652f Stavros Sachtouris
    )
257 62c6652f Stavros Sachtouris
258 62c6652f Stavros Sachtouris
    @errors.generic.all
259 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
260 62c6652f Stavros Sachtouris
    def _run(self):
261 62c6652f Stavros Sachtouris
        nets = self.client.list_subnets()
262 62c6652f Stavros Sachtouris
        nets = self._filter_by_name(nets)
263 62c6652f Stavros Sachtouris
        nets = self._filter_by_id(nets)
264 5c5eb675 Stavros Sachtouris
        if not self['detail']:
265 62c6652f Stavros Sachtouris
            nets = [dict(
266 c77131f4 Stavros Sachtouris
                _0_id=n['id'],
267 c77131f4 Stavros Sachtouris
                _1_name=n['name'],
268 c77131f4 Stavros Sachtouris
                _2_net='( of network %s )' % n['network_id']) for n in nets]
269 c77131f4 Stavros Sachtouris
            kwargs = dict(title=('_0_id', '_1_name', '_2_net'))
270 c77131f4 Stavros Sachtouris
        else:
271 c77131f4 Stavros Sachtouris
            kwargs = dict()
272 62c6652f Stavros Sachtouris
        if self['more']:
273 62c6652f Stavros Sachtouris
            kwargs['out'] = StringIO()
274 62c6652f Stavros Sachtouris
            kwargs['title'] = ()
275 62c6652f Stavros Sachtouris
        self._print(nets, **kwargs)
276 62c6652f Stavros Sachtouris
        if self['more']:
277 62c6652f Stavros Sachtouris
            pager(kwargs['out'].getvalue())
278 62c6652f Stavros Sachtouris
279 62c6652f Stavros Sachtouris
    def main(self):
280 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
281 62c6652f Stavros Sachtouris
        self._run()
282 62c6652f Stavros Sachtouris
283 62c6652f Stavros Sachtouris
284 62c6652f Stavros Sachtouris
@command(subnet_cmds)
285 62c6652f Stavros Sachtouris
class subnet_info(_init_network, _optional_json):
286 62c6652f Stavros Sachtouris
    """Get details about a subnet"""
287 62c6652f Stavros Sachtouris
288 62c6652f Stavros Sachtouris
    @errors.generic.all
289 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
290 62c6652f Stavros Sachtouris
    def _run(self, subnet_id):
291 62c6652f Stavros Sachtouris
        net = self.client.get_subnet_details(subnet_id)
292 62c6652f Stavros Sachtouris
        self._print(net, self.print_dict)
293 62c6652f Stavros Sachtouris
294 62c6652f Stavros Sachtouris
    def main(self, subnet_id):
295 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
296 62c6652f Stavros Sachtouris
        self._run(subnet_id=subnet_id)
297 62c6652f Stavros Sachtouris
298 62c6652f Stavros Sachtouris
299 62c6652f Stavros Sachtouris
class AllocationPoolArgument(RepeatableArgument):
300 62c6652f Stavros Sachtouris
301 62c6652f Stavros Sachtouris
    @property
302 62c6652f Stavros Sachtouris
    def value(self):
303 62c6652f Stavros Sachtouris
        return super(AllocationPoolArgument, self).value or []
304 62c6652f Stavros Sachtouris
305 62c6652f Stavros Sachtouris
    @value.setter
306 62c6652f Stavros Sachtouris
    def value(self, new_pools):
307 7a3c66e1 Stavros Sachtouris
        if not new_pools:
308 7a3c66e1 Stavros Sachtouris
            return
309 62c6652f Stavros Sachtouris
        new_list = []
310 62c6652f Stavros Sachtouris
        for pool in new_pools:
311 62c6652f Stavros Sachtouris
            start, comma, end = pool.partition(',')
312 62c6652f Stavros Sachtouris
            if not (start and comma and end):
313 62c6652f Stavros Sachtouris
                raise CLIInvalidArgument(
314 62c6652f Stavros Sachtouris
                    'Invalid allocation pool argument %s' % pool, details=[
315 62c6652f Stavros Sachtouris
                    'Allocation values must be of the form:',
316 62c6652f Stavros Sachtouris
                    '  <start address>,<end address>'])
317 62c6652f Stavros Sachtouris
            new_list.append(dict(start=start, end=end))
318 62c6652f Stavros Sachtouris
        self._value = new_list
319 62c6652f Stavros Sachtouris
320 62c6652f Stavros Sachtouris
321 62c6652f Stavros Sachtouris
@command(subnet_cmds)
322 62c6652f Stavros Sachtouris
class subnet_create(_init_network, _optional_json):
323 264a13f7 Stavros Sachtouris
    """Create a new subnet"""
324 62c6652f Stavros Sachtouris
325 62c6652f Stavros Sachtouris
    arguments = dict(
326 62c6652f Stavros Sachtouris
        name=ValueArgument('Subnet name', '--name'),
327 62c6652f Stavros Sachtouris
        allocation_pools=AllocationPoolArgument(
328 62c6652f Stavros Sachtouris
            'start_address,end_address of allocation pool (can be repeated)'
329 62c6652f Stavros Sachtouris
            ' e.g., --alloc-pool=123.45.67.1,123.45.67.8',
330 62c6652f Stavros Sachtouris
            '--alloc-pool'),
331 62c6652f Stavros Sachtouris
        gateway=ValueArgument('Gateway IP', '--gateway'),
332 62c6652f Stavros Sachtouris
        subnet_id=ValueArgument('The id for the subnet', '--id'),
333 62c6652f Stavros Sachtouris
        ipv6=FlagArgument('If set, IP version is set to 6, else 4', '--ipv6'),
334 264a13f7 Stavros Sachtouris
        enable_dhcp=FlagArgument('Enable dhcp (default: off)', '--with-dhcp'),
335 264a13f7 Stavros Sachtouris
        network_id=ValueArgument('Set the network ID', '--network-id'),
336 264a13f7 Stavros Sachtouris
        cidr=ValueArgument('Set the CIDR', '--cidr')
337 62c6652f Stavros Sachtouris
    )
338 264a13f7 Stavros Sachtouris
    required = ('network_id', 'cidr')
339 62c6652f Stavros Sachtouris
340 62c6652f Stavros Sachtouris
    @errors.generic.all
341 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
342 62c6652f Stavros Sachtouris
    @errors.cyclades.network_id
343 62c6652f Stavros Sachtouris
    def _run(self, network_id, cidr):
344 62c6652f Stavros Sachtouris
        net = self.client.create_subnet(
345 62c6652f Stavros Sachtouris
            network_id, cidr,
346 62c6652f Stavros Sachtouris
            self['name'], self['allocation_pools'], self['gateway'],
347 62c6652f Stavros Sachtouris
            self['subnet_id'], self['ipv6'], self['enable_dhcp'])
348 62c6652f Stavros Sachtouris
        self._print(net, self.print_dict)
349 62c6652f Stavros Sachtouris
350 264a13f7 Stavros Sachtouris
    def main(self):
351 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
352 264a13f7 Stavros Sachtouris
        self._run(network_id=self['network_id'], cidr=self['cidr'])
353 62c6652f Stavros Sachtouris
354 62c6652f Stavros Sachtouris
355 62c6652f Stavros Sachtouris
# @command(subnet_cmds)
356 62c6652f Stavros Sachtouris
# class subnet_delete(_init_network, _optional_output_cmd):
357 62c6652f Stavros Sachtouris
#     """Delete a subnet"""
358 62c6652f Stavros Sachtouris
359 62c6652f Stavros Sachtouris
#     @errors.generic.all
360 62c6652f Stavros Sachtouris
#     @errors.cyclades.connection
361 62c6652f Stavros Sachtouris
#     def _run(self, subnet_id):
362 62c6652f Stavros Sachtouris
#         r = self.client.delete_subnet(subnet_id)
363 62c6652f Stavros Sachtouris
#         self._optional_output(r)
364 62c6652f Stavros Sachtouris
365 62c6652f Stavros Sachtouris
#     def main(self, subnet_id):
366 62c6652f Stavros Sachtouris
#         super(self.__class__, self)._run()
367 62c6652f Stavros Sachtouris
#         self._run(subnet_id=subnet_id)
368 62c6652f Stavros Sachtouris
369 62c6652f Stavros Sachtouris
370 62c6652f Stavros Sachtouris
@command(subnet_cmds)
371 264a13f7 Stavros Sachtouris
class subnet_modify(_init_network, _optional_json):
372 264a13f7 Stavros Sachtouris
    """Modify the attributes of a subnet"""
373 62c6652f Stavros Sachtouris
374 264a13f7 Stavros Sachtouris
    arguments = dict(
375 264a13f7 Stavros Sachtouris
        new_name=ValueArgument('New name of the subnet', '--name')
376 264a13f7 Stavros Sachtouris
    )
377 264a13f7 Stavros Sachtouris
    required = ['new_name']
378 62c6652f Stavros Sachtouris
379 62c6652f Stavros Sachtouris
    @errors.generic.all
380 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
381 62c6652f Stavros Sachtouris
    def _run(self, subnet_id):
382 2da652e2 Stavros Sachtouris
        r = self.client.update_subnet(subnet_id, name=self['new_name'])
383 62c6652f Stavros Sachtouris
        self._print(r, self.print_dict)
384 62c6652f Stavros Sachtouris
385 62c6652f Stavros Sachtouris
    def main(self, subnet_id):
386 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
387 62c6652f Stavros Sachtouris
        self._run(subnet_id=subnet_id)
388 447365fe Stavros Sachtouris
389 447365fe Stavros Sachtouris
390 447365fe Stavros Sachtouris
@command(port_cmds)
391 f3740b99 Stavros Sachtouris
class port_list(_init_network, _optional_json, _name_filter, _id_filter):
392 11cc86af Stavros Sachtouris
    """List all ports"""
393 447365fe Stavros Sachtouris
394 f3740b99 Stavros Sachtouris
    arguments = dict(
395 f3740b99 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
396 f3740b99 Stavros Sachtouris
        more=FlagArgument(
397 f3740b99 Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
398 f3740b99 Stavros Sachtouris
            '--more'),
399 f3740b99 Stavros Sachtouris
        user_id=ValueArgument(
400 f3740b99 Stavros Sachtouris
            'show only networks belonging to user with this id', '--user-id')
401 f3740b99 Stavros Sachtouris
    )
402 f3740b99 Stavros Sachtouris
403 447365fe Stavros Sachtouris
    @errors.generic.all
404 447365fe Stavros Sachtouris
    @errors.cyclades.connection
405 11cc86af Stavros Sachtouris
    def _run(self):
406 f3740b99 Stavros Sachtouris
        detail = bool(self['detail'] or self['user_id'])
407 f3740b99 Stavros Sachtouris
        ports = self.client.list_ports(detail=detail)
408 f3740b99 Stavros Sachtouris
        ports = self._filter_by_user_id(ports)
409 f3740b99 Stavros Sachtouris
        ports = self._filter_by_name(ports)
410 f3740b99 Stavros Sachtouris
        ports = self._filter_by_id(ports)
411 f3740b99 Stavros Sachtouris
        if detail and not self['detail']:
412 f3740b99 Stavros Sachtouris
            ports = [dict(
413 f3740b99 Stavros Sachtouris
                id=p['id'], name=p['name'], links=p['links']) for p in ports]
414 f3740b99 Stavros Sachtouris
        kwargs = dict()
415 f3740b99 Stavros Sachtouris
        if self['more']:
416 f3740b99 Stavros Sachtouris
            kwargs['out'] = StringIO()
417 f3740b99 Stavros Sachtouris
            kwargs['title'] = ()
418 f3740b99 Stavros Sachtouris
        self._print(ports, **kwargs)
419 f3740b99 Stavros Sachtouris
        if self['more']:
420 f3740b99 Stavros Sachtouris
            pager(kwargs['out'].getvalue())
421 447365fe Stavros Sachtouris
422 11cc86af Stavros Sachtouris
    def main(self):
423 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
424 11cc86af Stavros Sachtouris
        self._run()
425 447365fe Stavros Sachtouris
426 447365fe Stavros Sachtouris
427 447365fe Stavros Sachtouris
@command(port_cmds)
428 447365fe Stavros Sachtouris
class port_info(_init_network, _optional_json):
429 447365fe Stavros Sachtouris
    """Get details about a port"""
430 447365fe Stavros Sachtouris
431 447365fe Stavros Sachtouris
    @errors.generic.all
432 447365fe Stavros Sachtouris
    @errors.cyclades.connection
433 447365fe Stavros Sachtouris
    def _run(self, port_id):
434 f3740b99 Stavros Sachtouris
        port = self.client.get_port_details(port_id)
435 f3740b99 Stavros Sachtouris
        self._print(port, self.print_dict)
436 447365fe Stavros Sachtouris
437 447365fe Stavros Sachtouris
    def main(self, port_id):
438 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
439 447365fe Stavros Sachtouris
        self._run(port_id=port_id)
440 447365fe Stavros Sachtouris
441 447365fe Stavros Sachtouris
442 447365fe Stavros Sachtouris
@command(port_cmds)
443 f261965c Stavros Sachtouris
class port_delete(_init_network, _optional_output_cmd, _port_wait):
444 264a13f7 Stavros Sachtouris
    """Delete a port (== disconnect server from network)"""
445 447365fe Stavros Sachtouris
446 f261965c Stavros Sachtouris
    arguments = dict(
447 f261965c Stavros Sachtouris
        wait=FlagArgument('Wait port to be established', ('-w', '--wait'))
448 f261965c Stavros Sachtouris
    )
449 f261965c Stavros Sachtouris
450 447365fe Stavros Sachtouris
    @errors.generic.all
451 447365fe Stavros Sachtouris
    @errors.cyclades.connection
452 447365fe Stavros Sachtouris
    def _run(self, port_id):
453 f3740b99 Stavros Sachtouris
        if self['wait']:
454 f3740b99 Stavros Sachtouris
            status = self.client.get_port_details(port_id)['status']
455 447365fe Stavros Sachtouris
        r = self.client.delete_port(port_id)
456 f261965c Stavros Sachtouris
        if self['wait']:
457 f3740b99 Stavros Sachtouris
            try:
458 f3740b99 Stavros Sachtouris
                self._wait(port_id, status)
459 f3740b99 Stavros Sachtouris
            except ClientError as ce:
460 f3740b99 Stavros Sachtouris
                if ce.status not in (404, ):
461 f3740b99 Stavros Sachtouris
                    raise
462 f3740b99 Stavros Sachtouris
                self.error('Port %s is deleted' % port_id)
463 447365fe Stavros Sachtouris
        self._optional_output(r)
464 447365fe Stavros Sachtouris
465 447365fe Stavros Sachtouris
    def main(self, port_id):
466 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
467 447365fe Stavros Sachtouris
        self._run(port_id=port_id)
468 447365fe Stavros Sachtouris
469 447365fe Stavros Sachtouris
470 447365fe Stavros Sachtouris
@command(port_cmds)
471 264a13f7 Stavros Sachtouris
class port_modify(_init_network, _optional_json):
472 264a13f7 Stavros Sachtouris
    """Modify the attributes of a port"""
473 447365fe Stavros Sachtouris
474 264a13f7 Stavros Sachtouris
    arguments = dict(new_name=ValueArgument('New name of the port', '--name'))
475 264a13f7 Stavros Sachtouris
    required = ['new_name', ]
476 447365fe Stavros Sachtouris
477 447365fe Stavros Sachtouris
    @errors.generic.all
478 447365fe Stavros Sachtouris
    @errors.cyclades.connection
479 447365fe Stavros Sachtouris
    def _run(self, port_id):
480 447365fe Stavros Sachtouris
        r = self.client.get_port_details(port_id)
481 447365fe Stavros Sachtouris
        r = self.client.update_port(
482 264a13f7 Stavros Sachtouris
            port_id, r['network_id'], name=self['new_name'])
483 447365fe Stavros Sachtouris
        self._print(r, self.print_dict)
484 447365fe Stavros Sachtouris
485 447365fe Stavros Sachtouris
    def main(self, port_id):
486 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
487 447365fe Stavros Sachtouris
        self._run(port_id=port_id)
488 447365fe Stavros Sachtouris
489 447365fe Stavros Sachtouris
490 17cfc2f0 Stavros Sachtouris
class _port_create(_init_network, _optional_json, _port_wait):
491 fd981f77 Stavros Sachtouris
492 17cfc2f0 Stavros Sachtouris
    def connect(self, network_id, device_id):
493 909ae594 Stavros Sachtouris
        fixed_ips = [dict(ip_address=self['ip_address'])] if (
494 cc5da5a5 Stavros Sachtouris
            self['ip_address']) else None
495 909ae594 Stavros Sachtouris
        if fixed_ips and self['subnet_id']:
496 909ae594 Stavros Sachtouris
            fixed_ips[0]['subnet_id'] = self['subnet_id']
497 fd981f77 Stavros Sachtouris
        r = self.client.create_port(
498 fd981f77 Stavros Sachtouris
            network_id, device_id,
499 fd981f77 Stavros Sachtouris
            name=self['name'],
500 fd981f77 Stavros Sachtouris
            security_groups=self['security_group_id'],
501 fd981f77 Stavros Sachtouris
            fixed_ips=fixed_ips)
502 fd981f77 Stavros Sachtouris
        if self['wait']:
503 fd981f77 Stavros Sachtouris
            self._wait(r['id'], r['status'])
504 f3740b99 Stavros Sachtouris
            r = self.client.get_port_details(r['id'])
505 f3740b99 Stavros Sachtouris
        self._print([r])
506 fd981f77 Stavros Sachtouris
507 fd981f77 Stavros Sachtouris
508 ccdd1b82 Stavros Sachtouris
@command(port_cmds)
509 f25bd53b Stavros Sachtouris
class port_create(_port_create):
510 264a13f7 Stavros Sachtouris
    """Create a new port (== connect server to network)"""
511 ccdd1b82 Stavros Sachtouris
512 ccdd1b82 Stavros Sachtouris
    arguments = dict(
513 b7d79306 Stavros Sachtouris
        name=ValueArgument('A human readable name', '--name'),
514 ccdd1b82 Stavros Sachtouris
        security_group_id=RepeatableArgument(
515 ccdd1b82 Stavros Sachtouris
            'Add a security group id (can be repeated)',
516 b7d79306 Stavros Sachtouris
            ('-g', '--security-group')),
517 b7d79306 Stavros Sachtouris
        subnet_id=ValueArgument(
518 b7d79306 Stavros Sachtouris
            'Subnet id for fixed ips (used with --ip-address)',
519 b7d79306 Stavros Sachtouris
            '--subnet-id'),
520 b7d79306 Stavros Sachtouris
        ip_address=ValueArgument(
521 909ae594 Stavros Sachtouris
            'IP address for subnet id', '--ip-address'),
522 264a13f7 Stavros Sachtouris
        network_id=ValueArgument('Set the network ID', '--network-id'),
523 264a13f7 Stavros Sachtouris
        device_id=ValueArgument(
524 264a13f7 Stavros Sachtouris
            'The device is either a virtual server or a virtual router',
525 c6afee48 Stavros Sachtouris
            '--device-id'),
526 c6afee48 Stavros Sachtouris
        wait=FlagArgument('Wait port to be established', ('-w', '--wait')),
527 ccdd1b82 Stavros Sachtouris
    )
528 e3f54dc0 Stavros Sachtouris
    required = ('network_id', 'device_id')
529 ccdd1b82 Stavros Sachtouris
530 17cfc2f0 Stavros Sachtouris
    @errors.generic.all
531 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.connection
532 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.network_id
533 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.server_id
534 17cfc2f0 Stavros Sachtouris
    def _run(self, network_id, server_id):
535 17cfc2f0 Stavros Sachtouris
        self.connect(network_id, server_id)
536 17cfc2f0 Stavros Sachtouris
537 264a13f7 Stavros Sachtouris
    def main(self):
538 ccdd1b82 Stavros Sachtouris
        super(self.__class__, self)._run()
539 17cfc2f0 Stavros Sachtouris
        self._run(network_id=self['network_id'], server_id=self['device_id'])
540 264a13f7 Stavros Sachtouris
541 264a13f7 Stavros Sachtouris
542 c6afee48 Stavros Sachtouris
@command(port_cmds)
543 c6afee48 Stavros Sachtouris
class port_wait(_init_network, _port_wait):
544 c3d42104 Stavros Sachtouris
    """Wait for port to finish (default: BUILD)"""
545 c6afee48 Stavros Sachtouris
546 c6afee48 Stavros Sachtouris
    arguments = dict(
547 c3d42104 Stavros Sachtouris
        port_status=StatusArgument(
548 c3d42104 Stavros Sachtouris
            'Wait while in this status (%s, default: %s)' % (
549 c3d42104 Stavros Sachtouris
                ', '.join(port_states), port_states[0]),
550 c3d42104 Stavros Sachtouris
            '--status',
551 c3d42104 Stavros Sachtouris
            valid_states=port_states),
552 c6afee48 Stavros Sachtouris
        timeout=IntArgument(
553 c6afee48 Stavros Sachtouris
            'Wait limit in seconds (default: 60)', '--timeout', default=60)
554 c6afee48 Stavros Sachtouris
    )
555 c6afee48 Stavros Sachtouris
556 c6afee48 Stavros Sachtouris
    @errors.generic.all
557 c6afee48 Stavros Sachtouris
    @errors.cyclades.connection
558 c3d42104 Stavros Sachtouris
    def _run(self, port_id, port_status):
559 c6afee48 Stavros Sachtouris
        port = self.client.get_port_details(port_id)
560 c3d42104 Stavros Sachtouris
        if port['status'].lower() == port_status.lower():
561 c3d42104 Stavros Sachtouris
            self._wait(port_id, port_status, timeout=self['timeout'])
562 c6afee48 Stavros Sachtouris
        else:
563 c6afee48 Stavros Sachtouris
            self.error(
564 c6afee48 Stavros Sachtouris
                'Port %s: Cannot wait for status %s, '
565 c6afee48 Stavros Sachtouris
                'status is already %s' % (
566 c3d42104 Stavros Sachtouris
                    port_id, port_status, port['status']))
567 c6afee48 Stavros Sachtouris
568 dbf65aaf Stavros Sachtouris
    def main(self, port_id):
569 c6afee48 Stavros Sachtouris
        super(self.__class__, self)._run()
570 c3d42104 Stavros Sachtouris
        port_status = self['port_status'] or port_states[0]
571 c3d42104 Stavros Sachtouris
        self._run(port_id=port_id, port_status=port_status)
572 c6afee48 Stavros Sachtouris
573 c6afee48 Stavros Sachtouris
574 d1bced10 Stavros Sachtouris
@command(ip_cmds)
575 d1bced10 Stavros Sachtouris
class ip_list(_init_network, _optional_json):
576 d1bced10 Stavros Sachtouris
    """List reserved floating IPs"""
577 d1bced10 Stavros Sachtouris
578 d1bced10 Stavros Sachtouris
    @errors.generic.all
579 d1bced10 Stavros Sachtouris
    @errors.cyclades.connection
580 d1bced10 Stavros Sachtouris
    def _run(self):
581 d1bced10 Stavros Sachtouris
        self._print(self.client.list_floatingips())
582 d1bced10 Stavros Sachtouris
583 d1bced10 Stavros Sachtouris
    def main(self):
584 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
585 d1bced10 Stavros Sachtouris
        self._run()
586 d1bced10 Stavros Sachtouris
587 d1bced10 Stavros Sachtouris
588 d1bced10 Stavros Sachtouris
@command(ip_cmds)
589 d1bced10 Stavros Sachtouris
class ip_info(_init_network, _optional_json):
590 d1bced10 Stavros Sachtouris
    """Get details on a floating IP"""
591 d1bced10 Stavros Sachtouris
592 d1bced10 Stavros Sachtouris
    @errors.generic.all
593 d1bced10 Stavros Sachtouris
    @errors.cyclades.connection
594 d1bced10 Stavros Sachtouris
    def _run(self, ip_id):
595 291cab21 Stavros Sachtouris
        self._print(
596 291cab21 Stavros Sachtouris
            self.client.get_floatingip_details(ip_id), self.print_dict)
597 d1bced10 Stavros Sachtouris
598 d1bced10 Stavros Sachtouris
    def main(self, ip_id):
599 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
600 d1bced10 Stavros Sachtouris
        self._run(ip_id=ip_id)
601 d1bced10 Stavros Sachtouris
602 d1bced10 Stavros Sachtouris
603 d1bced10 Stavros Sachtouris
@command(ip_cmds)
604 d1bced10 Stavros Sachtouris
class ip_create(_init_network, _optional_json):
605 d1bced10 Stavros Sachtouris
    """Reserve an IP on a network"""
606 264a13f7 Stavros Sachtouris
607 d1bced10 Stavros Sachtouris
    arguments = dict(
608 d1bced10 Stavros Sachtouris
        network_id=ValueArgument(
609 d1bced10 Stavros Sachtouris
            'The network to preserve the IP on', '--network-id'),
610 cc5da5a5 Stavros Sachtouris
        ip_address=ValueArgument('Allocate an IP address', '--address')
611 d1bced10 Stavros Sachtouris
    )
612 d1bced10 Stavros Sachtouris
    required = ('network_id', )
613 d1bced10 Stavros Sachtouris
614 d1bced10 Stavros Sachtouris
    @errors.generic.all
615 d1bced10 Stavros Sachtouris
    @errors.cyclades.connection
616 d1bced10 Stavros Sachtouris
    @errors.cyclades.network_id
617 d1bced10 Stavros Sachtouris
    def _run(self, network_id):
618 d1bced10 Stavros Sachtouris
        self._print(
619 d1bced10 Stavros Sachtouris
            self.client.create_floatingip(
620 d1bced10 Stavros Sachtouris
                network_id, floating_ip_address=self['ip_address']),
621 d1bced10 Stavros Sachtouris
            self.print_dict)
622 d1bced10 Stavros Sachtouris
623 d1bced10 Stavros Sachtouris
    def main(self):
624 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
625 d1bced10 Stavros Sachtouris
        self._run(network_id=self['network_id'])
626 d1bced10 Stavros Sachtouris
627 d1bced10 Stavros Sachtouris
628 d1bced10 Stavros Sachtouris
@command(ip_cmds)
629 d1bced10 Stavros Sachtouris
class ip_delete(_init_network, _optional_output_cmd):
630 d1bced10 Stavros Sachtouris
    """Unreserve an IP (also delete the port, if attached)"""
631 d1bced10 Stavros Sachtouris
632 d1bced10 Stavros Sachtouris
    def _run(self, ip_id):
633 291cab21 Stavros Sachtouris
        self._optional_output(self.client.delete_floatingip(ip_id))
634 d1bced10 Stavros Sachtouris
635 d1bced10 Stavros Sachtouris
    def main(self, ip_id):
636 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
637 d1bced10 Stavros Sachtouris
        self._run(ip_id=ip_id)
638 d1bced10 Stavros Sachtouris
639 d1bced10 Stavros Sachtouris
640 cc5da5a5 Stavros Sachtouris
@command(ip_cmds)
641 cc5da5a5 Stavros Sachtouris
class ip_attach(_port_create):
642 cc5da5a5 Stavros Sachtouris
    """Attach an IP on a virtual server"""
643 cc5da5a5 Stavros Sachtouris
644 cc5da5a5 Stavros Sachtouris
    arguments = dict(
645 cc5da5a5 Stavros Sachtouris
        name=ValueArgument('A human readable name for the port', '--name'),
646 cc5da5a5 Stavros Sachtouris
        security_group_id=RepeatableArgument(
647 cc5da5a5 Stavros Sachtouris
            'Add a security group id (can be repeated)',
648 cc5da5a5 Stavros Sachtouris
            ('-g', '--security-group')),
649 cc5da5a5 Stavros Sachtouris
        subnet_id=ValueArgument('Subnet id', '--subnet-id'),
650 cc5da5a5 Stavros Sachtouris
        wait=FlagArgument('Wait IP to be attached', ('-w', '--wait')),
651 cc5da5a5 Stavros Sachtouris
        server_id=ValueArgument(
652 cc5da5a5 Stavros Sachtouris
            'Server to attach to this IP', '--server-id')
653 cc5da5a5 Stavros Sachtouris
    )
654 cc5da5a5 Stavros Sachtouris
    required = ('server_id', )
655 cc5da5a5 Stavros Sachtouris
656 cc5da5a5 Stavros Sachtouris
    @errors.generic.all
657 cc5da5a5 Stavros Sachtouris
    @errors.cyclades.connection
658 cc5da5a5 Stavros Sachtouris
    @errors.cyclades.server_id
659 58f4caba Stavros Sachtouris
    def _run(self, ip_or_ip_id, server_id):
660 cc5da5a5 Stavros Sachtouris
        netid = None
661 cc5da5a5 Stavros Sachtouris
        for ip in self.client.list_floatingips():
662 58f4caba Stavros Sachtouris
            if ip_or_ip_id in (ip['floating_ip_address'], ip['id']):
663 cc5da5a5 Stavros Sachtouris
                netid = ip['floating_network_id']
664 cc5da5a5 Stavros Sachtouris
                iparg = ValueArgument(parsed_name='--ip')
665 58f4caba Stavros Sachtouris
                iparg.value = ip['floating_ip_address']
666 cc5da5a5 Stavros Sachtouris
                self.arguments['ip_address'] = iparg
667 cc5da5a5 Stavros Sachtouris
                break
668 cc5da5a5 Stavros Sachtouris
        if netid:
669 cc5da5a5 Stavros Sachtouris
            self.error('Creating a port to attach IP %s to server %s' % (
670 58f4caba Stavros Sachtouris
                ip_or_ip_id, server_id))
671 cc5da5a5 Stavros Sachtouris
            self.connect(netid, server_id)
672 cc5da5a5 Stavros Sachtouris
        else:
673 cc5da5a5 Stavros Sachtouris
            raiseCLIError(
674 58f4caba Stavros Sachtouris
                '%s does not match any reserved IPs or IP ids' % ip_or_ip_id,
675 cc5da5a5 Stavros Sachtouris
                details=[
676 cc5da5a5 Stavros Sachtouris
                    'To reserve an IP:', '  [kamaki] ip create',
677 cc5da5a5 Stavros Sachtouris
                    'To see all reserved IPs:', '  [kamaki] ip list'])
678 cc5da5a5 Stavros Sachtouris
679 58f4caba Stavros Sachtouris
    def main(self, ip_or_ip_id):
680 cc5da5a5 Stavros Sachtouris
        super(self.__class__, self)._run()
681 58f4caba Stavros Sachtouris
        self._run(ip_or_ip_id=ip_or_ip_id, server_id=self['server_id'])
682 cc5da5a5 Stavros Sachtouris
683 cc5da5a5 Stavros Sachtouris
684 cc5da5a5 Stavros Sachtouris
@command(ip_cmds)
685 cc5da5a5 Stavros Sachtouris
class ip_detach(_init_network, _port_wait, _optional_json):
686 cc5da5a5 Stavros Sachtouris
    """Detach an IP from a virtual server"""
687 cc5da5a5 Stavros Sachtouris
688 cc5da5a5 Stavros Sachtouris
    arguments = dict(
689 cc5da5a5 Stavros Sachtouris
        wait=FlagArgument('Wait network to disconnect', ('-w', '--wait')),
690 cc5da5a5 Stavros Sachtouris
    )
691 cc5da5a5 Stavros Sachtouris
692 cc5da5a5 Stavros Sachtouris
    @errors.generic.all
693 cc5da5a5 Stavros Sachtouris
    @errors.cyclades.connection
694 58f4caba Stavros Sachtouris
    def _run(self, ip_or_ip_id):
695 cc5da5a5 Stavros Sachtouris
        for ip in self.client.list_floatingips():
696 58f4caba Stavros Sachtouris
            if ip_or_ip_id in (ip['floating_ip_address'], ip['id']):
697 cc5da5a5 Stavros Sachtouris
                if not ip['port_id']:
698 58f4caba Stavros Sachtouris
                    raiseCLIError('IP %s is not attached' % ip_or_ip_id)
699 cc5da5a5 Stavros Sachtouris
                self.error('Deleting port %s:' % ip['port_id'])
700 cc5da5a5 Stavros Sachtouris
                self.client.delete_port(ip['port_id'])
701 cc5da5a5 Stavros Sachtouris
                if self['wait']:
702 cc5da5a5 Stavros Sachtouris
                    port_status = self.client.get_port_details(ip['port_id'])[
703 cc5da5a5 Stavros Sachtouris
                        'status']
704 cc5da5a5 Stavros Sachtouris
                    try:
705 cc5da5a5 Stavros Sachtouris
                        self._wait(ip['port_id'], port_status)
706 cc5da5a5 Stavros Sachtouris
                    except ClientError as ce:
707 cc5da5a5 Stavros Sachtouris
                        if ce.status not in (404, ):
708 cc5da5a5 Stavros Sachtouris
                            raise
709 cc5da5a5 Stavros Sachtouris
                        self.error('Port %s is deleted' % ip['port_id'])
710 cc5da5a5 Stavros Sachtouris
                return
711 58f4caba Stavros Sachtouris
        raiseCLIError('IP or IP id %s not found' % ip_or_ip_id)
712 cc5da5a5 Stavros Sachtouris
713 58f4caba Stavros Sachtouris
    def main(self, ip_or_ip_id):
714 cc5da5a5 Stavros Sachtouris
        super(self.__class__, self)._run()
715 58f4caba Stavros Sachtouris
        self._run(ip_or_ip_id)
716 cc5da5a5 Stavros Sachtouris
717 cc5da5a5 Stavros Sachtouris
718 d1bced10 Stavros Sachtouris
#  Warn users for some importand changes
719 264a13f7 Stavros Sachtouris
720 264a13f7 Stavros Sachtouris
@command(network_cmds)
721 fd981f77 Stavros Sachtouris
class network_connect(_port_create):
722 fd981f77 Stavros Sachtouris
    """Connect a network with a device (server or router)"""
723 264a13f7 Stavros Sachtouris
724 fd981f77 Stavros Sachtouris
    arguments = dict(
725 17cfc2f0 Stavros Sachtouris
        name=ValueArgument('A human readable name for the port', '--name'),
726 fd981f77 Stavros Sachtouris
        security_group_id=RepeatableArgument(
727 fd981f77 Stavros Sachtouris
            'Add a security group id (can be repeated)',
728 fd981f77 Stavros Sachtouris
            ('-g', '--security-group')),
729 fd981f77 Stavros Sachtouris
        subnet_id=ValueArgument(
730 fd981f77 Stavros Sachtouris
            'Subnet id for fixed ips (used with --ip-address)',
731 fd981f77 Stavros Sachtouris
            '--subnet-id'),
732 fd981f77 Stavros Sachtouris
        ip_address=ValueArgument(
733 fd981f77 Stavros Sachtouris
            'IP address for subnet id (used with --subnet-id', '--ip-address'),
734 17cfc2f0 Stavros Sachtouris
        wait=FlagArgument('Wait network to connect', ('-w', '--wait')),
735 7a3c66e1 Stavros Sachtouris
        device_id=RepeatableArgument(
736 7a3c66e1 Stavros Sachtouris
            'Connect this device to the network (can be repeated)',
737 7a3c66e1 Stavros Sachtouris
            '--device-id')
738 fd981f77 Stavros Sachtouris
    )
739 7a3c66e1 Stavros Sachtouris
    required = ('device_id', )
740 fd981f77 Stavros Sachtouris
741 17cfc2f0 Stavros Sachtouris
    @errors.generic.all
742 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.connection
743 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.network_id
744 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.server_id
745 17cfc2f0 Stavros Sachtouris
    def _run(self, network_id, server_id):
746 f3740b99 Stavros Sachtouris
        self.error('Creating a port to connect network %s with device %s' % (
747 f3740b99 Stavros Sachtouris
            network_id, server_id))
748 17cfc2f0 Stavros Sachtouris
        self.connect(network_id, server_id)
749 17cfc2f0 Stavros Sachtouris
750 7a3c66e1 Stavros Sachtouris
    def main(self, network_id):
751 fd981f77 Stavros Sachtouris
        super(self.__class__, self)._run()
752 7a3c66e1 Stavros Sachtouris
        for sid in self['device_id']:
753 7a3c66e1 Stavros Sachtouris
            self._run(network_id=network_id, server_id=sid)
754 264a13f7 Stavros Sachtouris
755 264a13f7 Stavros Sachtouris
756 264a13f7 Stavros Sachtouris
@command(network_cmds)
757 17cfc2f0 Stavros Sachtouris
class network_disconnect(_init_network, _port_wait, _optional_json):
758 6318da0c Dionysis Grigoropoulos
    """Disconnect a network from a device"""
759 264a13f7 Stavros Sachtouris
760 fd981f77 Stavros Sachtouris
    def _cyclades_client(self):
761 fd981f77 Stavros Sachtouris
        auth = getattr(self, 'auth_base')
762 fd981f77 Stavros Sachtouris
        endpoints = auth.get_service_endpoints('compute')
763 fd981f77 Stavros Sachtouris
        URL = endpoints['publicURL']
764 fd981f77 Stavros Sachtouris
        from kamaki.clients.cyclades import CycladesClient
765 fd981f77 Stavros Sachtouris
        return CycladesClient(URL, self.client.token)
766 fd981f77 Stavros Sachtouris
767 17cfc2f0 Stavros Sachtouris
    arguments = dict(
768 7a3c66e1 Stavros Sachtouris
        wait=FlagArgument('Wait network to disconnect', ('-w', '--wait')),
769 7a3c66e1 Stavros Sachtouris
        device_id=RepeatableArgument(
770 7a3c66e1 Stavros Sachtouris
            'Disconnect device from the network (can be repeated)',
771 7a3c66e1 Stavros Sachtouris
            '--device-id')
772 17cfc2f0 Stavros Sachtouris
    )
773 7a3c66e1 Stavros Sachtouris
    required = ('device_id', )
774 17cfc2f0 Stavros Sachtouris
775 fd981f77 Stavros Sachtouris
    @errors.generic.all
776 fd981f77 Stavros Sachtouris
    @errors.cyclades.connection
777 fd981f77 Stavros Sachtouris
    @errors.cyclades.network_id
778 fd981f77 Stavros Sachtouris
    @errors.cyclades.server_id
779 f3740b99 Stavros Sachtouris
    def _run(self, network_id, server_id):
780 f3740b99 Stavros Sachtouris
        vm = self._cyclades_client().get_server_details(server_id)
781 f3740b99 Stavros Sachtouris
        ports = [port for port in vm['attachments'] if (
782 7a3c66e1 Stavros Sachtouris
            port['network_id'] in (network_id, ))]
783 f3740b99 Stavros Sachtouris
        if not ports:
784 fd981f77 Stavros Sachtouris
            raiseCLIError('Network %s is not connected to device %s' % (
785 f3740b99 Stavros Sachtouris
                network_id, server_id))
786 f3740b99 Stavros Sachtouris
        for port in ports:
787 f3740b99 Stavros Sachtouris
            if self['wait']:
788 f3740b99 Stavros Sachtouris
                port['status'] = self.client.get_port_details(port['id'])[
789 f3740b99 Stavros Sachtouris
                    'status']
790 f3740b99 Stavros Sachtouris
            self.client.delete_port(port['id'])
791 f3740b99 Stavros Sachtouris
            self.error('Deleting port %s:' % port['id'])
792 f3740b99 Stavros Sachtouris
            self.print_dict(port)
793 17cfc2f0 Stavros Sachtouris
            if self['wait']:
794 f3740b99 Stavros Sachtouris
                try:
795 f3740b99 Stavros Sachtouris
                    self._wait(port['id'], port['status'])
796 f3740b99 Stavros Sachtouris
                except ClientError as ce:
797 f3740b99 Stavros Sachtouris
                    if ce.status not in (404, ):
798 f3740b99 Stavros Sachtouris
                        raise
799 f3740b99 Stavros Sachtouris
                    self.error('Port %s is deleted' % port['id'])
800 fd981f77 Stavros Sachtouris
801 7a3c66e1 Stavros Sachtouris
    def main(self, network_id):
802 fd981f77 Stavros Sachtouris
        super(self.__class__, self)._run()
803 7a3c66e1 Stavros Sachtouris
        for sid in self['device_id']:
804 7a3c66e1 Stavros Sachtouris
            self._run(network_id=network_id, server_id=sid)