Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / management / commands / network-create.py @ 3785b737

History | View | Annotate | Download (8.7 kB)

1
# Copyright 2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from optparse import make_option
35

    
36
from django.core.management.base import BaseCommand, CommandError
37
from synnefo.management.common import get_backend, convert_api_faults
38
from snf_django.management.utils import parse_bool
39

    
40
from synnefo.db.models import Network, Backend
41
from synnefo.logic import networks, subnets
42
from synnefo.management import pprint
43

    
44
NETWORK_FLAVORS = Network.FLAVORS.keys()
45

    
46

    
47
class Command(BaseCommand):
48
    can_import_settings = True
49
    output_transaction = True
50

    
51
    help = "Create a new network"
52

    
53
    option_list = BaseCommand.option_list + (
54
        make_option(
55
            '--name',
56
            dest='name',
57
            help="Name of the network"),
58
        make_option(
59
            '--name4',
60
            dest='name4',
61
            help="Name of the IPv4 subnet"),
62
        make_option(
63
            '--name6',
64
            dest='name6',
65
            help="Name of the IPv6 subnet"),
66
        make_option(
67
            '--owner',
68
            dest='owner',
69
            help="The owner of the network"),
70
        make_option(
71
            '--subnet',
72
            dest='subnet',
73
            default=None,
74
            # required=True,
75
            help='IPv4 subnet of the network'),
76
        make_option(
77
            '--gateway',
78
            dest='gateway',
79
            default=None,
80
            help='IPv4 gateway of the network'),
81
        make_option(
82
            '--subnet6',
83
            dest='subnet6',
84
            default=None,
85
            help='IPv6 subnet of the network'),
86
        make_option(
87
            '--gateway6',
88
            dest='gateway6',
89
            default=None,
90
            help='IPv6 gateway of the network'),
91
        make_option(
92
            '--dhcp',
93
            dest='dhcp',
94
            default="False",
95
            choices=["True", "False"],
96
            metavar="True|False",
97
            help='Automatically assign IPs'),
98
        make_option(
99
            '--slaac',
100
            dest='slaac',
101
            default="False",
102
            choices=["True", "False"],
103
            metavar="True|False",
104
            help='Automatically assign IPs for the IPv6 subnet'),
105
        make_option(
106
            '--public',
107
            dest='public',
108
            action='store_true',
109
            default=False,
110
            help='Network is public'),
111
        make_option(
112
            '--flavor',
113
            dest='flavor',
114
            default=None,
115
            choices=NETWORK_FLAVORS,
116
            help='Network flavor. Choices: ' + ', '.join(NETWORK_FLAVORS)),
117
        make_option(
118
            '--mode',
119
            dest='mode',
120
            default=None,
121
            help="Overwrite flavor connectivity mode."),
122
        make_option(
123
            '--link',
124
            dest='link',
125
            default=None,
126
            help="Overwrite flavor connectivity link."),
127
        make_option(
128
            '--mac-prefix',
129
            dest='mac_prefix',
130
            default=None,
131
            help="Overwrite flavor connectivity MAC prefix"),
132
        make_option(
133
            '--tags',
134
            dest='tags',
135
            default=None,
136
            help='The tags of the Network (comma separated strings)'),
137
        make_option(
138
            '--floating-ip-pool',
139
            dest='floating_ip_pool',
140
            default="False",
141
            choices=["True", "False"],
142
            metavar="True|False",
143
            help="Use the network as a Floating IP pool. Floating IP pools"
144
                 " are created in all available backends."),
145
        make_option(
146
            "--backend-ids",
147
            dest="backend_ids",
148
            default=None,
149
            help="Comma seperated list of Ganeti backends IDs that the network"
150
                 " will be created. Only for public networks. Use 'all' to"
151
                 " create network in all available backends."),
152
    )
153

    
154
    @convert_api_faults
155
    def handle(self, *args, **options):
156
        if args:
157
            raise CommandError("Command doesn't accept any arguments")
158

    
159
        name = options['name']
160
        name4 = options['name4']
161
        name6 = options['name6']
162
        subnet = options['subnet']
163
        gateway = options['gateway']
164
        subnet6 = options['subnet6']
165
        gateway6 = options['gateway6']
166
        backend_ids = options['backend_ids']
167
        public = options['public']
168
        flavor = options['flavor']
169
        mode = options['mode']
170
        link = options['link']
171
        mac_prefix = options['mac_prefix']
172
        tags = options['tags']
173
        userid = options["owner"]
174
        floating_ip_pool = parse_bool(options["floating_ip_pool"])
175
        dhcp = parse_bool(options["dhcp"])
176
        slaac = parse_bool(options["slaac"])
177

    
178
        if name is None:
179
            name = ""
180
        if flavor is None:
181
            raise CommandError("flavor is required")
182

    
183
        if (subnet is None) and (subnet6 is None):
184
            raise CommandError("subnet or subnet6 is required")
185
        if subnet is None and gateway is not None:
186
            raise CommandError("Cannot use gateway without subnet")
187
        if subnet is None and dhcp is not None:
188
            raise CommandError("Cannot use dhcp without subnet")
189
        if subnet is None and name4 is not None:
190
            raise CommandError("Cannot use name without subnet")
191

    
192
        if subnet6 is None and gateway6 is not None:
193
            raise CommandError("Cannot use gateway6 without subnet6")
194
        if subnet6 is None and slaac is not None:
195
            raise CommandError("Cannot use slaac without subnet6")
196
        if public and not (backend_ids or floating_ip_pool):
197
            raise CommandError("backend-ids is required")
198
        if subnet6 is None and name6 is not None:
199
            raise CommandError("Cannot use name6 without subnet6")
200
        if not userid and not public:
201
            raise CommandError("'owner' is required for private networks")
202

    
203
        backends = []
204
        if backend_ids is not None:
205
            if backend_ids == "all":
206
                backends = Backend.objects.filter(offline=False)
207
            else:
208
                for backend_id in backend_ids.split(","):
209
                    try:
210
                        backend_id = int(backend_id)
211
                    except ValueError:
212
                        raise CommandError("Invalid backend-id: %s"
213
                                           % backend_id)
214
                    backend = get_backend(backend_id)
215
                    backends.append(backend)
216

    
217
        network = networks.create(userid=userid, name=name, flavor=flavor,
218
                                  public=public, mode=mode,
219
                                  link=link, mac_prefix=mac_prefix, tags=tags,
220
                                  floating_ip_pool=floating_ip_pool,
221
                                  backends=backends, lazy_create=False)
222

    
223
        sub4 = subnets._create_subnet(network.id, cidr=subnet, name=name4,
224
                                      ipversion=4, gateway=gateway, dhcp=dhcp,
225
                                      user_id=userid)
226

    
227
        sub6 = subnets._create_subnet(network.id, cidr=subnet6, name=name6,
228
                                      ipversion=6, gateway=gateway6,
229
                                      dhcp=slaac, user_id=userid)
230

    
231
        self.stdout.write("Created network '%s' in DB:\n" % network)
232
        pprint.pprint_network(network, stdout=self.stdout)
233
        pprint.pprint_network_subnets(network, stdout=self.stdout)