Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / api / management / commands / network-modify.py @ ab6d1a2f

History | View | Annotate | Download (6.9 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, BackendNetwork, pooled_rapi_client)
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-to-backend",
76
            dest="add_to_backend",
77
            metavar="BACKEND_ID",
78
            help="Create a network to a Ganeti backend."),
79
        make_option(
80
            "--remove-from-backend",
81
            dest="remove_from_backend",
82
            metavar="BACKEND_ID",
83
            help="Remove a network from a Ganeti backend."),
84
    )
85

    
86
    @transaction.commit_on_success
87
    def handle(self, *args, **options):
88
        if len(args) != 1:
89
            raise CommandError("Please provide a network ID")
90

    
91
        network = get_network(args[0])
92

    
93
        new_name = options.get("name")
94
        if new_name is not None:
95
            old_name = network.name
96
            network = networks.rename(network, new_name)
97
            self.stdout.write("Renamed network '%s' from '%s' to '%s'.\n" %
98
                              (network, old_name, new_name))
99

    
100
        drained = options.get("drained")
101
        if drained is not None:
102
            drained = parse_bool(drained)
103
            network.drained = drained
104
            network.save()
105
            self.stdout.write("Set network '%s' as drained=%s.\n" %
106
                              (network, drained))
107

    
108
        new_owner = options.get("userid")
109
        if new_owner is not None:
110
            if "@" in new_owner:
111
                raise CommandError("Invalid owner UUID.")
112
            old_owner = network.userid
113
            network.userid = new_owner
114
            network.save()
115
            msg = "Changed the owner of network '%s' from '%s' to '%s'.\n"
116
            self.stdout.write(msg % (network, old_owner, new_owner))
117

    
118
        floating_ip_pool = options["floating_ip_pool"]
119
        if floating_ip_pool is not None:
120
            floating_ip_pool = parse_bool(floating_ip_pool)
121
            if floating_ip_pool is False and network.floating_ip_pool is True:
122
                if network.floating_ips.filter(deleted=False).exists():
123
                    msg = ("Can not make network a non floating IP pool."
124
                           " There are still reserved floating IPs.")
125
                    raise CommandError(msg)
126
            network.floating_ip_pool = floating_ip_pool
127
            network.save()
128
            self.stdout.write("Set network '%s' as floating-ip-pool=%s.\n" %
129
                              (network, floating_ip_pool))
130
            if floating_ip_pool is True:
131
                for backend in Backend.objects.filter(offline=False):
132
                    try:
133
                        bnet = network.backend_networks.get(backend=backend)
134
                    except BackendNetwork.DoesNotExist:
135
                        bnet = network.create_backend_network(backend=backend)
136
                    if bnet.operstate != "ACTIVE":
137
                        backend_mod.create_network(network, backend,
138
                                                   connect=True)
139
                        msg = ("Sent job to create network '%s' in backend"
140
                               " '%s'\n" % (network, backend))
141
                        self.stdout.write(msg)
142

    
143
        add_to_backend = options["add_to_backend"]
144
        if add_to_backend is not None:
145
            backend = get_backend(add_to_backend)
146
            network.create_backend_network(backend=backend)
147
            backend_mod.create_network(network, backend, connect=True)
148
            msg = "Sent job to create network '%s' in backend '%s'\n"
149
            self.stdout.write(msg % (network, backend))
150

    
151
        remove_from_backend = options["remove_from_backend"]
152
        if remove_from_backend is not None:
153
            backend = get_backend(remove_from_backend)
154
            if network.nics.filter(machine__backend=backend,
155
                                   machine__deleted=False).exists():
156
                msg = "Can not remove. There are still connected VMs to this"\
157
                      " network"
158
                raise CommandError(msg)
159
            network.action = "DESTROY"
160
            network.save()
161
            backend_mod.delete_network(network, backend, disconnect=True)
162
            msg = "Sent job to delete network '%s' from backend '%s'\n"
163
            self.stdout.write(msg % (network, backend))