~ubuntu-branches/ubuntu/raring/nova/raring-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, Yolanda Robla, James Page
  • Date: 2013-01-11 13:06:56 UTC
  • mfrom: (1.1.67)
  • Revision ID: package-import@ubuntu.com-20130111130656-7n7fkevy03stm3mv
Tags: 2013.1~g2-0ubuntu1
[ Chuck Short ]
* New upstream release.
* debian/patches/ubuntu-show-tests.patch: Dropped no longer needed.
* debian/nova-xcp-plugins.install: Fix xcp-plugins empty packages
* debian/control: Drop python-nose in favor or testrepository
* debian/control: Add python-coverage as a build dep.
* debian/rules, debian/control: Run pep8 tests.
* debian/*.init: Remove they are not needed and take up space
* debian/control, debian/nova-cells.{install, logrotate, upstart}: Add
  cells support.
* debian/patches/fix-ubuntu-tests.patch: temporarily disable failing tests.
* debian/control, debian/nova-baremetal.{install, logrotate, upstart}: Add
  nova baremetal support.
* debian/control: Remove python-support.

[ Adam Gandelman ]
* debian/*.manpages: Install Sphinx-generated manpages instead of
  our own.
* debian/nova-compute-*.conf: Specify the newly required compute_driver
  flag in addition to libvirt_type.
* debian/control:  Specify required python-webob and python-stevedore
  versions.

[ Yolanda Robla ]
* debian/*.upstart: Use start-stop-daemon instead of su for chuid
  (LP: #1086833).
* debian/rules: Remove override of dh_installinit for discriminating
  between Debian and Ubuntu.
* debian/nova-common.docs: Installing changelogs from rules
* debian/rules: Replacing perms in /etc/nova/logging.conf for 0644
* debian/control: adduser dependency on nova-compute.
* debian/control: added section oldlibs and priority extra on
  nova-ajax-console-proxy.
* debian/nova-xvpvncproxy.postrm: removing because of duplicates.

[ James Page ]
* d/control: Add ~ to python-sqlalchemy-ext versioned dependencies to
  make backporting easier.
* d/control: Updated nova-volume description and depdendencies to
  mark it as a transitional package, moved to oldlibs/extra.
* d/p/fix-libvirt-tests.patch: Dropped; accepted upstream.
* d/control: Added python-stevedore to BD's.
* d/*.postrm: Dropped postrm's that just run update-rc.d; this is not
  required when deploying upstart configurations only.
* d/nova-scheduler.manpages: Add man page for nova-rpc-zmq-receiver.
* d/rules: Install upstream changelog with a policy compliant name.
* d/control: Mark nova-compute-xcp as virtual package.
* d/control: nova-api-os-volume; Depend on cinder-api and mark as
  transitional package.
* d/nova-api-os-volume.lintian-overrides: Dropped - no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright 2011 OpenStack Foundation
 
1
# Copyright 2011 OpenStack LLC.
2
2
# Copyright 2012 Justin Santa Barbara
3
3
# All Rights Reserved.
4
4
#
16
16
 
17
17
"""The security groups extension."""
18
18
 
19
 
import json
 
19
from xml.dom import minidom
 
20
 
20
21
import webob
21
22
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
34
32
from nova.openstack.common import log as logging
35
 
from nova.virt import netutils
36
 
 
37
33
 
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.
112
108
    """
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')
132
128
    """
133
129
 
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}}
139
135
 
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"""
142
138
        sg_rule = {}
143
139
        sg_rule_node = self.find_first_child_named(node,
144
140
                                                   'security_group_rule')
179
175
    """Base class for Security Group controllers."""
180
176
 
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)
186
181
 
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}
201
196
        else:
202
197
            sg_rule['ip_range'] = {'cidr': rule['cidr']}
203
198
        return sg_rule
219
214
        authorize(context)
220
215
        return context
221
216
 
 
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
 
222
224
    def _from_body(self, body, key):
223
225
        if not body:
224
226
            raise exc.HTTPUnprocessableEntity()
236
238
        """Return data about the given security group."""
237
239
        context = self._authorize_context(req)
238
240
 
239
 
        id = self.security_group_api.validate_id(id)
 
241
        id = self._validate_id(id)
240
242
 
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)
250
252
 
251
 
        id = self.security_group_api.validate_id(id)
 
253
        id = self._validate_id(id)
252
254
 
253
255
        security_group = self.security_group_api.get(context, None, id,
254
256
                                                     map_exception=True)
259
261
 
260
262
    @wsgi.serializers(xml=SecurityGroupsTemplate)
261
263
    def index(self, req):
262
 
        """Returns a list of security groups."""
 
264
        """Returns a list of security groups"""
263
265
        context = self._authorize_context(req)
264
266
 
265
267
        search_opts = {}
271
273
 
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]
275
277
 
276
278
        return {'security_groups':
277
279
                list(sorted(result,
292
294
        self.security_group_api.validate_property(group_description,
293
295
                                                  'description', None)
294
296
 
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
                                                   group_description)
297
299
 
298
300
        return {'security_group': self._format_security_group(context,
299
 
                                                              group_ref)}
 
301
                                                                 group_ref)}
300
302
 
301
303
 
302
304
class SecurityGroupRulesController(SecurityGroupControllerBase):
308
310
 
309
311
        sg_rule = self._from_body(body, 'security_group_rule')
310
312
 
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
                                                        None))
313
315
 
314
316
        security_group = self.security_group_api.get(context, None,
315
317
                                          parent_group_id, map_exception=True)
 
318
 
316
319
        try:
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))
325
328
 
326
 
        if new_rule is None:
 
329
        if values is None:
327
330
            msg = _("Not enough parameters to build a valid rule.")
328
331
            raise exc.HTTPBadRequest(explanation=msg)
329
332
 
330
 
        new_rule['parent_group_id'] = security_group['id']
331
 
 
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)
337
 
 
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
 
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]
341
341
 
342
342
        return {"security_group_rule": self._format_security_group_rule(
343
343
                                                        context,
347
347
                           ip_protocol=None, cidr=None, group_id=None):
348
348
 
349
349
        if group_id is not None:
350
 
            group_id = self.security_group_api.validate_id(group_id)
351
 
 
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)
363
362
 
364
 
        id = self.security_group_api.validate_id(id)
 
363
        id = self._validate_id(id)
365
364
 
366
365
        rule = self.security_group_api.get_rule(context, id)
367
366
 
368
 
        group_id = rule['parent_group_id']
 
367
        group_id = rule.parent_group_id
369
368
 
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)
410
408
 
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())
468
464
 
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)
475
 
                if groups:
476
 
                    server[key] = [{"name": group["name"]} for group in groups]
477
 
        else:
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.
482
 
            instance_sgs = []
483
 
            if req.method != 'POST':
484
 
                for server in servers:
485
 
                    instance_sgs = (
486
 
                        self.security_group_api.get_instance_security_groups(
487
 
                            req, server['id']))
488
 
            else:
489
 
                try:
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'}])
496
 
                except ValueError:
497
 
                    root = minidom.parseString(req.body)
498
 
                    sg_root = root.getElementsByTagName(key)
499
 
                    if sg_root:
500
 
                        security_groups = sg_root[0].getElementsByTagName(
501
 
                            'security_group')
502
 
                        for security_group in security_groups:
503
 
                            instance_sgs.append(
504
 
                                {'name': security_group.getAttribute('name')})
505
 
                    if not instance_sgs:
506
 
                        instance_sgs = [{'name': 'default'}]
507
 
 
508
 
            if instance_sgs:
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)
 
470
            if groups:
 
471
                server[key] = [{"name": group["name"]} for group in groups]
511
472
 
512
473
    def _show(self, req, resp_obj):
513
474
        if not softauth(req.environ['nova.context']):
561
522
 
562
523
 
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"
595
556
        return resources
596
557
 
597
558
 
598
 
class NativeSecurityGroupExceptions(object):
 
559
class NativeSecurityGroupAPI(compute_api.SecurityGroupAPI):
599
560
    @staticmethod
600
561
    def raise_invalid_property(msg):
601
562
        raise exc.HTTPBadRequest(explanation=msg)
619
580
    @staticmethod
620
581
    def raise_not_found(msg):
621
582
        raise exc.HTTPNotFound(explanation=msg)
622
 
 
623
 
 
624
 
class NativeNovaSecurityGroupAPI(NativeSecurityGroupExceptions,
625
 
                                 compute_api.SecurityGroupAPI):
626
 
    pass
627
 
 
628
 
 
629
 
class NativeQuantumSecurityGroupAPI(NativeSecurityGroupExceptions,
630
 
                                    quantum_driver.SecurityGroupAPI):
631
 
    pass