~ubuntu-branches/ubuntu/saucy/nova/saucy-proposed

« back to all changes in this revision

Viewing changes to nova/api/openstack/compute/contrib/security_groups.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short, Adam Gandelman
  • Date: 2013-02-22 09:27:29 UTC
  • mfrom: (1.1.68)
  • Revision ID: package-import@ubuntu.com-20130222092729-nn3gt8rf97uvts77
Tags: 2013.1.g3-0ubuntu1
[ Chuck Short ]
* New usptream release. 
* debian/patches/debian/patches/fix-ubuntu-tests.patch: Refreshed.
* debian/nova-baremetal.logrotate: Fix logfile path.
* debian/control, debian/nova-spiceproxy.{install, logrotate, upstart}:
  Add spice html5 proxy support.
* debian/nova-novncproxy.upstart: Start on runlevel [2345]
* debian/rules: Call testr directly since run_tests.sh -N gives weird return
  value when tests pass.
* debian/pyddist-overrides: Add websockify.
* debian/nova-common.postinst: Removed config file conversion, since
  the option is no longer available. (LP: #1110567)
* debian/control: Add python-pyasn1 as a dependency.
* debian/control: Add python-oslo-config as a dependency.
* debian/control: Suggest sysfsutils, sg3-utils, multipath-tools for fibre
  channel support.

[ Adam Gandelman ]
* debian/control: Fix typo (websocikfy -> websockify).

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""The security groups extension."""
18
18
 
19
 
from xml.dom import minidom
20
 
 
 
19
import json
21
20
import webob
22
21
from webob import exc
 
22
from xml.dom import minidom
23
23
 
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
 
37
 
33
38
 
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.
108
113
    """
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')
128
133
    """
129
134
 
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}}
135
140
 
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."""
138
143
        sg_rule = {}
139
144
        sg_rule_node = self.find_first_child_named(node,
140
145
                                                   'security_group_rule')
175
180
    """Base class for Security Group controllers."""
176
181
 
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)
181
187
 
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')}
196
202
        else:
197
203
            sg_rule['ip_range'] = {'cidr': rule['cidr']}
198
204
        return sg_rule
214
220
        authorize(context)
215
221
        return context
216
222
 
217
 
    def _validate_id(self, id):
218
 
        try:
219
 
            return int(id)
220
 
        except ValueError:
221
 
            msg = _("Security group id should be integer")
222
 
            raise exc.HTTPBadRequest(explanation=msg)
223
 
 
224
223
    def _from_body(self, body, key):
225
224
        if not body:
226
225
            raise exc.HTTPUnprocessableEntity()
238
237
        """Return data about the given security group."""
239
238
        context = self._authorize_context(req)
240
239
 
241
 
        id = self._validate_id(id)
 
240
        id = self.security_group_api.validate_id(id)
242
241
 
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)
252
251
 
253
 
        id = self._validate_id(id)
 
252
        id = self.security_group_api.validate_id(id)
254
253
 
255
254
        security_group = self.security_group_api.get(context, None, id,
256
255
                                                     map_exception=True)
261
260
 
262
261
    @wsgi.serializers(xml=SecurityGroupsTemplate)
263
262
    def index(self, req):
264
 
        """Returns a list of security groups"""
 
263
        """Returns a list of security groups."""
265
264
        context = self._authorize_context(req)
266
265
 
267
266
        search_opts = {}
273
272
 
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]
277
276
 
278
277
        return {'security_groups':
279
278
                list(sorted(result,
294
293
        self.security_group_api.validate_property(group_description,
295
294
                                                  'description', None)
296
295
 
297
 
        group_ref = self.security_group_api.create(context, group_name,
298
 
                                                   group_description)
 
296
        group_ref = self.security_group_api.create_security_group(
 
297
            context, group_name, group_description)
299
298
 
300
299
        return {'security_group': self._format_security_group(context,
301
 
                                                                 group_ref)}
 
300
                                                              group_ref)}
302
301
 
303
302
 
304
303
class SecurityGroupRulesController(SecurityGroupControllerBase):
310
309
 
311
310
        sg_rule = self._from_body(body, 'security_group_rule')
312
311
 
313
 
        parent_group_id = self._validate_id(sg_rule.get('parent_group_id',
314
 
                                                        None))
 
312
        parent_group_id = self.security_group_api.validate_id(
 
313
            sg_rule.get('parent_group_id', None))
315
314
 
316
315
        security_group = self.security_group_api.get(context, None,
317
316
                                          parent_group_id, map_exception=True)
318
 
 
319
317
        try:
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))
328
326
 
329
 
        if values is None:
 
327
        if new_rule is None:
330
328
            msg = _("Not enough parameters to build a valid rule.")
331
329
            raise exc.HTTPBadRequest(explanation=msg)
332
330
 
333
 
        values['parent_group_id'] = security_group.id
334
 
 
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)
338
 
 
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']
 
332
 
 
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)
 
338
 
 
339
        security_group_rule = (
 
340
            self.security_group_api.create_security_group_rule(
 
341
                context, security_group, new_rule))
341
342
 
342
343
        return {"security_group_rule": self._format_security_group_rule(
343
344
                                                        context,
347
348
                           ip_protocol=None, cidr=None, group_id=None):
348
349
 
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)
 
352
 
 
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)
362
364
 
363
 
        id = self._validate_id(id)
 
365
        id = self.security_group_api.validate_id(id)
364
366
 
365
367
        rule = self.security_group_api.get_rule(context, id)
366
368
 
367
 
        group_id = rule.parent_group_id
 
369
        group_id = rule['parent_group_id']
368
370
 
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)
408
411
 
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())
464
469
 
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)
470
 
            if groups:
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)
 
476
                if groups:
 
477
                    server[key] = [{"name": group["name"]} for group in groups]
 
478
        else:
 
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.
 
483
            instance_sgs = []
 
484
            if req.method != 'POST':
 
485
                for server in servers:
 
486
                    instance_sgs = (
 
487
                        self.security_group_api.get_instance_security_groups(
 
488
                            req, server['id']))
 
489
            else:
 
490
                try:
 
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'}])
 
497
                except ValueError:
 
498
                    root = minidom.parseString(req.body)
 
499
                    sg_root = root.getElementsByTagName(key)
 
500
                    if sg_root:
 
501
                        security_groups = sg_root[0].getElementsByTagName(
 
502
                            'security_group')
 
503
                        for security_group in security_groups:
 
504
                            instance_sgs.append(
 
505
                                {'name': security_group.getAttribute('name')})
 
506
                    if not instance_sgs:
 
507
                        instance_sgs = [{'name': 'default'}]
 
508
 
 
509
            if instance_sgs:
 
510
                for server in servers:
 
511
                    server[key] = instance_sgs
472
512
 
473
513
    def _show(self, req, resp_obj):
474
514
        if not softauth(req.environ['nova.context']):
522
562
 
523
563
 
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"
556
596
        return resources
557
597
 
558
598
 
559
 
class NativeSecurityGroupAPI(compute_api.SecurityGroupAPI):
 
599
class NativeSecurityGroupExceptions(object):
560
600
    @staticmethod
561
601
    def raise_invalid_property(msg):
562
602
        raise exc.HTTPBadRequest(explanation=msg)
580
620
    @staticmethod
581
621
    def raise_not_found(msg):
582
622
        raise exc.HTTPNotFound(explanation=msg)
 
623
 
 
624
 
 
625
class NativeNovaSecurityGroupAPI(compute_api.SecurityGroupAPI,
 
626
                                 NativeSecurityGroupExceptions):
 
627
    pass
 
628
 
 
629
 
 
630
class NativeQuantumSecurityGroupAPI(quantum_driver.SecurityGroupAPI,
 
631
                                    NativeSecurityGroupExceptions):
 
632
    pass