Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / management / commands / network-modify.py @ a6e6fe48

History | View | Annotate | Download (7.6 kB)

1
# Copyright 2012-2014 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

    
38
from synnefo.db.models import Backend
39
from synnefo.management.common import get_resource
40
from snf_django.management.utils import parse_bool
41
from synnefo.logic import networks, backend as backend_mod
42
from django.db import transaction
43

    
44

    
45
class Command(BaseCommand):
46
    args = "<Network ID>"
47
    help = "Modify a network."
48

    
49
    option_list = BaseCommand.option_list + (
50
        make_option(
51
            '--name',
52
            dest='name',
53
            metavar='NAME',
54
            help="Rename a network"),
55
        make_option(
56
            '--userid',
57
            dest='userid',
58
            help="Change the owner of the network."),
59
        make_option(
60
            "--drained",
61
            dest="drained",
62
            metavar="True|False",
63
            choices=["True", "False"],
64
            help="Set network as drained to prevent creation of new ports."),
65
        make_option(
66
            "--floating-ip-pool",
67
            dest="floating_ip_pool",
68
            metavar="True|False",
69
            choices=["True", "False"],
70
            help="Convert network to a floating IP pool. During this"
71
                 " conversation the network will be created to all"
72
                 " available Ganeti backends."),
73
        make_option(
74
            '--add-reserved-ips',
75
            dest="add_reserved_ips",
76
            help="Comma seperated list of IPs to externally reserve."),
77
        make_option(
78
            '--remove-reserved-ips',
79
            dest="remove_reserved_ips",
80
            help="Comma seperated list of IPs to externally release."),
81
        make_option(
82
            "--add-to-backend",
83
            dest="add_to_backend",
84
            metavar="BACKEND_ID",
85
            help="Create a network to a Ganeti backend."),
86
        make_option(
87
            "--remove-from-backend",
88
            dest="remove_from_backend",
89
            metavar="BACKEND_ID",
90
            help="Remove a network from a Ganeti backend."),
91
    )
92

    
93
    @transaction.commit_on_success
94
    def handle(self, *args, **options):
95
        if len(args) != 1:
96
            raise CommandError("Please provide a network ID")
97

    
98
        network = get_resource("network", args[0])
99

    
100
        new_name = options.get("name")
101
        if new_name is not None:
102
            old_name = network.name
103
            network = networks.rename(network, new_name)
104
            self.stdout.write("Renamed network '%s' from '%s' to '%s'.\n" %
105
                              (network, old_name, new_name))
106

    
107
        drained = options.get("drained")
108
        if drained is not None:
109
            drained = parse_bool(drained)
110
            network.drained = drained
111
            network.save()
112
            self.stdout.write("Set network '%s' as drained=%s.\n" %
113
                              (network, drained))
114

    
115
        new_owner = options.get("userid")
116
        if new_owner is not None:
117
            if "@" in new_owner:
118
                raise CommandError("Invalid owner UUID.")
119
            old_owner = network.userid
120
            network.userid = new_owner
121
            network.save()
122
            msg = "Changed the owner of network '%s' from '%s' to '%s'.\n"
123
            self.stdout.write(msg % (network, old_owner, new_owner))
124

    
125
        floating_ip_pool = options["floating_ip_pool"]
126
        if floating_ip_pool is not None:
127
            floating_ip_pool = parse_bool(floating_ip_pool)
128
            if floating_ip_pool is False and network.floating_ip_pool is True:
129
                if network.ips.filter(deleted=False, floating_ip=True)\
130
                              .exists():
131
                    msg = ("Cannot make network a non floating IP pool."
132
                           " There are still reserved floating IPs.")
133
                    raise CommandError(msg)
134
            network.floating_ip_pool = floating_ip_pool
135
            network.save()
136
            self.stdout.write("Set network '%s' as floating-ip-pool=%s.\n" %
137
                              (network, floating_ip_pool))
138
            if floating_ip_pool is True:
139
                for backend in Backend.objects.filter(offline=False):
140
                    bnet, jobs =\
141
                        backend_mod.ensure_network_is_active(backend,
142
                                                             network.id)
143
                    if jobs:
144
                        msg = ("Sent job to create network '%s' in backend"
145
                               " '%s'\n" % (network, backend))
146
                        self.stdout.write(msg)
147

    
148
        add_reserved_ips = options.get('add_reserved_ips')
149
        remove_reserved_ips = options.get('remove_reserved_ips')
150
        if add_reserved_ips or remove_reserved_ips:
151
            if add_reserved_ips:
152
                add_reserved_ips = add_reserved_ips.split(",")
153
                for ip in add_reserved_ips:
154
                    network.reserve_address(ip, external=True)
155
            if remove_reserved_ips:
156
                remove_reserved_ips = remove_reserved_ips.split(",")
157
                for ip in remove_reserved_ips:
158
                    network.release_address(ip, external=True)
159

    
160
        add_to_backend = options["add_to_backend"]
161
        if add_to_backend is not None:
162
            backend = get_resource("backend", add_to_backend)
163
            bnet, jobs = backend_mod.ensure_network_is_active(backend,
164
                                                              network.id)
165
            if jobs:
166
                msg = "Sent job to create network '%s' in backend '%s'\n"
167
                self.stdout.write(msg % (network, backend))
168

    
169
        remove_from_backend = options["remove_from_backend"]
170
        if remove_from_backend is not None:
171
            backend = get_resource("backend", remove_from_backend)
172
            if network.nics.filter(machine__backend=backend,
173
                                   machine__deleted=False).exists():
174
                msg = "Cannot remove. There are still connected VMs to this"\
175
                      " network"
176
                raise CommandError(msg)
177
            backend_mod.delete_network(network, backend, disconnect=True)
178
            msg = "Sent job to delete network '%s' from backend '%s'\n"
179
            self.stdout.write(msg % (network, backend))