Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / networks.py @ ff5edb80

History | View | Annotate | Download (6.5 kB)

1 ff5edb80 Giorgos Korfiatis
# Copyright 2011-2014 GRNET S.A. All rights reserved.
2 ece5581b Christos Stavrakakis
#
3 ece5581b Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 ece5581b Christos Stavrakakis
# without modification, are permitted provided that the following
5 ece5581b Christos Stavrakakis
# conditions are met:
6 ece5581b Christos Stavrakakis
#
7 ece5581b Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 ece5581b Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 ece5581b Christos Stavrakakis
#      disclaimer.
10 ece5581b Christos Stavrakakis
#
11 ece5581b Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 ece5581b Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 ece5581b Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 ece5581b Christos Stavrakakis
#      provided with the distribution.
15 ece5581b Christos Stavrakakis
#
16 ece5581b Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 ece5581b Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 ece5581b Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 ece5581b Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 ece5581b Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 ece5581b Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 ece5581b Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 ece5581b Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 ece5581b Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 ece5581b Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 ece5581b Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 ece5581b Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 ece5581b Christos Stavrakakis
#
29 ece5581b Christos Stavrakakis
# The views and conclusions contained in the software and
30 ece5581b Christos Stavrakakis
# documentation are those of the authors and should not be
31 ece5581b Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 ece5581b Christos Stavrakakis
# or implied, of GRNET S.A.
33 a4658bbe Christos Stavrakakis
34 ece5581b Christos Stavrakakis
from functools import wraps
35 ece5581b Christos Stavrakakis
from django.db import transaction
36 e4def9d6 Christos Stavrakakis
from django.conf import settings
37 ece5581b Christos Stavrakakis
38 ece5581b Christos Stavrakakis
from snf_django.lib.api import faults
39 ece5581b Christos Stavrakakis
from synnefo.api import util
40 ece5581b Christos Stavrakakis
from synnefo import quotas
41 f82dfec6 Christos Stavrakakis
from synnefo.db.models import Network, Backend
42 ece5581b Christos Stavrakakis
from synnefo.db.utils import validate_mac
43 ece5581b Christos Stavrakakis
from synnefo.db.pools import EmptyPool
44 7b5263e4 Christos Stavrakakis
from synnefo.logic import backend as backend_mod
45 ba6ad346 Dionysis Grigoropoulos
from synnefo.logic import utils
46 ece5581b Christos Stavrakakis
47 ece5581b Christos Stavrakakis
from logging import getLogger
48 ece5581b Christos Stavrakakis
log = getLogger(__name__)
49 ece5581b Christos Stavrakakis
50 ece5581b Christos Stavrakakis
51 ece5581b Christos Stavrakakis
def validate_network_action(network, action):
52 ece5581b Christos Stavrakakis
    if network.deleted:
53 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Network has been deleted.")
54 ece5581b Christos Stavrakakis
55 ece5581b Christos Stavrakakis
56 ece5581b Christos Stavrakakis
def network_command(action):
57 ece5581b Christos Stavrakakis
    def decorator(func):
58 ece5581b Christos Stavrakakis
        @wraps(func)
59 ece5581b Christos Stavrakakis
        @transaction.commit_on_success()
60 ece5581b Christos Stavrakakis
        def wrapper(network, *args, **kwargs):
61 ece5581b Christos Stavrakakis
            validate_network_action(network, action)
62 ece5581b Christos Stavrakakis
            return func(network, *args, **kwargs)
63 ece5581b Christos Stavrakakis
        return wrapper
64 ece5581b Christos Stavrakakis
    return decorator
65 ece5581b Christos Stavrakakis
66 ece5581b Christos Stavrakakis
67 ece5581b Christos Stavrakakis
@transaction.commit_on_success
68 3785b737 Dionysis Grigoropoulos
def create(userid, name, flavor, link=None, mac_prefix=None, mode=None,
69 47c27955 Giorgos Korfiatis
           floating_ip_pool=False, tags=None, public=False, drained=False,
70 47c27955 Giorgos Korfiatis
           project=None):
71 ece5581b Christos Stavrakakis
    if flavor is None:
72 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Missing request parameter 'type'")
73 ece5581b Christos Stavrakakis
    elif flavor not in Network.FLAVORS.keys():
74 ece5581b Christos Stavrakakis
        raise faults.BadRequest("Invalid network type '%s'" % flavor)
75 ece5581b Christos Stavrakakis
76 c75ab92e Christos Stavrakakis
    if mac_prefix is not None and flavor == "MAC_FILTERED":
77 8d5795b4 Christos Stavrakakis
        raise faults.BadRequest("Cannot override MAC_FILTERED mac-prefix")
78 c75ab92e Christos Stavrakakis
    if link is not None and flavor == "PHYSICAL_VLAN":
79 8d5795b4 Christos Stavrakakis
        raise faults.BadRequest("Cannot override PHYSICAL_VLAN link")
80 c75ab92e Christos Stavrakakis
81 ba6ad346 Dionysis Grigoropoulos
    utils.check_name_length(name, Network.NETWORK_NAME_LENGTH, "Network name "
82 ba6ad346 Dionysis Grigoropoulos
                            "is too long")
83 ba6ad346 Dionysis Grigoropoulos
84 ece5581b Christos Stavrakakis
    try:
85 c75ab92e Christos Stavrakakis
        fmode, flink, fmac_prefix, ftags = util.values_from_flavor(flavor)
86 ece5581b Christos Stavrakakis
    except EmptyPool:
87 ece5581b Christos Stavrakakis
        log.error("Failed to allocate resources for network of type: %s",
88 ece5581b Christos Stavrakakis
                  flavor)
89 ece5581b Christos Stavrakakis
        msg = "Failed to allocate resources for network."
90 ece5581b Christos Stavrakakis
        raise faults.ServiceUnavailable(msg)
91 c75ab92e Christos Stavrakakis
92 c75ab92e Christos Stavrakakis
    mode = mode or fmode
93 c75ab92e Christos Stavrakakis
    link = link or flink
94 c75ab92e Christos Stavrakakis
    mac_prefix = mac_prefix or fmac_prefix
95 c75ab92e Christos Stavrakakis
    tags = tags or ftags
96 c75ab92e Christos Stavrakakis
97 ece5581b Christos Stavrakakis
    validate_mac(mac_prefix + "0:00:00:00")
98 ece5581b Christos Stavrakakis
99 84813b31 Christos Stavrakakis
    # Check that given link is unique!
100 84813b31 Christos Stavrakakis
    if (link is not None and flavor == "IP_LESS_ROUTED" and
101 84813b31 Christos Stavrakakis
       Network.objects.filter(deleted=False, mode=mode, link=link).exists()):
102 84813b31 Christos Stavrakakis
        msg = "Link '%s' is already used." % link
103 84813b31 Christos Stavrakakis
        raise faults.BadRequest(msg)
104 84813b31 Christos Stavrakakis
105 47c27955 Giorgos Korfiatis
    if project is None:
106 47c27955 Giorgos Korfiatis
        project = userid
107 47c27955 Giorgos Korfiatis
108 ece5581b Christos Stavrakakis
    network = Network.objects.create(
109 ece5581b Christos Stavrakakis
        name=name,
110 a96e84cf Christos Stavrakakis
        userid=userid,
111 47c27955 Giorgos Korfiatis
        project=project,
112 ece5581b Christos Stavrakakis
        flavor=flavor,
113 ece5581b Christos Stavrakakis
        mode=mode,
114 ece5581b Christos Stavrakakis
        link=link,
115 ece5581b Christos Stavrakakis
        mac_prefix=mac_prefix,
116 ece5581b Christos Stavrakakis
        tags=tags,
117 c75ab92e Christos Stavrakakis
        public=public,
118 3d63d954 Christos Stavrakakis
        external_router=public,
119 c75ab92e Christos Stavrakakis
        floating_ip_pool=floating_ip_pool,
120 ece5581b Christos Stavrakakis
        action='CREATE',
121 d193a5c8 Christos Stavrakakis
        state='ACTIVE',
122 d193a5c8 Christos Stavrakakis
        drained=drained)
123 ece5581b Christos Stavrakakis
124 e4def9d6 Christos Stavrakakis
    if link is None:
125 e4def9d6 Christos Stavrakakis
        network.link = "%slink-%d" % (settings.BACKEND_PREFIX_ID, network.id)
126 e4def9d6 Christos Stavrakakis
        network.save()
127 e4def9d6 Christos Stavrakakis
128 ece5581b Christos Stavrakakis
    # Issue commission to Quotaholder and accept it since at the end of
129 ece5581b Christos Stavrakakis
    # this transaction the Network object will be created in the DB.
130 ece5581b Christos Stavrakakis
    # Note: the following call does a commit!
131 48f5b1bc Christos Stavrakakis
    if not public:
132 48f5b1bc Christos Stavrakakis
        quotas.issue_and_accept_commission(network)
133 b47f167a Christos Stavrakakis
134 ece5581b Christos Stavrakakis
    return network
135 ece5581b Christos Stavrakakis
136 ece5581b Christos Stavrakakis
137 7b5263e4 Christos Stavrakakis
def create_network_in_backends(network):
138 7b5263e4 Christos Stavrakakis
    job_ids = []
139 7b5263e4 Christos Stavrakakis
    for bend in Backend.objects.filter(offline=False):
140 7b5263e4 Christos Stavrakakis
        network.create_backend_network(bend)
141 7b5263e4 Christos Stavrakakis
        jobs = backend_mod.create_network(network=network, backend=bend,
142 7b5263e4 Christos Stavrakakis
                                          connect=True)
143 7b5263e4 Christos Stavrakakis
        job_ids.extend(jobs)
144 7b5263e4 Christos Stavrakakis
    return job_ids
145 7b5263e4 Christos Stavrakakis
146 7b5263e4 Christos Stavrakakis
147 ece5581b Christos Stavrakakis
@network_command("RENAME")
148 ece5581b Christos Stavrakakis
def rename(network, name):
149 ece5581b Christos Stavrakakis
    network.name = name
150 ece5581b Christos Stavrakakis
    network.save()
151 ece5581b Christos Stavrakakis
    return network
152 ece5581b Christos Stavrakakis
153 ece5581b Christos Stavrakakis
154 ece5581b Christos Stavrakakis
@network_command("DESTROY")
155 ece5581b Christos Stavrakakis
def delete(network):
156 c82f57ad Christos Stavrakakis
    if network.nics.exists():
157 8d5795b4 Christos Stavrakakis
        raise faults.Conflict("Cannot delete network. There are ports still"
158 c82f57ad Christos Stavrakakis
                              " configured on network network %s" % network.id)
159 a96e84cf Christos Stavrakakis
    if network.ips.filter(deleted=False, floating_ip=True).exists():
160 8d5795b4 Christos Stavrakakis
        msg = "Cannot delete netowrk. Network has allocated floating IPs."
161 a96e84cf Christos Stavrakakis
        raise faults.Conflict(msg)
162 ece5581b Christos Stavrakakis
163 ece5581b Christos Stavrakakis
    network.action = "DESTROY"
164 3f18f035 Christos Stavrakakis
    # Mark network as drained to prevent automatic allocation of
165 3f18f035 Christos Stavrakakis
    # public/floating IPs while the network is being deleted
166 6176e251 Christos Stavrakakis
    if network.public:
167 6176e251 Christos Stavrakakis
        network.drained = True
168 ece5581b Christos Stavrakakis
    network.save()
169 ece5581b Christos Stavrakakis
170 ece5581b Christos Stavrakakis
    # Delete network to all backends that exists
171 b47f167a Christos Stavrakakis
    for bnet in network.backend_networks.exclude(operstate="DELETED"):
172 b47f167a Christos Stavrakakis
        backend_mod.delete_network(network, bnet.backend)
173 b47f167a Christos Stavrakakis
    else:
174 b47f167a Christos Stavrakakis
        # If network does not exist in any backend, update the network state
175 b47f167a Christos Stavrakakis
        backend_mod.update_network_state(network)
176 ece5581b Christos Stavrakakis
    return network
177 99667854 Giorgos Korfiatis
178 99667854 Giorgos Korfiatis
179 99667854 Giorgos Korfiatis
@network_command("REASSIGN")
180 99667854 Giorgos Korfiatis
def reassign(network, project):
181 99667854 Giorgos Korfiatis
    action_fields = {"to_project": project, "from_project": network.project}
182 99667854 Giorgos Korfiatis
    network.project = project
183 99667854 Giorgos Korfiatis
    network.save()
184 99667854 Giorgos Korfiatis
    quotas.issue_and_accept_commission(network, action="REASSIGN",
185 99667854 Giorgos Korfiatis
                                       action_fields=action_fields)
186 99667854 Giorgos Korfiatis
    return network