~openstack-charmers-next/charms/trusty/nova-cloud-controller/trunk

« back to all changes in this revision

Viewing changes to hooks/charmhelpers/contrib/openstack/context.py

  • Committer: Liam Young
  • Date: 2016-04-12 14:09:23 UTC
  • Revision ID: liam.young@canonical.com-20160412140923-5yie4mt86023vyxi
Charmhelper sync before 1604 testing

Change-Id: Ie00b1a39d14fc44f702aa6b664e8d12ec4fc5de7

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
import re
21
21
import time
22
22
from base64 import b64decode
23
 
from subprocess import check_call
 
23
from subprocess import check_call, CalledProcessError
24
24
 
25
25
import six
26
26
import yaml
45
45
    INFO,
46
46
    WARNING,
47
47
    ERROR,
 
48
    status_set,
48
49
)
49
50
 
50
51
from charmhelpers.core.sysctl import create as sysctl_create
1491
1492
    """
1492
1493
    def __call__(self):
1493
1494
        return {'use_internal_endpoints': config('use-internal-endpoints')}
 
1495
 
 
1496
 
 
1497
class AppArmorContext(OSContextGenerator):
 
1498
    """Base class for apparmor contexts."""
 
1499
 
 
1500
    def __init__(self):
 
1501
        self._ctxt = None
 
1502
        self.aa_profile = None
 
1503
        self.aa_utils_packages = ['apparmor-utils']
 
1504
 
 
1505
    @property
 
1506
    def ctxt(self):
 
1507
        if self._ctxt is not None:
 
1508
            return self._ctxt
 
1509
        self._ctxt = self._determine_ctxt()
 
1510
        return self._ctxt
 
1511
 
 
1512
    def _determine_ctxt(self):
 
1513
        """
 
1514
        Validate aa-profile-mode settings is disable, enforce, or complain.
 
1515
 
 
1516
        :return ctxt: Dictionary of the apparmor profile or None
 
1517
        """
 
1518
        if config('aa-profile-mode') in ['disable', 'enforce', 'complain']:
 
1519
            ctxt = {'aa-profile-mode': config('aa-profile-mode')}
 
1520
        else:
 
1521
            ctxt = None
 
1522
        return ctxt
 
1523
 
 
1524
    def __call__(self):
 
1525
        return self.ctxt
 
1526
 
 
1527
    def install_aa_utils(self):
 
1528
        """
 
1529
        Install packages required for apparmor configuration.
 
1530
        """
 
1531
        log("Installing apparmor utils.")
 
1532
        ensure_packages(self.aa_utils_packages)
 
1533
 
 
1534
    def manually_disable_aa_profile(self):
 
1535
        """
 
1536
        Manually disable an apparmor profile.
 
1537
 
 
1538
        If aa-profile-mode is set to disabled (default) this is required as the
 
1539
        template has been written but apparmor is yet unaware of the profile
 
1540
        and aa-disable aa-profile fails. Without this the profile would kick
 
1541
        into enforce mode on the next service restart.
 
1542
 
 
1543
        """
 
1544
        profile_path = '/etc/apparmor.d'
 
1545
        disable_path = '/etc/apparmor.d/disable'
 
1546
        if not os.path.lexists(os.path.join(disable_path, self.aa_profile)):
 
1547
            os.symlink(os.path.join(profile_path, self.aa_profile),
 
1548
                       os.path.join(disable_path, self.aa_profile))
 
1549
 
 
1550
    def setup_aa_profile(self):
 
1551
        """
 
1552
        Setup an apparmor profile.
 
1553
        The ctxt dictionary will contain the apparmor profile mode and
 
1554
        the apparmor profile name.
 
1555
        Makes calls out to aa-disable, aa-complain, or aa-enforce to setup
 
1556
        the apparmor profile.
 
1557
        """
 
1558
        self()
 
1559
        if not self.ctxt:
 
1560
            log("Not enabling apparmor Profile")
 
1561
            return
 
1562
        self.install_aa_utils()
 
1563
        cmd = ['aa-{}'.format(self.ctxt['aa-profile-mode'])]
 
1564
        cmd.append(self.ctxt['aa-profile'])
 
1565
        log("Setting up the apparmor profile for {} in {} mode."
 
1566
            "".format(self.ctxt['aa-profile'], self.ctxt['aa-profile-mode']))
 
1567
        try:
 
1568
            check_call(cmd)
 
1569
        except CalledProcessError as e:
 
1570
            # If aa-profile-mode is set to disabled (default) manual
 
1571
            # disabling is required as the template has been written but
 
1572
            # apparmor is yet unaware of the profile and aa-disable aa-profile
 
1573
            # fails. If aa-disable learns to read profile files first this can
 
1574
            # be removed.
 
1575
            if self.ctxt['aa-profile-mode'] == 'disable':
 
1576
                log("Manually disabling the apparmor profile for {}."
 
1577
                    "".format(self.ctxt['aa-profile']))
 
1578
                self.manually_disable_aa_profile()
 
1579
                return
 
1580
            status_set('blocked', "Apparmor profile {} failed to be set to {}."
 
1581
                                  "".format(self.ctxt['aa-profile'],
 
1582
                                            self.ctxt['aa-profile-mode']))
 
1583
            raise e