root / snf-cyclades-app / synnefo / neutron / network_views.py @ d6b24130
History | View | Annotate | Download (8.4 kB)
1 | d6b24130 | Marios Kogias | from django.http import HttpResponse |
---|---|---|---|
2 | d6b24130 | Marios Kogias | from django.utils import simplejson as json |
3 | d6b24130 | Marios Kogias | from django.db import transaction |
4 | d6b24130 | Marios Kogias | from django.db.models import Q |
5 | d6b24130 | Marios Kogias | from synnefo.db.pools import EmptyPool |
6 | d6b24130 | Marios Kogias | from synnefo.db.utils import validate_mac |
7 | d6b24130 | Marios Kogias | from django.conf import settings |
8 | d6b24130 | Marios Kogias | from snf_django.lib import api |
9 | d6b24130 | Marios Kogias | from snf_django.lib.api import utils |
10 | d6b24130 | Marios Kogias | from synnefo.logic import backend |
11 | d6b24130 | Marios Kogias | from django.template.loader import render_to_string |
12 | d6b24130 | Marios Kogias | from synnefo.api import util |
13 | d6b24130 | Marios Kogias | from models import Network |
14 | d6b24130 | Marios Kogias | |
15 | d6b24130 | Marios Kogias | from logging import getLogger |
16 | d6b24130 | Marios Kogias | |
17 | d6b24130 | Marios Kogias | from synnefo import quotas |
18 | d6b24130 | Marios Kogias | |
19 | d6b24130 | Marios Kogias | |
20 | d6b24130 | Marios Kogias | log = getLogger(__name__) |
21 | d6b24130 | Marios Kogias | |
22 | d6b24130 | Marios Kogias | def demux(request): |
23 | d6b24130 | Marios Kogias | if request.method == 'GET': |
24 | d6b24130 | Marios Kogias | #return HttpResponse("in network get")
|
25 | d6b24130 | Marios Kogias | return list_networks(request)
|
26 | d6b24130 | Marios Kogias | elif request.method == 'POST': |
27 | d6b24130 | Marios Kogias | #return create_network(request)
|
28 | d6b24130 | Marios Kogias | return HttpResponse("in network post") |
29 | d6b24130 | Marios Kogias | else:
|
30 | d6b24130 | Marios Kogias | return api.api_method_not_allowed(request)
|
31 | d6b24130 | Marios Kogias | |
32 | d6b24130 | Marios Kogias | def network_demux(request,offset): |
33 | d6b24130 | Marios Kogias | |
34 | d6b24130 | Marios Kogias | if request.method == 'GET': |
35 | d6b24130 | Marios Kogias | return get_network(request,offset)
|
36 | d6b24130 | Marios Kogias | #return HttpResponse("in network det get")
|
37 | d6b24130 | Marios Kogias | elif request.method == 'DELETE': |
38 | d6b24130 | Marios Kogias | return delete_network(request,offset)
|
39 | d6b24130 | Marios Kogias | #return HttpResponse("in network det delete")
|
40 | d6b24130 | Marios Kogias | elif request.method == 'PUT': |
41 | d6b24130 | Marios Kogias | #return update_network(request,offset)
|
42 | d6b24130 | Marios Kogias | return HttpResponse("in network det put") |
43 | d6b24130 | Marios Kogias | else:
|
44 | d6b24130 | Marios Kogias | return api.api_method_not_allowed(request)
|
45 | d6b24130 | Marios Kogias | |
46 | d6b24130 | Marios Kogias | @api.api_method(http_method='GET', user_required=True, logger=log) |
47 | d6b24130 | Marios Kogias | def list_networks(request): |
48 | d6b24130 | Marios Kogias | log.debug('list_networks')
|
49 | d6b24130 | Marios Kogias | |
50 | d6b24130 | Marios Kogias | user_networks = Network.objects.filter(Q(userid=request.user_uniq) | |
51 | d6b24130 | Marios Kogias | Q(public=True))
|
52 | d6b24130 | Marios Kogias | |
53 | d6b24130 | Marios Kogias | user_networks = user_networks.filter(deleted=False)
|
54 | d6b24130 | Marios Kogias | |
55 | d6b24130 | Marios Kogias | networks = [network_to_dict(network) |
56 | d6b24130 | Marios Kogias | for network in user_networks.order_by('id')] |
57 | d6b24130 | Marios Kogias | |
58 | d6b24130 | Marios Kogias | if request.serialization == 'xml': |
59 | d6b24130 | Marios Kogias | data = render_to_string('list_networks.xml', {
|
60 | d6b24130 | Marios Kogias | 'networks': networks })
|
61 | d6b24130 | Marios Kogias | else:
|
62 | d6b24130 | Marios Kogias | data = json.dumps({'networks': networks})
|
63 | d6b24130 | Marios Kogias | |
64 | d6b24130 | Marios Kogias | return HttpResponse(data, status=200) |
65 | d6b24130 | Marios Kogias | |
66 | d6b24130 | Marios Kogias | @api.api_method(http_method='POST', user_required=True, logger=log) |
67 | d6b24130 | Marios Kogias | @transaction.commit_manually
|
68 | d6b24130 | Marios Kogias | def create_network (request): |
69 | d6b24130 | Marios Kogias | '''
|
70 | d6b24130 | Marios Kogias | This operation does not require a rest body. If specified, the body might
|
71 | d6b24130 | Marios Kogias | include one or more of the following attributes:
|
72 | d6b24130 | Marios Kogias |
|
73 | d6b24130 | Marios Kogias | name: a string specifying a symbolic name for the network, which is not
|
74 | d6b24130 | Marios Kogias | required to be unique;
|
75 | d6b24130 | Marios Kogias |
|
76 | d6b24130 | Marios Kogias | admin_state_up: a bool value specifying the administrative status of the network;
|
77 | d6b24130 | Marios Kogias |
|
78 | d6b24130 | Marios Kogias | 2 more attirbutes for administrative users (not supported)
|
79 | d6b24130 | Marios Kogias | '''
|
80 | d6b24130 | Marios Kogias | |
81 | d6b24130 | Marios Kogias | try:
|
82 | d6b24130 | Marios Kogias | user_id = request.user_uniq |
83 | d6b24130 | Marios Kogias | if request.raw_post_data:
|
84 | d6b24130 | Marios Kogias | req = utils.get_request_dict(request) |
85 | d6b24130 | Marios Kogias | log.info('create_network %s', req)
|
86 | d6b24130 | Marios Kogias | try:
|
87 | d6b24130 | Marios Kogias | d = req['network']
|
88 | d6b24130 | Marios Kogias | name = d['name']
|
89 | d6b24130 | Marios Kogias | except KeyError: |
90 | d6b24130 | Marios Kogias | raise api.faults.BadRequest("Malformed request") |
91 | d6b24130 | Marios Kogias | |
92 | d6b24130 | Marios Kogias | flavor = d.get("type", None) |
93 | d6b24130 | Marios Kogias | if flavor is None: |
94 | d6b24130 | Marios Kogias | #raise faults.BadRequest("Missing request parameter 'type'")
|
95 | d6b24130 | Marios Kogias | # set default flavor
|
96 | d6b24130 | Marios Kogias | #FIX ME!!!
|
97 | d6b24130 | Marios Kogias | flavor="MAC_FILTERED"
|
98 | d6b24130 | Marios Kogias | log.info("not found flavor")
|
99 | d6b24130 | Marios Kogias | elif flavor not in Network.FLAVORS.keys(): |
100 | d6b24130 | Marios Kogias | raise api.faults.BadRequest("Invalid network type '%s'" % flavor) |
101 | d6b24130 | Marios Kogias | log.info("found flavor 1")
|
102 | d6b24130 | Marios Kogias | elif flavor not in settings.API_ENABLED_NETWORK_FLAVORS: |
103 | d6b24130 | Marios Kogias | log.info("found flavor2")
|
104 | d6b24130 | Marios Kogias | raise api.faults.Forbidden("Can not create network of type '%s'" %flavor) |
105 | d6b24130 | Marios Kogias | # Get and validate flavor. Flavors are still exposed as 'type' in the
|
106 | d6b24130 | Marios Kogias | # API.
|
107 | d6b24130 | Marios Kogias | else:
|
108 | d6b24130 | Marios Kogias | name = ""
|
109 | d6b24130 | Marios Kogias | flavor = "MAC_FILTERED" # this is the default FIX ME |
110 | d6b24130 | Marios Kogias | |
111 | d6b24130 | Marios Kogias | try:
|
112 | d6b24130 | Marios Kogias | mode, link, mac_prefix, tags = util.values_from_flavor(flavor) |
113 | d6b24130 | Marios Kogias | validate_mac(mac_prefix + "0:00:00:00")
|
114 | d6b24130 | Marios Kogias | network = Network.objects.create( |
115 | d6b24130 | Marios Kogias | name=name, |
116 | d6b24130 | Marios Kogias | userid=user_id, |
117 | d6b24130 | Marios Kogias | flavor=flavor, |
118 | d6b24130 | Marios Kogias | mode=mode, |
119 | d6b24130 | Marios Kogias | link=link, |
120 | d6b24130 | Marios Kogias | mac_prefix=mac_prefix, |
121 | d6b24130 | Marios Kogias | tags=tags, |
122 | d6b24130 | Marios Kogias | action='CREATE',
|
123 | d6b24130 | Marios Kogias | state='ACTIVE')
|
124 | d6b24130 | Marios Kogias | except EmptyPool:
|
125 | d6b24130 | Marios Kogias | log.error("Failed to allocate resources for network of type: %s",
|
126 | d6b24130 | Marios Kogias | flavor) |
127 | d6b24130 | Marios Kogias | raise api.faults.ServiceUnavailable("Failed to allocate network" |
128 | d6b24130 | Marios Kogias | " resources")
|
129 | d6b24130 | Marios Kogias | |
130 | d6b24130 | Marios Kogias | # Issue commission to Quotaholder and accept it since at the end of
|
131 | d6b24130 | Marios Kogias | # this transaction the Network object will be created in the DB.
|
132 | d6b24130 | Marios Kogias | # Note: the following call does a commit!
|
133 | d6b24130 | Marios Kogias | #quotas.issue_and_accept_commission(network)
|
134 | d6b24130 | Marios Kogias | # COME BACK....
|
135 | d6b24130 | Marios Kogias | |
136 | d6b24130 | Marios Kogias | except:
|
137 | d6b24130 | Marios Kogias | transaction.rollback() |
138 | d6b24130 | Marios Kogias | log.info("roll")
|
139 | d6b24130 | Marios Kogias | raise
|
140 | d6b24130 | Marios Kogias | else:
|
141 | d6b24130 | Marios Kogias | transaction.commit() |
142 | d6b24130 | Marios Kogias | log.info("commit")
|
143 | d6b24130 | Marios Kogias | networkdict = network_to_dict(network) |
144 | d6b24130 | Marios Kogias | response = render_network(request, networkdict, status=201)
|
145 | d6b24130 | Marios Kogias | |
146 | d6b24130 | Marios Kogias | return response
|
147 | d6b24130 | Marios Kogias | |
148 | d6b24130 | Marios Kogias | @api.api_method(http_method='GET', user_required=True, logger=log) |
149 | d6b24130 | Marios Kogias | def get_network(request,network_id): |
150 | d6b24130 | Marios Kogias | log.debug('get_network_details %s', network_id)
|
151 | d6b24130 | Marios Kogias | net = get_network_fromdb(network_id, request.user_uniq) |
152 | d6b24130 | Marios Kogias | |
153 | d6b24130 | Marios Kogias | #needs discussion
|
154 | d6b24130 | Marios Kogias | if net.deleted:
|
155 | d6b24130 | Marios Kogias | raise api.faults.BadRequest("Network has been deleted.") |
156 | d6b24130 | Marios Kogias | else:
|
157 | d6b24130 | Marios Kogias | netdict = network_to_dict(net) |
158 | d6b24130 | Marios Kogias | return render_network(request, netdict)
|
159 | d6b24130 | Marios Kogias | |
160 | d6b24130 | Marios Kogias | @api.api_method(http_method='DELETE', user_required=True, logger=log) |
161 | d6b24130 | Marios Kogias | @transaction.commit_on_success
|
162 | d6b24130 | Marios Kogias | def delete_network(request,network_id): |
163 | d6b24130 | Marios Kogias | log.info('delete_network %s', network_id)
|
164 | d6b24130 | Marios Kogias | net = get_network_fromdb(network_id, request.user_uniq, for_update=True)
|
165 | d6b24130 | Marios Kogias | |
166 | d6b24130 | Marios Kogias | log.info(net.name) |
167 | d6b24130 | Marios Kogias | if net.public:
|
168 | d6b24130 | Marios Kogias | raise api.faults.Forbidden('Can not delete the public network.') |
169 | d6b24130 | Marios Kogias | |
170 | d6b24130 | Marios Kogias | if net.deleted:
|
171 | d6b24130 | Marios Kogias | raise api.faults.BadRequest("Network has been deleted.") |
172 | d6b24130 | Marios Kogias | |
173 | d6b24130 | Marios Kogias | if net.machines.all(): # Nics attached on network |
174 | d6b24130 | Marios Kogias | raise api.faults.NetworkInUse('Machines are connected to network.') |
175 | d6b24130 | Marios Kogias | |
176 | d6b24130 | Marios Kogias | net.action = 'DESTROY'
|
177 | d6b24130 | Marios Kogias | net.save() |
178 | d6b24130 | Marios Kogias | '''
|
179 | d6b24130 | Marios Kogias | skip the backend part...
|
180 | d6b24130 | Marios Kogias | backend_networks = net.backend_networks.exclude(operstate="DELETED")
|
181 | d6b24130 | Marios Kogias | for bnet in backend_networks:
|
182 | d6b24130 | Marios Kogias | backend.delete_network(net, bnet.backend)
|
183 | d6b24130 | Marios Kogias | if not backend_networks:
|
184 | d6b24130 | Marios Kogias | backend.update_network_state(net)
|
185 | d6b24130 | Marios Kogias | '''
|
186 | d6b24130 | Marios Kogias | |
187 | d6b24130 | Marios Kogias | #the following has to leave when fix the backend thing
|
188 | d6b24130 | Marios Kogias | net.deleted = True
|
189 | d6b24130 | Marios Kogias | net.save() |
190 | d6b24130 | Marios Kogias | |
191 | d6b24130 | Marios Kogias | return HttpResponse(status=204) |
192 | d6b24130 | Marios Kogias | |
193 | d6b24130 | Marios Kogias | |
194 | d6b24130 | Marios Kogias | @api.api_method(http_method='PUT', user_required=True, logger=log) |
195 | d6b24130 | Marios Kogias | def update_network(request,network_id): |
196 | d6b24130 | Marios Kogias | '''
|
197 | d6b24130 | Marios Kogias | You can update only name and admin_state_up
|
198 | d6b24130 | Marios Kogias | '''
|
199 | d6b24130 | Marios Kogias | net = get_network_fromdb(network_id, request.user_uniq, for_update=True)
|
200 | d6b24130 | Marios Kogias | info = utils.get_request_dict(request) |
201 | d6b24130 | Marios Kogias | |
202 | d6b24130 | Marios Kogias | updatable = set(["name","admin_state_up"]) |
203 | d6b24130 | Marios Kogias | try:
|
204 | d6b24130 | Marios Kogias | new_vals = info["network"]
|
205 | d6b24130 | Marios Kogias | except Keyerror:
|
206 | d6b24130 | Marios Kogias | raise api.faults.BadRequest("Malformed request") |
207 | d6b24130 | Marios Kogias | |
208 | d6b24130 | Marios Kogias | for key,val in new_vals.iteritems(): |
209 | d6b24130 | Marios Kogias | if key in updatable: |
210 | d6b24130 | Marios Kogias | setattr(net,key,val)
|
211 | d6b24130 | Marios Kogias | else:
|
212 | d6b24130 | Marios Kogias | raise api.faults.BadRequest("Wrong field update") |
213 | d6b24130 | Marios Kogias | net.save() |
214 | d6b24130 | Marios Kogias | #net_dic = network_to_dict(net)
|
215 | d6b24130 | Marios Kogias | #data = json.dumps({"network":net_dic})
|
216 | d6b24130 | Marios Kogias | netdict = network_to_dict(net) |
217 | d6b24130 | Marios Kogias | return render_network(request, netdict, 200) |
218 | d6b24130 | Marios Kogias | |
219 | d6b24130 | Marios Kogias | def network_to_dict(network): |
220 | d6b24130 | Marios Kogias | d = {'id': str(network.id), 'name': network.name} |
221 | d6b24130 | Marios Kogias | d['links'] = util.network_to_links(network.id)
|
222 | d6b24130 | Marios Kogias | d['user_id'] = network.userid
|
223 | d6b24130 | Marios Kogias | d['tenant_id'] = network.userid
|
224 | d6b24130 | Marios Kogias | d['type'] = network.flavor
|
225 | d6b24130 | Marios Kogias | d['updated'] = utils.isoformat(network.updated)
|
226 | d6b24130 | Marios Kogias | d['created'] = utils.isoformat(network.created)
|
227 | d6b24130 | Marios Kogias | d['status'] = network.state
|
228 | d6b24130 | Marios Kogias | d['public'] = network.public
|
229 | d6b24130 | Marios Kogias | d['admin_state_up'] = "true" |
230 | d6b24130 | Marios Kogias | subnet_cidr = [s.subnet_id for s in network.subnet_set.all()] |
231 | d6b24130 | Marios Kogias | d['subnets'] = subnet_cidr
|
232 | d6b24130 | Marios Kogias | return d
|
233 | d6b24130 | Marios Kogias | |
234 | d6b24130 | Marios Kogias | |
235 | d6b24130 | Marios Kogias | |
236 | d6b24130 | Marios Kogias | |
237 | d6b24130 | Marios Kogias | |
238 | d6b24130 | Marios Kogias | def render_network(request, networkdict, status=200): |
239 | d6b24130 | Marios Kogias | if request.serialization == 'xml': |
240 | d6b24130 | Marios Kogias | data = render_to_string('network.xml', {'network': networkdict}) |
241 | d6b24130 | Marios Kogias | else:
|
242 | d6b24130 | Marios Kogias | data = json.dumps({'network': networkdict})
|
243 | d6b24130 | Marios Kogias | return HttpResponse(data, status=status)
|
244 | d6b24130 | Marios Kogias | |
245 | d6b24130 | Marios Kogias | |
246 | d6b24130 | Marios Kogias | |
247 | d6b24130 | Marios Kogias | |
248 | d6b24130 | Marios Kogias | def get_network_fromdb(network_id, user_id, for_update=False): |
249 | d6b24130 | Marios Kogias | """
|
250 | d6b24130 | Marios Kogias | Return a Network instance or raise ItemNotFound.
|
251 | d6b24130 | Marios Kogias | This is the same as util.get_network
|
252 | d6b24130 | Marios Kogias | """
|
253 | d6b24130 | Marios Kogias | try:
|
254 | d6b24130 | Marios Kogias | network_id = int(network_id)
|
255 | d6b24130 | Marios Kogias | objects = Network.objects |
256 | d6b24130 | Marios Kogias | if for_update:
|
257 | d6b24130 | Marios Kogias | objects = objects.select_for_update() |
258 | d6b24130 | Marios Kogias | return objects.get(Q(userid=user_id) | Q(public=True), id=network_id) |
259 | d6b24130 | Marios Kogias | except (ValueError, Network.DoesNotExist): |
260 | d6b24130 | Marios Kogias | raise api.faults.ItemNotFound('Network not found.') |