Revision eb647cfe kamaki/clients/cyclades/__init__.py

b/kamaki/clients/cyclades/__init__.py
61 61
                {"network": <network_uuid>},
62 62
                {"network": <network_uuid>, "fixed_ip": address},
63 63
                {"port": <port_id>}, ...]
64
            ATTENTION: Empty list is different to None. None means ' do not
65
            mention it', empty list means 'automatically get an ip'
64 66

  
65 67
        :returns: a dict with the new virtual server details
66 68

  
......
76 78

  
77 79
        return super(CycladesClient, self).create_server(
78 80
            name, flavor_id, image_id,
79
            metadata=metadata, personality=personality)
81
            metadata=metadata, personality=personality, networks=networks)
80 82

  
81 83
    def start_server(self, server_id):
82 84
        """Submit a startup request
......
157 159
        r = self.servers_stats_get(server_id)
158 160
        return r.json['stats']
159 161

  
160
    def list_networks(self, detail=False):
161
        """
162
        :param detail: (bool)
163

  
164
        :returns: (list) id,name if not detail else full info per network
165
        """
166
        detail = 'detail' if detail else ''
167
        r = self.networks_get(command=detail)
168
        return r.json['networks']
169

  
170
    def list_network_nics(self, network_id):
171
        """
172
        :param network_id: integer (str or int)
173

  
174
        :returns: (list)
175
        """
176
        r = self.networks_get(network_id=network_id)
177
        return r.json['network']['attachments']
178

  
179
    def create_network(
180
            self, name,
181
            cidr=None, gateway=None, type=None, dhcp=False):
182
        """
183
        :param name: (str)
184

  
185
        :param cidr: (str)
186

  
187
        :param geteway: (str)
188

  
189
        :param type: (str) if None, will use MAC_FILTERED as default
190
            Valid values: CUSTOM, IP_LESS_ROUTED, MAC_FILTERED, PHYSICAL_VLAN
191

  
192
        :param dhcp: (bool)
193

  
194
        :returns: (dict) network detailed info
195
        """
196
        net = dict(name=name)
197
        if cidr:
198
            net['cidr'] = cidr
199
        if gateway:
200
            net['gateway'] = gateway
201
        net['type'] = type or 'MAC_FILTERED'
202
        net['dhcp'] = True if dhcp else False
203
        req = dict(network=net)
204
        r = self.networks_post(json_data=req, success=202)
205
        return r.json['network']
206

  
207
    def get_network_details(self, network_id):
208
        """
209
        :param network_id: integer (str or int)
210

  
211
        :returns: (dict)
212
        """
213
        r = self.networks_get(network_id=network_id)
214
        return r.json['network']
215

  
216
    def update_network_name(self, network_id, new_name):
217
        """
218
        :param network_id: integer (str or int)
219

  
220
        :param new_name: (str)
221

  
222
        :returns: (dict) response headers
223
        """
224
        req = {'network': {'name': new_name}}
225
        r = self.networks_put(network_id=network_id, json_data=req)
226
        return r.headers
227

  
228
    def delete_network(self, network_id):
229
        """
230
        :param network_id: integer (str or int)
231

  
232
        :returns: (dict) response headers
233

  
234
        :raises ClientError: 421 Network in use
235
        """
236
        try:
237
            r = self.networks_delete(network_id)
238
            return r.headers
239
        except ClientError as err:
240
            if err.status == 421:
241
                err.details = [
242
                    'Network may be still connected to at least one server']
243
            raise
244

  
245
    def connect_server(self, server_id, network_id):
246
        """ Connect a server to a network
247

  
248
        :param server_id: integer (str or int)
249

  
250
        :param network_id: integer (str or int)
251

  
252
        :returns: (dict) response headers
253
        """
254
        req = {'add': {'serverRef': server_id}}
255
        r = self.networks_post(network_id, 'action', json_data=req)
256
        return r.headers
257

  
258
    def disconnect_server(self, server_id, nic_id):
259
        """
260
        :param server_id: integer (str or int)
261

  
262
        :param nic_id: (str)
263

  
264
        :returns: (int) the number of nics disconnected
265
        """
266
        vm_nets = self.list_server_nics(server_id)
267
        num_of_disconnections = 0
268
        for (nic_id, network_id) in [(
269
                net['id'],
270
                net['network_id']) for net in vm_nets if nic_id == net['id']]:
271
            req = {'remove': {'attachment': '%s' % nic_id}}
272
            self.networks_post(network_id, 'action', json_data=req)
273
            num_of_disconnections += 1
274
        return num_of_disconnections
275

  
276
    def disconnect_network_nics(self, netid):
277
        """
278
        :param netid: integer (str or int)
279
        """
280
        for nic in self.list_network_nics(netid):
281
            req = dict(remove=dict(attachment=nic))
282
            self.networks_post(netid, 'action', json_data=req)
283

  
284 162
    def wait_server(
285 163
            self, server_id,
286 164
            current_status='BUILD',
......
308 186
        return self._wait(
309 187
            server_id, current_status, get_status, delay, max_wait, wait_cb)
310 188

  
311
    def wait_network(
312
            self, net_id,
313
            current_status='PENDING', delay=1, max_wait=100, wait_cb=None):
314
        """Wait for network while its status is current_status
315

  
316
        :param net_id: integer (str or int)
317

  
318
        :param current_status: (str) PENDING | ACTIVE | DELETED
319

  
320
        :param delay: time interval between retries
321

  
322
        :max_wait: (int) timeout in secconds
323

  
324
        :param wait_cb: if set a progressbar is used to show progress
325

  
326
        :returns: (str) the new mode if succesfull, (bool) False if timed out
327
        """
328

  
329
        def get_status(self, net_id):
330
            r = self.get_network_details(net_id)
331
            return r['status'], None
332

  
333
        return self._wait(
334
            net_id, current_status, get_status, delay, max_wait, wait_cb)
335

  
336 189
    def wait_firewall(
337 190
            self, server_id,
338 191
            current_status='DISABLED', delay=1, max_wait=100, wait_cb=None):
......
358 211
            server_id, current_status, get_status, delay, max_wait, wait_cb)
359 212

  
360 213

  
361
class CycladesNetworkClient(NetworkClient, Waiter):
214
class CycladesNetworkClient(NetworkClient):
362 215
    """Cyclades Network API extentions"""
363 216

  
364 217
    network_types = (
......
379 232
        return r.json['network']
380 233

  
381 234
    def create_port(
382
            self, network_id, device_id,
383
            security_groups=None, name=None, fixed_ips=None):
384
        port = dict(network_id=network_id, device_id=device_id)
235
            self, network_id,
236
            device_id=None, security_groups=None, name=None, fixed_ips=None):
237
        port = dict(network_id=network_id)
238
        if device_id:
239
            port['device_id'] = device_id
385 240
        if security_groups:
386 241
            port['security_groups'] = security_groups
387 242
        if name:
388 243
            port['name'] = name
389
        for fixed_ip in fixed_ips:
244
        for fixed_ip in fixed_ips or []:
390 245
            diff = set(['subnet_id', 'ip_address']).difference(fixed_ip)
391 246
            if diff:
392 247
                raise ValueError(
......
396 251
        r = self.ports_post(json_data=dict(port=port), success=201)
397 252
        return r.json['port']
398 253

  
399
    def wait_network(
400
            self, net_id,
401
            current_status='PENDING', delay=1, max_wait=100, wait_cb=None):
254
    def create_floatingip(self, floating_network_id, floating_ip_address=''):
255
        return super(CycladesNetworkClient, self).create_floatingip(
256
            floating_network_id, floating_ip_address=floating_ip_address)
402 257

  
403
        def get_status(self, net_id):
404
            r = self.get_network_details(net_id)
405
            return r['status'], None
406

  
407
        return self._wait(
408
            net_id, current_status, get_status, delay, max_wait, wait_cb)
409

  
410
    def wait_port(
411
            self, port_id,
412
            current_status='PENDING', delay=1, max_wait=100, wait_cb=None):
413

  
414
        def get_status(self, net_id):
415
            r = self.get_port_details(port_id)
416
            return r['status'], None
417

  
418
        return self._wait(
419
            port_id, current_status, get_status, delay, max_wait, wait_cb)
258
    def update_floatingip(self, floating_network_id, floating_ip_address=''):
259
        """To nullify something optional, use None"""
260
        return super(CycladesNetworkClient, self).update_floatingip(
261
            floating_network_id, floating_ip_address=floating_ip_address)

Also available in: Unified diff