Revision 0bf38f8c

b/docs/examplesdir/astakos.rst
5 5
is the synnefo implementation of a variant of OpenStack Keystone with custom
6 6
extentions. Kamaki offer tools for managing Astakos information.
7 7

  
8
.. node:: The underlying library that calls the API is part of the synnefo
8
.. note:: The underlying library that calls the API is part of the synnefo
9 9
    and it is called 'astakosclient'
10 10

  
11 11
User
b/docs/examplesdir/server.rst
47 47
    f1r57-1m4g3-1d Debian Base Alpha
48 48
    53c0nd-1m4g3-1d Beta Debian Base
49 49

  
50
Let's pick the `C1R128D1drbd` (id: 1) flavor and the `Debian Base Alpha` (id:
50
Pick the `C1R128D1drbd` (id: 1) flavor and the `Debian Base Alpha` (id:
51 51
f1r57-1m4g3-1d) image to create a new virtual server called 'My First Server'
52 52

  
53 53
.. code-block:: console
......
101 101
    <bar showing destruction progress, until 100%>
102 102
    Server 141 is now in DELETED mode
103 103

  
104
Create Servers with networks
105
----------------------------
106

  
107
First, check the available IPs:
108

  
109
.. code-block:: console
110

  
111
    $ kamaki ip list
112
    42042
113
        instance_id: 424242
114
        floating_network_id: 1
115
        fixed_ip_address: None
116
        floating_ip_address: 123.456.78.90
117
        port_id: 24024
118

  
119
So, there is an ip (123.456.78.90) on network 1. We can use it:
120

  
121
.. code-block:: console
122

  
123
    $ kamaki server create --network=1,123.456.78.90 --name='Extrovert Server' --flavor-id=1 --image-id=f1r57-1m4g3-1d
124
    ...
125

  
126
Another case it the connection to a private network (so, no IP):
127

  
128
.. code-block:: console
129

  
130
    $ kamaki network list
131
    1   Public network
132
    7   A custom private network
133
    9   Another custom private network
134

  
135
    $ kamaki server create --network=7 --name='Introvert Server' --flavor-id=1 --image-id=f1r57-1m4g3-1d
136

  
137
.. note:: Multiple *- -network* args will create a corresponding number of
138
    connections (nics) to the specified networks.
139

  
140
.. note:: Ommiting *- -network* will let the cloud apply the default network
141
    policy. To create a server without any connections (nics), use the
142
    *- -no-network argument*
143

  
144

  
104 145
Inject ssh keys to a debian server
105 146
----------------------------------
106 147

  
......
134 175

  
135 176
.. code-block:: console
136 177

  
137
    $ kamaki server create --name='NoPassword Server' --flavor-id=1 --image-id=f1r57-1m4g3-1d -p /home/someuser/.ssh/id_rsa.pub,/root/.ssh/authorized_keys
178
    $ kamaki server create --name='NoPassword Server' --flavor-id=1 --image-id=f1r57-1m4g3-1d \
179
        --network=1,123.456.78.90 \
180
        -p /home/someuser/.ssh/id_rsa.pub,/root/.ssh/authorized_keys
181

  
138 182
    accessIPv4:
139 183
    accessIPv6:
140 184
    addresses:
......
159 203
    updated:         2013-06-19T12:34:48.512867+00:00
160 204
    user_id:         s0m3-u53r-1d
161 205

  
162
When the virtual server is ready, get the virtual servers external IP from the
163
web UI. Let's assume the IP is 123.456.78.90 .
206
When the server is ready, we can connect through the public network 1 and the
207
IP 123.456.78.90 :
164 208

  
165 209
.. code-block:: console
166 210

  
b/kamaki/cli/commands/cyclades.py
375 375
                                '%s' % ve])
376 376

  
377 377

  
378
class NetworkIpArgument(RepeatableArgument):
378
class NetworkArgument(RepeatableArgument):
379
    """[id=]NETWORK_ID[,[ip=]IP]"""
379 380

  
380 381
    @property
381 382
    def value(self):
382
        return getattr(self, '_value', [])
383
        return getattr(self, '_value', self.default)
383 384

  
384 385
    @value.setter
385 386
    def value(self, new_value):
386
        for v in (new_value or []):
387
            net_and_ip = v.split(',')
388
            if len(net_and_ip) < 2:
387
        for v in new_value or []:
388
            part1, sep, part2 = v.partition(',')
389
            netid, ip = '', ''
390
            if part1.startswith('id='):
391
                netid = part1[len('id='):]
392
            elif part1.startswith('ip='):
393
                ip = part1[len('ip='):]
394
            else:
395
                netid = part1
396
            if part2:
397
                if (part2.startswith('id=') and netid) or (
398
                        part2.startswith('ip=') and ip):
399
                    raise CLIInvalidArgument(
400
                        'Invalid network argument %s' % v, details=[
401
                        'Valid format: [id=]NETWORK_ID[,[ip=]IP]'])
402
                if part2.startswith('id='):
403
                    netid = part2[len('id='):]
404
                elif part2.startswith('ip='):
405
                    ip = part2[len('ip='):]
406
                elif netid:
407
                    ip = part2
408
                else:
409
                    netid = part2
410
            if not netid:
389 411
                raise CLIInvalidArgument(
390
                    'Value "%s" is missing parts' % v,
391
                    details=['Correct format: %s NETWORK_ID,IP' % (
392
                        self.parsed_name[0])])
393
            self._value = getattr(self, '_value', list())
394
            self._value.append(
395
                dict(uuid=net_and_ip[0], fixed_ip=net_and_ip[1]))
412
                    'Invalid network argument %s' % v, details=[
413
                    'Valid format: [id=]NETWORK_ID[,[ip=]IP]'])
414
            self._value = getattr(self, '_value', [])
415
            self._value.append(dict(uuid=netid))
416
            if ip:
417
                self._value[-1]['fixed_ip'] = ip
396 418

  
397 419

  
398 420
@command(server_cmds)
......
413 435
            '--cluster-size'),
414 436
        max_threads=IntArgument(
415 437
            'Max threads in cluster mode (default 1)', '--threads'),
416
        network_id=RepeatableArgument(
417
            'Connect server to network (can be repeated)', '--network'),
418
        network_id_and_ip=NetworkIpArgument(
419
            'Connect server to network w. floating ip ( NETWORK_ID,IP )'
420
            '(can be repeated)',
421
            '--network-with-ip'),
422
        automatic_ip=FlagArgument(
423
            'Automatically assign an IP to the server', '--automatic-ip')
438
        network_configuration=NetworkArgument(
439
            'Connect server to network: [id=]NETWORK_ID[,[ip=]IP]        . '
440
            'Use only NETWORK_ID for private networks.        . '
441
            'Use NETWORK_ID,[ip=]IP for networks with IP.        . '
442
            'Can be repeated, mutually exclussive with --no-network',
443
            '--network'),
444
        no_network=FlagArgument(
445
            'Do not create any network NICs on the server.        . '
446
            'Mutually exclusive to --network        . '
447
            'If neither --network or --no-network are used, the default '
448
            'network policy is applied. This policy is configured on the '
449
            'cloud and kamaki is oblivious to it',
450
            '--no-network')
424 451
    )
425 452
    required = ('server_name', 'flavor_id', 'image_id')
426 453

  
427 454
    @errors.cyclades.cluster_size
428 455
    def _create_cluster(self, prefix, flavor_id, image_id, size):
429
        if self['automatic_ip']:
430
            networks = []
431
        else:
432
            networks = [dict(uuid=netid) for netid in (
433
                self['network_id'] or [])] + (self['network_id_and_ip'] or [])
434
            networks = networks or None
456
        networks = self['network_configuration'] or (
457
            None if self['no_network'] else [])
435 458
        servers = [dict(
436 459
            name='%s%s' % (prefix, i if size > 1 else ''),
437 460
            flavor_id=flavor_id,
......
483 506

  
484 507
    def main(self):
485 508
        super(self.__class__, self)._run()
486
        if self['automatic_ip'] and (
487
                self['network_id'] or self['network_id_and_ip']):
488
            raise CLIInvalidArgument('Invalid argument combination', details=[
489
                'Argument %s should not be combined with other' % (
490
                    self.arguments['automatic_ip'].lvalue),
491
                'network-related arguments i.e., %s or %s' % (
492
                    self.arguments['network_id'].lvalue,
493
                    self.arguments['network_id_and_ip'].lvalue)])
509
        if self['no_network'] and self['network']:
510
            raise CLIInvalidArgument(
511
                'Invalid argument compination', importance=2, details=[
512
                'Arguments %s and %s are mutually exclusive' % (
513
                    self.arguments['no_network'].lvalue,
514
                    self.arguments['network'].lvalue)])
494 515
        self._run(
495 516
            name=self['server_name'],
496 517
            flavor_id=self['flavor_id'],

Also available in: Unified diff