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