17
17
"""The security groups extension."""
19
from xml.dom import minidom
21
22
from webob import exc
22
from xml.dom import minidom
24
24
from nova.api.openstack import common
25
25
from nova.api.openstack import extensions
29
29
from nova.compute import api as compute_api
30
30
from nova import db
31
31
from nova import exception
32
from nova.network.security_group import openstack_driver
33
from nova.network.security_group import quantum_driver
34
32
from nova.openstack.common import log as logging
35
from nova.virt import netutils
38
34
LOG = logging.getLogger(__name__)
39
35
authorize = extensions.extension_authorizer('compute', 'security_groups')
111
107
Deserializer to handle xml-formatted security group requests.
113
109
def default(self, string):
114
"""Deserialize an xml-formatted security group create request."""
115
dom = xmlutil.safe_minidom_parse_string(string)
110
"""Deserialize an xml-formatted security group create request"""
111
dom = minidom.parseString(string)
116
112
security_group = {}
117
113
sg_node = self.find_first_child_named(dom,
118
114
'security_group')
134
130
def default(self, string):
135
"""Deserialize an xml-formatted security group create request."""
136
dom = xmlutil.safe_minidom_parse_string(string)
131
"""Deserialize an xml-formatted security group create request"""
132
dom = minidom.parseString(string)
137
133
security_group_rule = self._extract_security_group_rule(dom)
138
134
return {'body': {'security_group_rule': security_group_rule}}
140
136
def _extract_security_group_rule(self, node):
141
"""Marshal the security group rule attribute of a parsed request."""
137
"""Marshal the security group rule attribute of a parsed request"""
143
139
sg_rule_node = self.find_first_child_named(node,
144
140
'security_group_rule')
179
175
"""Base class for Security Group controllers."""
181
177
def __init__(self):
182
self.security_group_api = (
183
openstack_driver.get_openstack_security_group_driver())
178
self.security_group_api = NativeSecurityGroupAPI()
184
179
self.compute_api = compute.API(
185
180
security_group_api=self.security_group_api)
196
191
if rule['group_id']:
197
192
source_group = self.security_group_api.get(context,
198
193
id=rule['group_id'])
199
sg_rule['group'] = {'name': source_group.get('name'),
200
'tenant_id': source_group.get('project_id')}
194
sg_rule['group'] = {'name': source_group.name,
195
'tenant_id': source_group.project_id}
202
197
sg_rule['ip_range'] = {'cidr': rule['cidr']}
219
214
authorize(context)
217
def _validate_id(self, id):
221
msg = _("Security group id should be integer")
222
raise exc.HTTPBadRequest(explanation=msg)
222
224
def _from_body(self, body, key):
224
226
raise exc.HTTPUnprocessableEntity()
236
238
"""Return data about the given security group."""
237
239
context = self._authorize_context(req)
239
id = self.security_group_api.validate_id(id)
241
id = self._validate_id(id)
241
243
security_group = self.security_group_api.get(context, None, id,
242
244
map_exception=True)
248
250
"""Delete a security group."""
249
251
context = self._authorize_context(req)
251
id = self.security_group_api.validate_id(id)
253
id = self._validate_id(id)
253
255
security_group = self.security_group_api.get(context, None, id,
254
256
map_exception=True)
272
274
limited_list = common.limited(raw_groups, req)
273
275
result = [self._format_security_group(context, group)
274
for group in limited_list]
276
for group in limited_list]
276
278
return {'security_groups':
277
279
list(sorted(result,
292
294
self.security_group_api.validate_property(group_description,
293
295
'description', None)
295
group_ref = self.security_group_api.create_security_group(
296
context, group_name, group_description)
297
group_ref = self.security_group_api.create(context, group_name,
298
300
return {'security_group': self._format_security_group(context,
302
304
class SecurityGroupRulesController(SecurityGroupControllerBase):
309
311
sg_rule = self._from_body(body, 'security_group_rule')
311
parent_group_id = self.security_group_api.validate_id(
312
sg_rule.get('parent_group_id', None))
313
parent_group_id = self._validate_id(sg_rule.get('parent_group_id',
314
316
security_group = self.security_group_api.get(context, None,
315
317
parent_group_id, map_exception=True)
317
new_rule = self._rule_args_to_dict(context,
320
values = self._rule_args_to_dict(context,
318
321
to_port=sg_rule.get('to_port'),
319
322
from_port=sg_rule.get('from_port'),
320
323
ip_protocol=sg_rule.get('ip_protocol'),
323
326
except Exception as exp:
324
327
raise exc.HTTPBadRequest(explanation=unicode(exp))
327
330
msg = _("Not enough parameters to build a valid rule.")
328
331
raise exc.HTTPBadRequest(explanation=msg)
330
new_rule['parent_group_id'] = security_group['id']
332
if 'cidr' in new_rule:
333
net, prefixlen = netutils.get_net_and_prefixlen(new_rule['cidr'])
334
if net != '0.0.0.0' and prefixlen == '0':
335
msg = _("Bad prefix for network in cidr %s") % new_rule['cidr']
336
raise exc.HTTPBadRequest(explanation=msg)
338
security_group_rule = (
339
self.security_group_api.create_security_group_rule(
340
context, security_group, new_rule))
333
values['parent_group_id'] = security_group.id
335
if self.security_group_api.rule_exists(security_group, values):
336
msg = _('This rule already exists in group %s') % parent_group_id
337
raise exc.HTTPBadRequest(explanation=msg)
339
security_group_rule = self.security_group_api.add_rules(
340
context, parent_group_id, security_group['name'], [values])[0]
342
342
return {"security_group_rule": self._format_security_group_rule(
347
347
ip_protocol=None, cidr=None, group_id=None):
349
349
if group_id is not None:
350
group_id = self.security_group_api.validate_id(group_id)
352
# check if groupId exists
350
group_id = self._validate_id(group_id)
351
#check if groupId exists
353
352
self.security_group_api.get(context, id=group_id)
354
353
return self.security_group_api.new_group_ingress_rule(
355
354
group_id, ip_protocol, from_port, to_port)
361
360
def delete(self, req, id):
362
361
context = self._authorize_context(req)
364
id = self.security_group_api.validate_id(id)
363
id = self._validate_id(id)
366
365
rule = self.security_group_api.get_rule(context, id)
368
group_id = rule['parent_group_id']
367
group_id = rule.parent_group_id
370
369
security_group = self.security_group_api.get(context, None, group_id,
371
370
map_exception=True)
403
402
class SecurityGroupActionController(wsgi.Controller):
404
403
def __init__(self, *args, **kwargs):
405
404
super(SecurityGroupActionController, self).__init__(*args, **kwargs)
406
self.security_group_api = (
407
openstack_driver.get_openstack_security_group_driver())
405
self.security_group_api = NativeSecurityGroupAPI()
408
406
self.compute_api = compute.API(
409
407
security_group_api=self.security_group_api)
463
461
def __init__(self, *args, **kwargs):
464
462
super(SecurityGroupsOutputController, self).__init__(*args, **kwargs)
465
463
self.compute_api = compute.API()
466
self.security_group_api = (
467
openstack_driver.get_openstack_security_group_driver())
469
465
def _extend_servers(self, req, servers):
470
466
key = "security_groups"
471
if not openstack_driver.is_quantum_security_groups():
472
for server in servers:
473
instance = req.get_db_instance(server['id'])
474
groups = instance.get(key)
476
server[key] = [{"name": group["name"]} for group in groups]
478
# If method is a POST we get the security groups intended for an
479
# instance from the request. The reason for this is if using
480
# quantum security groups the requested security groups for the
481
# instance are not in the db and have not been sent to quantum yet.
483
if req.method != 'POST':
484
for server in servers:
486
self.security_group_api.get_instance_security_groups(
490
# try converting to json
491
req_obj = json.loads(req.body)
492
# Add security group to server, if no security group was in
493
# request add default since that is the group it is part of
494
instance_sgs = req_obj['server'].get(
495
key, [{'name': 'default'}])
497
root = minidom.parseString(req.body)
498
sg_root = root.getElementsByTagName(key)
500
security_groups = sg_root[0].getElementsByTagName(
502
for security_group in security_groups:
504
{'name': security_group.getAttribute('name')})
506
instance_sgs = [{'name': 'default'}]
509
for server in servers:
510
server[key] = instance_sgs
467
for server in servers:
468
instance = req.get_db_instance(server['id'])
469
groups = instance.get(key)
471
server[key] = [{"name": group["name"]} for group in groups]
512
473
def _show(self, req, resp_obj):
513
474
if not softauth(req.environ['nova.context']):
563
524
class Security_groups(extensions.ExtensionDescriptor):
564
"""Security group support."""
525
"""Security group support"""
565
526
name = "SecurityGroups"
566
527
alias = "os-security-groups"
567
528
namespace = "http://docs.openstack.org/compute/ext/securitygroups/api/v1.1"
620
581
def raise_not_found(msg):
621
582
raise exc.HTTPNotFound(explanation=msg)
624
class NativeNovaSecurityGroupAPI(NativeSecurityGroupExceptions,
625
compute_api.SecurityGroupAPI):
629
class NativeQuantumSecurityGroupAPI(NativeSecurityGroupExceptions,
630
quantum_driver.SecurityGroupAPI):