Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.2 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 validate_network_info, get_backend
38
from synnefo.webproject.management.utils import pprint_table
39

    
40
from synnefo import quotas
41
from synnefo.db.models import Network
42
from synnefo.logic.backend import create_network
43
from synnefo.api.util import values_from_flavor
44

    
45
NETWORK_FLAVORS = Network.FLAVORS.keys()
46

    
47

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

    
52
    help = "Create a new network"
53

    
54
    option_list = BaseCommand.option_list + (
55
        make_option(
56
            "-n",
57
            "--dry-run",
58
            dest="dry_run",
59
            default=False,
60
            action="store_true"),
61
        make_option(
62
            '--name',
63
            dest='name',
64
            help="Name of network"),
65
        make_option(
66
            '--owner',
67
            dest='owner',
68
            help="The owner of the network"),
69
        make_option(
70
            '--subnet',
71
            dest='subnet',
72
            default=None,
73
            # required=True,
74
            help='Subnet of the network'),
75
        make_option(
76
            '--gateway',
77
            dest='gateway',
78
            default=None,
79
            help='Gateway of the network'),
80
        make_option(
81
            '--subnet6',
82
            dest='subnet6',
83
            default=None,
84
            help='IPv6 subnet of the network'),
85
        make_option(
86
            '--gateway6',
87
            dest='gateway6',
88
            default=None,
89
            help='IPv6 gateway of the network'),
90
        make_option(
91
            '--dhcp',
92
            dest='dhcp',
93
            action='store_true',
94
            default=False,
95
            help='Automatically assign IPs'),
96
        make_option(
97
            '--public',
98
            dest='public',
99
            action='store_true',
100
            default=False,
101
            help='Network is public'),
102
        make_option(
103
            '--flavor',
104
            dest='flavor',
105
            default=None,
106
            choices=NETWORK_FLAVORS,
107
            help='Network flavor. Choices: ' + ', '.join(NETWORK_FLAVORS)),
108
        make_option(
109
            '--mode',
110
            dest='mode',
111
            default=None,
112
            help="Overwrite flavor connectivity mode."),
113
        make_option(
114
            '--link',
115
            dest='link',
116
            default=None,
117
            help="Overwrite flavor connectivity link."),
118
        make_option(
119
            '--mac-prefix',
120
            dest='mac_prefix',
121
            default=None,
122
            help="Overwrite flavor connectivity MAC prefix"),
123
        make_option(
124
            '--tags',
125
            dest='tags',
126
            default=None,
127
            help='The tags of the Network (comma separated strings)'),
128
        make_option(
129
            '--backend-id',
130
            dest='backend_id',
131
            default=None,
132
            help='ID of the backend that the network will be created. Only for'
133
                 ' public networks'),
134
    )
135

    
136
    def handle(self, *args, **options):
137
        if args:
138
            raise CommandError("Command doesn't accept any arguments")
139

    
140
        dry_run = options["dry_run"]
141
        name = options['name']
142
        subnet = options['subnet']
143
        backend_id = options['backend_id']
144
        public = options['public']
145
        flavor = options['flavor']
146
        mode = options['mode']
147
        link = options['link']
148
        mac_prefix = options['mac_prefix']
149
        tags = options['tags']
150
        userid = options["owner"]
151

    
152
        if not name:
153
            raise CommandError("Name is required")
154
        if not subnet:
155
            raise CommandError("Subnet is required")
156
        if not flavor:
157
            raise CommandError("Flavor is required")
158
        if public and not backend_id:
159
            raise CommandError("backend-id is required")
160
        if not userid and not public:
161
            raise CommandError("'owner' is required for private networks")
162

    
163
        if mac_prefix and flavor == "MAC_FILTERED":
164
            raise CommandError("Can not override MAC_FILTERED mac-prefix")
165
        if link and flavor == "PHYSICAL_VLAN":
166
            raise CommandError("Can not override PHYSICAL_VLAN link")
167

    
168
        if backend_id:
169
            backend = get_backend(backend_id)
170

    
171
        fmode, flink, fmac_prefix, ftags = values_from_flavor(flavor)
172
        mode = mode or fmode
173
        link = link or flink
174
        mac_prefix = mac_prefix or fmac_prefix
175
        tags = tags or ftags
176

    
177
        subnet, gateway, subnet6, gateway6 = validate_network_info(options)
178

    
179
        if not link or not mode:
180
            raise CommandError("Can not create network."
181
                               " No connectivity link or mode")
182
        netinfo = {
183
           "name": name,
184
           "userid": options["owner"],
185
           "subnet": subnet,
186
           "gateway": gateway,
187
           "gateway6": gateway6,
188
           "subnet6": subnet6,
189
           "dhcp": options["dhcp"],
190
           "flavor": flavor,
191
           "public": public,
192
           "mode": mode,
193
           "link": link,
194
           "mac_prefix": mac_prefix,
195
           "tags": tags,
196
           "state": "PENDING"}
197

    
198
        if dry_run:
199
            self.stdout.write("Creating network:\n")
200
            pprint_table(self.stdout, tuple(netinfo.items()))
201
            return
202

    
203
        network = Network.objects.create(**netinfo)
204
        if userid:
205
            quotas.issue_and_accept_commission(network)
206

    
207
        if public:
208
            # Create BackendNetwork only to the specified Backend
209
            network.create_backend_network(backend)
210
            create_network(network, backends=[backend])
211
        else:
212
            # Create BackendNetwork entries for all Backends
213
            network.create_backend_network()
214
            create_network(network)