Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / network.py @ d07e6fc2

History | View | Annotate | Download (21.3 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 cd0927f7 Stavros Sachtouris
from kamaki.clients.cyclades import CycladesNetworkClient
42 6f2b87c1 Stavros Sachtouris
from kamaki.cli.argument import (
43 6f2b87c1 Stavros Sachtouris
    FlagArgument, ValueArgument, RepeatableArgument, IntArgument)
44 d18e6439 Stavros Sachtouris
from kamaki.cli.commands import _command_init, errors, addLogSettings
45 d18e6439 Stavros Sachtouris
from kamaki.cli.commands import (
46 d18e6439 Stavros Sachtouris
    _optional_output_cmd, _optional_json, _name_filter, _id_filter)
47 7e57e590 Stavros Sachtouris
from kamaki.cli.utils import filter_dicts_by_dict
48 6f2b87c1 Stavros Sachtouris
from kamaki.cli.commands.cyclades import _service_wait
49 d18e6439 Stavros Sachtouris
50 d18e6439 Stavros Sachtouris
51 d18e6439 Stavros Sachtouris
network_cmds = CommandTree('network', 'Networking API network commands')
52 d18e6439 Stavros Sachtouris
port_cmds = CommandTree('port', 'Networking API network commands')
53 d18e6439 Stavros Sachtouris
subnet_cmds = CommandTree('subnet', 'Networking API network commands')
54 d1bced10 Stavros Sachtouris
ip_cmds = CommandTree('ip', 'Networking 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 d18e6439 Stavros Sachtouris
    \n* to check authentication: /user authenticate\
60 d18e6439 Stavros Sachtouris
    \n* to set authentication token: /config set cloud.<cloud>.token <token>'
61 d18e6439 Stavros Sachtouris
62 d18e6439 Stavros Sachtouris
63 c6afee48 Stavros Sachtouris
class _port_wait(_service_wait):
64 c6afee48 Stavros Sachtouris
65 c6afee48 Stavros Sachtouris
    def _wait(self, port_id, current_status, timeout=60):
66 c6afee48 Stavros Sachtouris
        super(_port_wait, self)._wait(
67 c6afee48 Stavros Sachtouris
            'Port', port_id, self.client.wait_port, current_status,
68 c6afee48 Stavros Sachtouris
            timeout=timeout)
69 c6afee48 Stavros Sachtouris
70 c6afee48 Stavros Sachtouris
71 5c433331 Stavros Sachtouris
class _init_network(_command_init):
72 bc4662d8 Stavros Sachtouris
    @errors.generic.all
73 bc4662d8 Stavros Sachtouris
    @addLogSettings
74 bc4662d8 Stavros Sachtouris
    def _run(self, service='network'):
75 bc4662d8 Stavros Sachtouris
        if getattr(self, 'cloud', None):
76 bc4662d8 Stavros Sachtouris
            base_url = self._custom_url(service) or self._custom_url(
77 264a13f7 Stavros Sachtouris
                'network')
78 bc4662d8 Stavros Sachtouris
            if base_url:
79 bc4662d8 Stavros Sachtouris
                token = self._custom_token(service) or self._custom_token(
80 264a13f7 Stavros Sachtouris
                    'network') or self.config.get_cloud('token')
81 cd0927f7 Stavros Sachtouris
                self.client = CycladesNetworkClient(
82 bc4662d8 Stavros Sachtouris
                  base_url=base_url, token=token)
83 bc4662d8 Stavros Sachtouris
                return
84 bc4662d8 Stavros Sachtouris
        else:
85 bc4662d8 Stavros Sachtouris
            self.cloud = 'default'
86 bc4662d8 Stavros Sachtouris
        if getattr(self, 'auth_base', False):
87 cec2dfcd Stavros Sachtouris
            network_endpoints = self.auth_base.get_service_endpoints(
88 264a13f7 Stavros Sachtouris
                self._custom_type('network') or 'network',
89 264a13f7 Stavros Sachtouris
                self._custom_version('network') or '')
90 cec2dfcd Stavros Sachtouris
            base_url = network_endpoints['publicURL']
91 bc4662d8 Stavros Sachtouris
            token = self.auth_base.token
92 cd0927f7 Stavros Sachtouris
            self.client = CycladesNetworkClient(base_url=base_url, token=token)
93 bc4662d8 Stavros Sachtouris
        else:
94 bc4662d8 Stavros Sachtouris
            raise CLIBaseUrlError(service='network')
95 bc4662d8 Stavros Sachtouris
96 bc4662d8 Stavros Sachtouris
    def main(self):
97 bc4662d8 Stavros Sachtouris
        self._run()
98 d18e6439 Stavros Sachtouris
99 d18e6439 Stavros Sachtouris
100 d18e6439 Stavros Sachtouris
@command(network_cmds)
101 5c433331 Stavros Sachtouris
class network_list(_init_network, _optional_json, _name_filter, _id_filter):
102 d18e6439 Stavros Sachtouris
    """List networks
103 d18e6439 Stavros Sachtouris
    Use filtering arguments (e.g., --name-like) to manage long server lists
104 d18e6439 Stavros Sachtouris
    """
105 d18e6439 Stavros Sachtouris
106 d18e6439 Stavros Sachtouris
    arguments = dict(
107 d18e6439 Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
108 cd40143a Stavros Sachtouris
        more=FlagArgument(
109 cd40143a Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
110 cd40143a Stavros Sachtouris
            '--more'),
111 7e57e590 Stavros Sachtouris
        user_id=ValueArgument(
112 7e57e590 Stavros Sachtouris
            'show only networks belonging to user with this id', '--user-id')
113 d18e6439 Stavros Sachtouris
    )
114 d18e6439 Stavros Sachtouris
115 7e57e590 Stavros Sachtouris
    def _filter_by_user_id(self, nets):
116 7e57e590 Stavros Sachtouris
        return filter_dicts_by_dict(nets, dict(user_id=self['user_id'])) if (
117 7e57e590 Stavros Sachtouris
            self['user_id']) else nets
118 7e57e590 Stavros Sachtouris
119 d18e6439 Stavros Sachtouris
    @errors.generic.all
120 d18e6439 Stavros Sachtouris
    @errors.cyclades.connection
121 d18e6439 Stavros Sachtouris
    def _run(self):
122 264a13f7 Stavros Sachtouris
        nets = self.client.list_networks()
123 7e57e590 Stavros Sachtouris
        nets = self._filter_by_user_id(nets)
124 77bf75fe Stavros Sachtouris
        nets = self._filter_by_name(nets)
125 77bf75fe Stavros Sachtouris
        nets = self._filter_by_id(nets)
126 264a13f7 Stavros Sachtouris
        if not self['detail']:
127 7e57e590 Stavros Sachtouris
            nets = [dict(
128 7e57e590 Stavros Sachtouris
                id=n['id'], name=n['name'], links=n['links']) for n in nets]
129 cd40143a Stavros Sachtouris
        kwargs = dict()
130 cd40143a Stavros Sachtouris
        if self['more']:
131 cd40143a Stavros Sachtouris
            kwargs['out'] = StringIO()
132 cd40143a Stavros Sachtouris
            kwargs['title'] = ()
133 cd40143a Stavros Sachtouris
        self._print(nets, **kwargs)
134 cd40143a Stavros Sachtouris
        if self['more']:
135 cd40143a Stavros Sachtouris
            pager(kwargs['out'].getvalue())
136 d18e6439 Stavros Sachtouris
137 d18e6439 Stavros Sachtouris
    def main(self):
138 d18e6439 Stavros Sachtouris
        super(self.__class__, self)._run()
139 d18e6439 Stavros Sachtouris
        self._run()
140 cd40143a Stavros Sachtouris
141 cd40143a Stavros Sachtouris
142 cd40143a Stavros Sachtouris
@command(network_cmds)
143 5c433331 Stavros Sachtouris
class network_info(_init_network, _optional_json):
144 cd40143a Stavros Sachtouris
    """Get details about a network"""
145 cd40143a Stavros Sachtouris
146 cd40143a Stavros Sachtouris
    @errors.generic.all
147 cd40143a Stavros Sachtouris
    @errors.cyclades.connection
148 cd40143a Stavros Sachtouris
    @errors.cyclades.network_id
149 cd40143a Stavros Sachtouris
    def _run(self, network_id):
150 cd40143a Stavros Sachtouris
        net = self.client.get_network_details(network_id)
151 cd40143a Stavros Sachtouris
        self._print(net, self.print_dict)
152 cd40143a Stavros Sachtouris
153 cd40143a Stavros Sachtouris
    def main(self, network_id):
154 cd40143a Stavros Sachtouris
        super(self.__class__, self)._run()
155 cd40143a Stavros Sachtouris
        self._run(network_id=network_id)
156 49413939 Stavros Sachtouris
157 49413939 Stavros Sachtouris
158 264a13f7 Stavros Sachtouris
class NetworkTypeArgument(ValueArgument):
159 264a13f7 Stavros Sachtouris
160 1c366ac9 Stavros Sachtouris
    types = ('MAC_FILTERED', 'CUSTOM', 'IP_LESS_ROUTED', 'PHYSICAL_VLAN')
161 264a13f7 Stavros Sachtouris
162 264a13f7 Stavros Sachtouris
    @property
163 264a13f7 Stavros Sachtouris
    def value(self):
164 1c366ac9 Stavros Sachtouris
        return getattr(self, '_value', self.types[0])
165 264a13f7 Stavros Sachtouris
166 264a13f7 Stavros Sachtouris
    @value.setter
167 264a13f7 Stavros Sachtouris
    def value(self, new_value):
168 264a13f7 Stavros Sachtouris
        if new_value and new_value.upper() in self.types:
169 264a13f7 Stavros Sachtouris
            self._value = new_value.upper()
170 264a13f7 Stavros Sachtouris
        elif new_value:
171 264a13f7 Stavros Sachtouris
            raise CLIInvalidArgument(
172 264a13f7 Stavros Sachtouris
                'Invalid network type %s' % new_value, details=[
173 264a13f7 Stavros Sachtouris
                    'Valid types: %s' % ', '.join(self.types), ])
174 264a13f7 Stavros Sachtouris
175 264a13f7 Stavros Sachtouris
176 49413939 Stavros Sachtouris
@command(network_cmds)
177 67dfe4a2 Stavros Sachtouris
class network_create(_init_network, _optional_json):
178 1c366ac9 Stavros Sachtouris
    """Create a new network (default type: MAC_FILTERED)"""
179 49413939 Stavros Sachtouris
180 cd0927f7 Stavros Sachtouris
    arguments = dict(
181 cd0927f7 Stavros Sachtouris
        name=ValueArgument('Network name', '--name'),
182 cd0927f7 Stavros Sachtouris
        shared=FlagArgument(
183 264a13f7 Stavros Sachtouris
            'Make network shared (special privileges required)', '--shared'),
184 264a13f7 Stavros Sachtouris
        network_type=NetworkTypeArgument(
185 264a13f7 Stavros Sachtouris
            'Valid network types: %s' % (', '.join(NetworkTypeArgument.types)),
186 67dfe4a2 Stavros Sachtouris
            '--type')
187 49413939 Stavros Sachtouris
    )
188 49413939 Stavros Sachtouris
189 49413939 Stavros Sachtouris
    @errors.generic.all
190 49413939 Stavros Sachtouris
    @errors.cyclades.connection
191 cd0927f7 Stavros Sachtouris
    @errors.cyclades.network_type
192 cd0927f7 Stavros Sachtouris
    def _run(self, network_type):
193 49413939 Stavros Sachtouris
        net = self.client.create_network(
194 cd0927f7 Stavros Sachtouris
            network_type, name=self['name'], shared=self['shared'])
195 49413939 Stavros Sachtouris
        self._print(net, self.print_dict)
196 49413939 Stavros Sachtouris
197 264a13f7 Stavros Sachtouris
    def main(self):
198 49413939 Stavros Sachtouris
        super(self.__class__, self)._run()
199 264a13f7 Stavros Sachtouris
        self._run(network_type=self['network_type'])
200 aef3fa1f Stavros Sachtouris
201 aef3fa1f Stavros Sachtouris
202 aef3fa1f Stavros Sachtouris
@command(network_cmds)
203 5c433331 Stavros Sachtouris
class network_delete(_init_network, _optional_output_cmd):
204 aef3fa1f Stavros Sachtouris
    """Delete a network"""
205 aef3fa1f Stavros Sachtouris
206 aef3fa1f Stavros Sachtouris
    @errors.generic.all
207 aef3fa1f Stavros Sachtouris
    @errors.cyclades.connection
208 58602137 Stavros Sachtouris
    @errors.cyclades.network_id
209 aef3fa1f Stavros Sachtouris
    def _run(self, network_id):
210 aef3fa1f Stavros Sachtouris
        r = self.client.delete_network(network_id)
211 aef3fa1f Stavros Sachtouris
        self._optional_output(r)
212 aef3fa1f Stavros Sachtouris
213 aef3fa1f Stavros Sachtouris
    def main(self, network_id):
214 aef3fa1f Stavros Sachtouris
        super(self.__class__, self)._run()
215 aef3fa1f Stavros Sachtouris
        self._run(network_id=network_id)
216 58602137 Stavros Sachtouris
217 58602137 Stavros Sachtouris
218 58602137 Stavros Sachtouris
@command(network_cmds)
219 264a13f7 Stavros Sachtouris
class network_modify(_init_network, _optional_json):
220 264a13f7 Stavros Sachtouris
    """Modify network attributes"""
221 58602137 Stavros Sachtouris
222 264a13f7 Stavros Sachtouris
    arguments = dict(new_name=ValueArgument('Rename the network', '--name'))
223 264a13f7 Stavros Sachtouris
    required = ['new_name', ]
224 58602137 Stavros Sachtouris
225 58602137 Stavros Sachtouris
    @errors.generic.all
226 58602137 Stavros Sachtouris
    @errors.cyclades.connection
227 58602137 Stavros Sachtouris
    @errors.cyclades.network_id
228 58602137 Stavros Sachtouris
    def _run(self, network_id):
229 264a13f7 Stavros Sachtouris
        r = self.client.update_network(network_id, name=self['new_name'])
230 58602137 Stavros Sachtouris
        self._print(r, self.print_dict)
231 58602137 Stavros Sachtouris
232 58602137 Stavros Sachtouris
    def main(self, network_id):
233 58602137 Stavros Sachtouris
        super(self.__class__, self)._run()
234 58602137 Stavros Sachtouris
        self._run(network_id=network_id)
235 62c6652f Stavros Sachtouris
236 62c6652f Stavros Sachtouris
237 62c6652f Stavros Sachtouris
@command(subnet_cmds)
238 62c6652f Stavros Sachtouris
class subnet_list(_init_network, _optional_json, _name_filter, _id_filter):
239 62c6652f Stavros Sachtouris
    """List subnets
240 62c6652f Stavros Sachtouris
    Use filtering arguments (e.g., --name-like) to manage long server lists
241 62c6652f Stavros Sachtouris
    """
242 62c6652f Stavros Sachtouris
243 62c6652f Stavros Sachtouris
    arguments = dict(
244 62c6652f Stavros Sachtouris
        detail=FlagArgument('show detailed output', ('-l', '--details')),
245 62c6652f Stavros Sachtouris
        more=FlagArgument(
246 62c6652f Stavros Sachtouris
            'output results in pages (-n to set items per page, default 10)',
247 5c5eb675 Stavros Sachtouris
            '--more')
248 62c6652f Stavros Sachtouris
    )
249 62c6652f Stavros Sachtouris
250 62c6652f Stavros Sachtouris
    @errors.generic.all
251 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
252 62c6652f Stavros Sachtouris
    def _run(self):
253 62c6652f Stavros Sachtouris
        nets = self.client.list_subnets()
254 62c6652f Stavros Sachtouris
        nets = self._filter_by_name(nets)
255 62c6652f Stavros Sachtouris
        nets = self._filter_by_id(nets)
256 5c5eb675 Stavros Sachtouris
        if not self['detail']:
257 62c6652f Stavros Sachtouris
            nets = [dict(
258 62c6652f Stavros Sachtouris
                id=n['id'], name=n['name'], links=n['links']) for n in nets]
259 62c6652f Stavros Sachtouris
        kwargs = dict()
260 62c6652f Stavros Sachtouris
        if self['more']:
261 62c6652f Stavros Sachtouris
            kwargs['out'] = StringIO()
262 62c6652f Stavros Sachtouris
            kwargs['title'] = ()
263 62c6652f Stavros Sachtouris
        self._print(nets, **kwargs)
264 62c6652f Stavros Sachtouris
        if self['more']:
265 62c6652f Stavros Sachtouris
            pager(kwargs['out'].getvalue())
266 62c6652f Stavros Sachtouris
267 62c6652f Stavros Sachtouris
    def main(self):
268 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
269 62c6652f Stavros Sachtouris
        self._run()
270 62c6652f Stavros Sachtouris
271 62c6652f Stavros Sachtouris
272 62c6652f Stavros Sachtouris
@command(subnet_cmds)
273 62c6652f Stavros Sachtouris
class subnet_info(_init_network, _optional_json):
274 62c6652f Stavros Sachtouris
    """Get details about a subnet"""
275 62c6652f Stavros Sachtouris
276 62c6652f Stavros Sachtouris
    @errors.generic.all
277 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
278 62c6652f Stavros Sachtouris
    def _run(self, subnet_id):
279 62c6652f Stavros Sachtouris
        net = self.client.get_subnet_details(subnet_id)
280 62c6652f Stavros Sachtouris
        self._print(net, self.print_dict)
281 62c6652f Stavros Sachtouris
282 62c6652f Stavros Sachtouris
    def main(self, subnet_id):
283 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
284 62c6652f Stavros Sachtouris
        self._run(subnet_id=subnet_id)
285 62c6652f Stavros Sachtouris
286 62c6652f Stavros Sachtouris
287 62c6652f Stavros Sachtouris
class AllocationPoolArgument(RepeatableArgument):
288 62c6652f Stavros Sachtouris
289 62c6652f Stavros Sachtouris
    @property
290 62c6652f Stavros Sachtouris
    def value(self):
291 62c6652f Stavros Sachtouris
        return super(AllocationPoolArgument, self).value or []
292 62c6652f Stavros Sachtouris
293 62c6652f Stavros Sachtouris
    @value.setter
294 62c6652f Stavros Sachtouris
    def value(self, new_pools):
295 62c6652f Stavros Sachtouris
        new_list = []
296 62c6652f Stavros Sachtouris
        for pool in new_pools:
297 62c6652f Stavros Sachtouris
            start, comma, end = pool.partition(',')
298 62c6652f Stavros Sachtouris
            if not (start and comma and end):
299 62c6652f Stavros Sachtouris
                raise CLIInvalidArgument(
300 62c6652f Stavros Sachtouris
                    'Invalid allocation pool argument %s' % pool, details=[
301 62c6652f Stavros Sachtouris
                    'Allocation values must be of the form:',
302 62c6652f Stavros Sachtouris
                    '  <start address>,<end address>'])
303 62c6652f Stavros Sachtouris
            new_list.append(dict(start=start, end=end))
304 62c6652f Stavros Sachtouris
        self._value = new_list
305 62c6652f Stavros Sachtouris
306 62c6652f Stavros Sachtouris
307 62c6652f Stavros Sachtouris
@command(subnet_cmds)
308 62c6652f Stavros Sachtouris
class subnet_create(_init_network, _optional_json):
309 264a13f7 Stavros Sachtouris
    """Create a new subnet"""
310 62c6652f Stavros Sachtouris
311 62c6652f Stavros Sachtouris
    arguments = dict(
312 62c6652f Stavros Sachtouris
        name=ValueArgument('Subnet name', '--name'),
313 62c6652f Stavros Sachtouris
        allocation_pools=AllocationPoolArgument(
314 62c6652f Stavros Sachtouris
            'start_address,end_address of allocation pool (can be repeated)'
315 62c6652f Stavros Sachtouris
            ' e.g., --alloc-pool=123.45.67.1,123.45.67.8',
316 62c6652f Stavros Sachtouris
            '--alloc-pool'),
317 62c6652f Stavros Sachtouris
        gateway=ValueArgument('Gateway IP', '--gateway'),
318 62c6652f Stavros Sachtouris
        subnet_id=ValueArgument('The id for the subnet', '--id'),
319 62c6652f Stavros Sachtouris
        ipv6=FlagArgument('If set, IP version is set to 6, else 4', '--ipv6'),
320 264a13f7 Stavros Sachtouris
        enable_dhcp=FlagArgument('Enable dhcp (default: off)', '--with-dhcp'),
321 264a13f7 Stavros Sachtouris
        network_id=ValueArgument('Set the network ID', '--network-id'),
322 264a13f7 Stavros Sachtouris
        cidr=ValueArgument('Set the CIDR', '--cidr')
323 62c6652f Stavros Sachtouris
    )
324 264a13f7 Stavros Sachtouris
    required = ('network_id', 'cidr')
325 62c6652f Stavros Sachtouris
326 62c6652f Stavros Sachtouris
    @errors.generic.all
327 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
328 62c6652f Stavros Sachtouris
    @errors.cyclades.network_id
329 62c6652f Stavros Sachtouris
    def _run(self, network_id, cidr):
330 62c6652f Stavros Sachtouris
        net = self.client.create_subnet(
331 62c6652f Stavros Sachtouris
            network_id, cidr,
332 62c6652f Stavros Sachtouris
            self['name'], self['allocation_pools'], self['gateway'],
333 62c6652f Stavros Sachtouris
            self['subnet_id'], self['ipv6'], self['enable_dhcp'])
334 62c6652f Stavros Sachtouris
        self._print(net, self.print_dict)
335 62c6652f Stavros Sachtouris
336 264a13f7 Stavros Sachtouris
    def main(self):
337 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
338 264a13f7 Stavros Sachtouris
        self._run(network_id=self['network_id'], cidr=self['cidr'])
339 62c6652f Stavros Sachtouris
340 62c6652f Stavros Sachtouris
341 62c6652f Stavros Sachtouris
# @command(subnet_cmds)
342 62c6652f Stavros Sachtouris
# class subnet_delete(_init_network, _optional_output_cmd):
343 62c6652f Stavros Sachtouris
#     """Delete a subnet"""
344 62c6652f Stavros Sachtouris
345 62c6652f Stavros Sachtouris
#     @errors.generic.all
346 62c6652f Stavros Sachtouris
#     @errors.cyclades.connection
347 62c6652f Stavros Sachtouris
#     def _run(self, subnet_id):
348 62c6652f Stavros Sachtouris
#         r = self.client.delete_subnet(subnet_id)
349 62c6652f Stavros Sachtouris
#         self._optional_output(r)
350 62c6652f Stavros Sachtouris
351 62c6652f Stavros Sachtouris
#     def main(self, subnet_id):
352 62c6652f Stavros Sachtouris
#         super(self.__class__, self)._run()
353 62c6652f Stavros Sachtouris
#         self._run(subnet_id=subnet_id)
354 62c6652f Stavros Sachtouris
355 62c6652f Stavros Sachtouris
356 62c6652f Stavros Sachtouris
@command(subnet_cmds)
357 264a13f7 Stavros Sachtouris
class subnet_modify(_init_network, _optional_json):
358 264a13f7 Stavros Sachtouris
    """Modify the attributes of a subnet"""
359 62c6652f Stavros Sachtouris
360 264a13f7 Stavros Sachtouris
    arguments = dict(
361 264a13f7 Stavros Sachtouris
        new_name=ValueArgument('New name of the subnet', '--name')
362 264a13f7 Stavros Sachtouris
    )
363 264a13f7 Stavros Sachtouris
    required = ['new_name']
364 62c6652f Stavros Sachtouris
365 62c6652f Stavros Sachtouris
    @errors.generic.all
366 62c6652f Stavros Sachtouris
    @errors.cyclades.connection
367 62c6652f Stavros Sachtouris
    def _run(self, subnet_id):
368 62c6652f Stavros Sachtouris
        r = self.client.get_subnet_details(subnet_id)
369 62c6652f Stavros Sachtouris
        r = self.client.update_subnet(
370 264a13f7 Stavros Sachtouris
            subnet_id, r['network_id'], name=self['new_name'])
371 62c6652f Stavros Sachtouris
        self._print(r, self.print_dict)
372 62c6652f Stavros Sachtouris
373 62c6652f Stavros Sachtouris
    def main(self, subnet_id):
374 62c6652f Stavros Sachtouris
        super(self.__class__, self)._run()
375 62c6652f Stavros Sachtouris
        self._run(subnet_id=subnet_id)
376 447365fe Stavros Sachtouris
377 447365fe Stavros Sachtouris
378 447365fe Stavros Sachtouris
@command(port_cmds)
379 11cc86af Stavros Sachtouris
class port_list(_init_network, _optional_json):
380 11cc86af Stavros Sachtouris
    """List all ports"""
381 447365fe Stavros Sachtouris
382 447365fe Stavros Sachtouris
    @errors.generic.all
383 447365fe Stavros Sachtouris
    @errors.cyclades.connection
384 11cc86af Stavros Sachtouris
    def _run(self):
385 11cc86af Stavros Sachtouris
        net = self.client.list_ports()
386 1d565254 Stavros Sachtouris
        self._print(net)
387 447365fe Stavros Sachtouris
388 11cc86af Stavros Sachtouris
    def main(self):
389 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
390 11cc86af Stavros Sachtouris
        self._run()
391 447365fe Stavros Sachtouris
392 447365fe Stavros Sachtouris
393 447365fe Stavros Sachtouris
@command(port_cmds)
394 447365fe Stavros Sachtouris
class port_info(_init_network, _optional_json):
395 447365fe Stavros Sachtouris
    """Get details about a port"""
396 447365fe Stavros Sachtouris
397 447365fe Stavros Sachtouris
    @errors.generic.all
398 447365fe Stavros Sachtouris
    @errors.cyclades.connection
399 447365fe Stavros Sachtouris
    def _run(self, port_id):
400 447365fe Stavros Sachtouris
        net = self.client.get_port_details(port_id)
401 447365fe Stavros Sachtouris
        self._print(net, self.print_dict)
402 447365fe Stavros Sachtouris
403 447365fe Stavros Sachtouris
    def main(self, port_id):
404 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
405 447365fe Stavros Sachtouris
        self._run(port_id=port_id)
406 447365fe Stavros Sachtouris
407 447365fe Stavros Sachtouris
408 447365fe Stavros Sachtouris
@command(port_cmds)
409 f261965c Stavros Sachtouris
class port_delete(_init_network, _optional_output_cmd, _port_wait):
410 264a13f7 Stavros Sachtouris
    """Delete a port (== disconnect server from network)"""
411 447365fe Stavros Sachtouris
412 f261965c Stavros Sachtouris
    arguments = dict(
413 f261965c Stavros Sachtouris
        wait=FlagArgument('Wait port to be established', ('-w', '--wait'))
414 f261965c Stavros Sachtouris
    )
415 f261965c Stavros Sachtouris
416 447365fe Stavros Sachtouris
    @errors.generic.all
417 447365fe Stavros Sachtouris
    @errors.cyclades.connection
418 447365fe Stavros Sachtouris
    def _run(self, port_id):
419 447365fe Stavros Sachtouris
        r = self.client.delete_port(port_id)
420 f261965c Stavros Sachtouris
        if self['wait']:
421 f261965c Stavros Sachtouris
            self._wait(r['id'], r['status'])
422 447365fe Stavros Sachtouris
        self._optional_output(r)
423 447365fe Stavros Sachtouris
424 447365fe Stavros Sachtouris
    def main(self, port_id):
425 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
426 447365fe Stavros Sachtouris
        self._run(port_id=port_id)
427 447365fe Stavros Sachtouris
428 447365fe Stavros Sachtouris
429 447365fe Stavros Sachtouris
@command(port_cmds)
430 264a13f7 Stavros Sachtouris
class port_modify(_init_network, _optional_json):
431 264a13f7 Stavros Sachtouris
    """Modify the attributes of a port"""
432 447365fe Stavros Sachtouris
433 264a13f7 Stavros Sachtouris
    arguments = dict(new_name=ValueArgument('New name of the port', '--name'))
434 264a13f7 Stavros Sachtouris
    required = ['new_name', ]
435 447365fe Stavros Sachtouris
436 447365fe Stavros Sachtouris
    @errors.generic.all
437 447365fe Stavros Sachtouris
    @errors.cyclades.connection
438 447365fe Stavros Sachtouris
    def _run(self, port_id):
439 447365fe Stavros Sachtouris
        r = self.client.get_port_details(port_id)
440 447365fe Stavros Sachtouris
        r = self.client.update_port(
441 264a13f7 Stavros Sachtouris
            port_id, r['network_id'], name=self['new_name'])
442 447365fe Stavros Sachtouris
        self._print(r, self.print_dict)
443 447365fe Stavros Sachtouris
444 447365fe Stavros Sachtouris
    def main(self, port_id):
445 447365fe Stavros Sachtouris
        super(self.__class__, self)._run()
446 447365fe Stavros Sachtouris
        self._run(port_id=port_id)
447 447365fe Stavros Sachtouris
448 447365fe Stavros Sachtouris
449 17cfc2f0 Stavros Sachtouris
class _port_create(_init_network, _optional_json, _port_wait):
450 fd981f77 Stavros Sachtouris
451 17cfc2f0 Stavros Sachtouris
    def connect(self, network_id, device_id):
452 fd981f77 Stavros Sachtouris
        fixed_ips = [dict(
453 fd981f77 Stavros Sachtouris
            subnet_id=self['subnet_id'], ip_address=self['ip_address'])] if (
454 fd981f77 Stavros Sachtouris
                self['subnet_id']) else None
455 fd981f77 Stavros Sachtouris
        r = self.client.create_port(
456 fd981f77 Stavros Sachtouris
            network_id, device_id,
457 fd981f77 Stavros Sachtouris
            name=self['name'],
458 fd981f77 Stavros Sachtouris
            security_groups=self['security_group_id'],
459 fd981f77 Stavros Sachtouris
            fixed_ips=fixed_ips)
460 fd981f77 Stavros Sachtouris
        if self['wait']:
461 fd981f77 Stavros Sachtouris
            self._wait(r['id'], r['status'])
462 fd981f77 Stavros Sachtouris
        self._print(r, self.print_dict)
463 fd981f77 Stavros Sachtouris
464 fd981f77 Stavros Sachtouris
465 ccdd1b82 Stavros Sachtouris
@command(port_cmds)
466 f25bd53b Stavros Sachtouris
class port_create(_port_create):
467 264a13f7 Stavros Sachtouris
    """Create a new port (== connect server to network)"""
468 ccdd1b82 Stavros Sachtouris
469 ccdd1b82 Stavros Sachtouris
    arguments = dict(
470 b7d79306 Stavros Sachtouris
        name=ValueArgument('A human readable name', '--name'),
471 ccdd1b82 Stavros Sachtouris
        security_group_id=RepeatableArgument(
472 ccdd1b82 Stavros Sachtouris
            'Add a security group id (can be repeated)',
473 b7d79306 Stavros Sachtouris
            ('-g', '--security-group')),
474 b7d79306 Stavros Sachtouris
        subnet_id=ValueArgument(
475 b7d79306 Stavros Sachtouris
            'Subnet id for fixed ips (used with --ip-address)',
476 b7d79306 Stavros Sachtouris
            '--subnet-id'),
477 b7d79306 Stavros Sachtouris
        ip_address=ValueArgument(
478 264a13f7 Stavros Sachtouris
            'IP address for subnet id (used with --subnet-id', '--ip-address'),
479 264a13f7 Stavros Sachtouris
        network_id=ValueArgument('Set the network ID', '--network-id'),
480 264a13f7 Stavros Sachtouris
        device_id=ValueArgument(
481 264a13f7 Stavros Sachtouris
            'The device is either a virtual server or a virtual router',
482 c6afee48 Stavros Sachtouris
            '--device-id'),
483 c6afee48 Stavros Sachtouris
        wait=FlagArgument('Wait port to be established', ('-w', '--wait')),
484 ccdd1b82 Stavros Sachtouris
    )
485 e3f54dc0 Stavros Sachtouris
    required = ('network_id', 'device_id')
486 ccdd1b82 Stavros Sachtouris
487 17cfc2f0 Stavros Sachtouris
    @errors.generic.all
488 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.connection
489 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.network_id
490 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.server_id
491 17cfc2f0 Stavros Sachtouris
    def _run(self, network_id, server_id):
492 17cfc2f0 Stavros Sachtouris
        self.connect(network_id, server_id)
493 17cfc2f0 Stavros Sachtouris
494 264a13f7 Stavros Sachtouris
    def main(self):
495 ccdd1b82 Stavros Sachtouris
        super(self.__class__, self)._run()
496 17cfc2f0 Stavros Sachtouris
        self._run(network_id=self['network_id'], server_id=self['device_id'])
497 264a13f7 Stavros Sachtouris
498 264a13f7 Stavros Sachtouris
499 c6afee48 Stavros Sachtouris
@command(port_cmds)
500 c6afee48 Stavros Sachtouris
class port_wait(_init_network, _port_wait):
501 67dfe4a2 Stavros Sachtouris
    """Wait for port to finish [ACTIVE, DOWN, BUILD, ERROR]"""
502 c6afee48 Stavros Sachtouris
503 c6afee48 Stavros Sachtouris
    arguments = dict(
504 c6afee48 Stavros Sachtouris
        timeout=IntArgument(
505 c6afee48 Stavros Sachtouris
            'Wait limit in seconds (default: 60)', '--timeout', default=60)
506 c6afee48 Stavros Sachtouris
    )
507 c6afee48 Stavros Sachtouris
508 c6afee48 Stavros Sachtouris
    @errors.generic.all
509 c6afee48 Stavros Sachtouris
    @errors.cyclades.connection
510 c6afee48 Stavros Sachtouris
    def _run(self, port_id, current_status):
511 c6afee48 Stavros Sachtouris
        port = self.client.get_port_details(port_id)
512 c6afee48 Stavros Sachtouris
        if port['status'].lower() == current_status.lower():
513 c6afee48 Stavros Sachtouris
            self._wait(port_id, current_status, timeout=self['timeout'])
514 c6afee48 Stavros Sachtouris
        else:
515 c6afee48 Stavros Sachtouris
            self.error(
516 c6afee48 Stavros Sachtouris
                'Port %s: Cannot wait for status %s, '
517 c6afee48 Stavros Sachtouris
                'status is already %s' % (
518 c6afee48 Stavros Sachtouris
                    port_id, current_status, port['status']))
519 c6afee48 Stavros Sachtouris
520 67dfe4a2 Stavros Sachtouris
    def main(self, port_id, current_status='BUILD'):
521 c6afee48 Stavros Sachtouris
        super(self.__class__, self)._run()
522 c6afee48 Stavros Sachtouris
        self._run(port_id=port_id, current_status=current_status)
523 c6afee48 Stavros Sachtouris
524 c6afee48 Stavros Sachtouris
525 d1bced10 Stavros Sachtouris
@command(ip_cmds)
526 d1bced10 Stavros Sachtouris
class ip_list(_init_network, _optional_json):
527 d1bced10 Stavros Sachtouris
    """List reserved floating IPs"""
528 d1bced10 Stavros Sachtouris
529 d1bced10 Stavros Sachtouris
    @errors.generic.all
530 d1bced10 Stavros Sachtouris
    @errors.cyclades.connection
531 d1bced10 Stavros Sachtouris
    def _run(self):
532 d1bced10 Stavros Sachtouris
        self._print(self.client.list_floatingips())
533 d1bced10 Stavros Sachtouris
534 d1bced10 Stavros Sachtouris
    def main(self):
535 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
536 d1bced10 Stavros Sachtouris
        self._run()
537 d1bced10 Stavros Sachtouris
538 d1bced10 Stavros Sachtouris
539 d1bced10 Stavros Sachtouris
@command(ip_cmds)
540 d1bced10 Stavros Sachtouris
class ip_info(_init_network, _optional_json):
541 d1bced10 Stavros Sachtouris
    """Get details on a floating IP"""
542 d1bced10 Stavros Sachtouris
543 d1bced10 Stavros Sachtouris
    @errors.generic.all
544 d1bced10 Stavros Sachtouris
    @errors.cyclades.connection
545 d1bced10 Stavros Sachtouris
    def _run(self, ip_id):
546 291cab21 Stavros Sachtouris
        self._print(
547 291cab21 Stavros Sachtouris
            self.client.get_floatingip_details(ip_id), self.print_dict)
548 d1bced10 Stavros Sachtouris
549 d1bced10 Stavros Sachtouris
    def main(self, ip_id):
550 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
551 d1bced10 Stavros Sachtouris
        self._run(ip_id=ip_id)
552 d1bced10 Stavros Sachtouris
553 d1bced10 Stavros Sachtouris
554 d1bced10 Stavros Sachtouris
@command(ip_cmds)
555 d1bced10 Stavros Sachtouris
class ip_create(_init_network, _optional_json):
556 d1bced10 Stavros Sachtouris
    """Reserve an IP on a network"""
557 264a13f7 Stavros Sachtouris
558 d1bced10 Stavros Sachtouris
    arguments = dict(
559 d1bced10 Stavros Sachtouris
        network_id=ValueArgument(
560 d1bced10 Stavros Sachtouris
            'The network to preserve the IP on', '--network-id'),
561 d1bced10 Stavros Sachtouris
        ip_address=ValueArgument('Allocate a specific IP address', '--address')
562 d1bced10 Stavros Sachtouris
    )
563 d1bced10 Stavros Sachtouris
    required = ('network_id', )
564 d1bced10 Stavros Sachtouris
565 d1bced10 Stavros Sachtouris
    @errors.generic.all
566 d1bced10 Stavros Sachtouris
    @errors.cyclades.connection
567 d1bced10 Stavros Sachtouris
    @errors.cyclades.network_id
568 d1bced10 Stavros Sachtouris
    def _run(self, network_id):
569 d1bced10 Stavros Sachtouris
        self._print(
570 d1bced10 Stavros Sachtouris
            self.client.create_floatingip(
571 d1bced10 Stavros Sachtouris
                network_id, floating_ip_address=self['ip_address']),
572 d1bced10 Stavros Sachtouris
            self.print_dict)
573 d1bced10 Stavros Sachtouris
574 d1bced10 Stavros Sachtouris
    def main(self):
575 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
576 d1bced10 Stavros Sachtouris
        self._run(network_id=self['network_id'])
577 d1bced10 Stavros Sachtouris
578 d1bced10 Stavros Sachtouris
579 d1bced10 Stavros Sachtouris
@command(ip_cmds)
580 d1bced10 Stavros Sachtouris
class ip_delete(_init_network, _optional_output_cmd):
581 d1bced10 Stavros Sachtouris
    """Unreserve an IP (also delete the port, if attached)"""
582 d1bced10 Stavros Sachtouris
583 d1bced10 Stavros Sachtouris
    def _run(self, ip_id):
584 291cab21 Stavros Sachtouris
        self._optional_output(self.client.delete_floatingip(ip_id))
585 d1bced10 Stavros Sachtouris
586 d1bced10 Stavros Sachtouris
    def main(self, ip_id):
587 d1bced10 Stavros Sachtouris
        super(self.__class__, self)._run()
588 d1bced10 Stavros Sachtouris
        self._run(ip_id=ip_id)
589 d1bced10 Stavros Sachtouris
590 d1bced10 Stavros Sachtouris
591 d1bced10 Stavros Sachtouris
#  Warn users for some importand changes
592 264a13f7 Stavros Sachtouris
593 264a13f7 Stavros Sachtouris
@command(network_cmds)
594 fd981f77 Stavros Sachtouris
class network_connect(_port_create):
595 fd981f77 Stavros Sachtouris
    """Connect a network with a device (server or router)"""
596 264a13f7 Stavros Sachtouris
597 fd981f77 Stavros Sachtouris
    arguments = dict(
598 17cfc2f0 Stavros Sachtouris
        name=ValueArgument('A human readable name for the port', '--name'),
599 fd981f77 Stavros Sachtouris
        security_group_id=RepeatableArgument(
600 fd981f77 Stavros Sachtouris
            'Add a security group id (can be repeated)',
601 fd981f77 Stavros Sachtouris
            ('-g', '--security-group')),
602 fd981f77 Stavros Sachtouris
        subnet_id=ValueArgument(
603 fd981f77 Stavros Sachtouris
            'Subnet id for fixed ips (used with --ip-address)',
604 fd981f77 Stavros Sachtouris
            '--subnet-id'),
605 fd981f77 Stavros Sachtouris
        ip_address=ValueArgument(
606 fd981f77 Stavros Sachtouris
            'IP address for subnet id (used with --subnet-id', '--ip-address'),
607 17cfc2f0 Stavros Sachtouris
        wait=FlagArgument('Wait network to connect', ('-w', '--wait')),
608 fd981f77 Stavros Sachtouris
    )
609 fd981f77 Stavros Sachtouris
610 17cfc2f0 Stavros Sachtouris
    @errors.generic.all
611 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.connection
612 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.network_id
613 17cfc2f0 Stavros Sachtouris
    @errors.cyclades.server_id
614 17cfc2f0 Stavros Sachtouris
    def _run(self, network_id, server_id):
615 17cfc2f0 Stavros Sachtouris
        self.connect(network_id, server_id)
616 17cfc2f0 Stavros Sachtouris
617 fd981f77 Stavros Sachtouris
    def main(self, network_id, device_id):
618 fd981f77 Stavros Sachtouris
        super(self.__class__, self)._run()
619 fd981f77 Stavros Sachtouris
        self._run(network_id=network_id, device_id=device_id)
620 264a13f7 Stavros Sachtouris
621 264a13f7 Stavros Sachtouris
622 264a13f7 Stavros Sachtouris
@command(network_cmds)
623 17cfc2f0 Stavros Sachtouris
class network_disconnect(_init_network, _port_wait, _optional_json):
624 fd981f77 Stavros Sachtouris
    """Disconnnect a network from a device"""
625 264a13f7 Stavros Sachtouris
626 fd981f77 Stavros Sachtouris
    def _cyclades_client(self):
627 fd981f77 Stavros Sachtouris
        auth = getattr(self, 'auth_base')
628 fd981f77 Stavros Sachtouris
        endpoints = auth.get_service_endpoints('compute')
629 fd981f77 Stavros Sachtouris
        URL = endpoints['publicURL']
630 fd981f77 Stavros Sachtouris
        from kamaki.clients.cyclades import CycladesClient
631 fd981f77 Stavros Sachtouris
        return CycladesClient(URL, self.client.token)
632 fd981f77 Stavros Sachtouris
633 17cfc2f0 Stavros Sachtouris
    arguments = dict(
634 17cfc2f0 Stavros Sachtouris
        wait=FlagArgument('Wait network to disconnect', ('-w', '--wait'))
635 17cfc2f0 Stavros Sachtouris
    )
636 17cfc2f0 Stavros Sachtouris
637 fd981f77 Stavros Sachtouris
    @errors.generic.all
638 fd981f77 Stavros Sachtouris
    @errors.cyclades.connection
639 fd981f77 Stavros Sachtouris
    @errors.cyclades.network_id
640 fd981f77 Stavros Sachtouris
    @errors.cyclades.server_id
641 fd981f77 Stavros Sachtouris
    def _run(self, network_id, device_id):
642 fd981f77 Stavros Sachtouris
        vm = self._cyclades_client().get_server_details(device_id)
643 fd981f77 Stavros Sachtouris
        nets = [net for net in vm['attachments'] if net['network_id'] not in (
644 fd981f77 Stavros Sachtouris
            'network_id', )]
645 fd981f77 Stavros Sachtouris
        if not nets:
646 fd981f77 Stavros Sachtouris
            raiseCLIError('Network %s is not connected to device %s' % (
647 fd981f77 Stavros Sachtouris
                network_id, device_id))
648 fd981f77 Stavros Sachtouris
        for net in nets:
649 fd981f77 Stavros Sachtouris
            self.client.port_delete(net['id'])
650 17cfc2f0 Stavros Sachtouris
            self.error('Deleting this connection:')
651 fd981f77 Stavros Sachtouris
            self.print_dict(net)
652 17cfc2f0 Stavros Sachtouris
            if self['wait']:
653 17cfc2f0 Stavros Sachtouris
                self._wait(net['id'], net['status'])
654 fd981f77 Stavros Sachtouris
655 fd981f77 Stavros Sachtouris
    def main(self, network_id, device_id):
656 fd981f77 Stavros Sachtouris
        super(self.__class__, self)._run()
657 fd981f77 Stavros Sachtouris
        self._run(network_id=network_id, device_id=device_id)