Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (7.6 kB)

1
# Copyright 2012-2013 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_network, get_backend)
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 as drained to exclude for IP allocation."
65
                 " Only used for public networks."),
66
        make_option(
67
            "--floating-ip-pool",
68
            dest="floating_ip_pool",
69
            metavar="True|False",
70
            choices=["True", "False"],
71
            help="Convert network to a floating IP pool. During this"
72
                 " conversation the network will be created to all"
73
                 " available Ganeti backends."),
74
        make_option(
75
            '--add-reserved-ips',
76
            dest="add_reserved_ips",
77
            help="Comma seperated list of IPs to externally reserve."),
78
        make_option(
79
            '--remove-reserved-ips',
80
            dest="remove_reserved_ips",
81
            help="Comma seperated list of IPs to externally release."),
82
        make_option(
83
            "--add-to-backend",
84
            dest="add_to_backend",
85
            metavar="BACKEND_ID",
86
            help="Create a network to a Ganeti backend."),
87
        make_option(
88
            "--remove-from-backend",
89
            dest="remove_from_backend",
90
            metavar="BACKEND_ID",
91
            help="Remove a network from a Ganeti backend."),
92
    )
93

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

    
99
        network = get_network(args[0])
100

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

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

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

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

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

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

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