Exemplo n.º 1
0
class CheckOperations(object):
    def __init__(self, application, info):
        self.application = application
        self.info = info
        self.ucr = ConfigRegistry()
        self.ucr.load()

    @classmethod
    def installed(cls, application, info):
        print("Running checks if correctly installed..")
        checks = cls(application, info)
        return all(
            (checks._check_dpkg_installed_status(),
             checks._check_ucr_variables_exist(), checks._check_files_exist(),
             checks._check_ldap_object_exists(),
             checks._check_url_accessible()))

    @classmethod
    def uninstalled(cls, application, info):
        print("Running checks if correctly uninstalled..")
        checks = cls(application, info)
        return all((checks._check_dpkg_uninstalled_status(),
                    checks._check_ucr_variables_dont_exist(),
                    checks._check_ldap_object_doesnt_exist()))

    def _fail(self, message):
        msg = "Error in (un)installed checks for {}: {}"
        print(msg.format(self.application, message))
        return False

    def _packages(self):
        for package in self.info.get("default_packages", list()):
            yield package
        master = ("domaincontroller_master", "domaincontroller_backup")
        if self.ucr.get("server/role") in master:
            for package in self.info.get("default_packages_master", list()):
                yield package

    def _dpkg_status(self, package):
        cmd = ["dpkg-query", "-f='${db:Status-Abbrev}xx'", "--show", package]
        output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
        (expected_char, current_char) = output[:2]
        expected = {
            "u": "unknown",
            "i": "install",
            "h": "hold",
            "r": "remove",
            "p": "purge"
        }.get(expected_char, "unknown")
        current = {
            "n": "not-installed",
            "c": "config-files",
            "U": "unpacked",
            "H": "half-installed",
            "F": "half-configured",
            "W": "triggers-awaited",
            "t": "tritters-pending",
            "i": "installed"
        }.get(current_char, "unknown")
        return (expected, current)

    def _get_dn(self):
        app_version = self.info.get("version")
        ldap_base = self.ucr.get("ldap/base")
        dn = "univentionAppID={id}_{version},cn={id},cn=apps,cn=univention,{base}"
        return dn.format(id=self.application,
                         version=app_version,
                         base=ldap_base)

    def _check_url(self, protocol, port, interface):
        fqdn = '{}.{}'.format(self.ucr.get("hostname"),
                              self.ucr.get("domainname"))
        url = "{}://{}:{}{}".format(protocol, fqdn, port, interface)
        response = requests.get(url, timeout=30, verify=False)

        try:
            response.raise_for_status()
        except requests.HTTPError:
            return self._fail("webinterface at {} not reachable".format(url))

        refresh = lxml.html.fromstring(
            response.text).cssselect('meta[http-equiv="refresh"]')

        if refresh:
            link = refresh[0].attrib['content'].partition("=")[2]
            return self._check_url(protocol, port, link)
        return True

    def _check_dpkg_installed_status(self):
        for package in self._packages():
            try:
                (expected, current) = self._dpkg_status(package)
                error = current != "installed"
            except subprocess.CalledProcessError:
                error = True
            if error:
                msg = "`dpkg -s {}` does not report as installed"
                return self._fail(msg.format(package))
        print("OK - dpkg reports correctly installed")
        return True

    def _check_dpkg_uninstalled_status(self):
        for package in self._packages():
            try:
                (expected, current) = self._dpkg_status(package)
                error = current not in ("not-installed", "unknown",
                                        "config-files")
            except subprocess.CalledProcessError as e:
                error = e.returncode != 1
            if error:
                msg = "`dpkg -s {}` does not report as uninstalled"
                return self._fail(msg.format(package))
        print("OK - dpkg reports correctly uninstalled")
        return True

    def _check_files_exist(self):
        for package in self._packages():
            output = subprocess.check_output(["dpkg", "--listfiles", package])
            for path in output.splitlines():
                if not os.path.exists(path):
                    msg = "{} from {} does not exist in filesystem"
                    return self._fail(msg.format(path, package))
        print("OK - All files exist in the filesystem after installation.")
        return True

    def _check_ucr_variables_exist(self):
        interface = self.info.get("web_interface")
        port_http = self.info.get("web_interface_port_http")
        port_https = self.info.get("web_interface_port_https")
        scheme = self.info.get("ucs_overview_category", "service")

        web_entries_base = "ucs/web/overview/entries/{}/{}".format(
            scheme, self.application)
        pairs = (("/link", interface), ("/port_http", str(port_http)),
                 ("/port_https", str(port_https)))

        if interface and port_http and port_https:
            unequal = [
                web_entries_base + ex for (ex, value) in pairs
                if self.ucr.get(web_entries_base + ex) != value
            ]
            if unequal:
                msg = "following UCR variables not set correctly: {}"
                return self._fail(msg.format(", ".join(unequal)))

            msg = "OK - All UCR variables ({}) set correctly after installation."
            print(msg.format(web_entries_base))
        return True

    def _check_ucr_variables_dont_exist(self):
        repository = "repository/online/component/{}".format(
            self.info.get("component_id"))
        web_entries = "ucs/web/overview/entries/(admin|service)/{}".format(
            self.application)
        pattern = re.compile("{}|{}".format(repository, web_entries))
        active = [key for key in self.ucr.keys() if pattern.match(key)]
        if active:
            msg = "following UCR variables still active: {}"
            return self._fail(msg.format(", ".join(active)))
        print("OK - All UCR variables removed after uninstallation.")
        return True

    def _check_ldap_object_exists(self):
        try:
            utils.verify_ldap_object(self._get_dn())
        except utils.LDAPObjectNotFound as e:
            return self._fail("Not Found: " + str(e))
        print("OK - LDAP object created after installation.")
        return True

    def _check_ldap_object_doesnt_exist(self):
        try:
            utils.verify_ldap_object(self._get_dn(), should_exist=False)
        except utils.LDAPUnexpectedObjectFound as e:
            return self._fail("Found unexpected: " + str(e))
        print("OK - LDAP object removed after uninstallation.")
        return True

    def _check_url_accessible(self):
        interface = self.info.get("web_interface")
        port_http = self.info.get("web_interface_port_http")
        port_https = self.info.get("web_interface_port_https")

        if all((interface, port_http, port_https)) and \
         self._check_url("http", port_http, interface) and \
         self._check_url("https", port_https, interface):
            print("OK - Webinterface reachable after installation.")
        return True
	'cn=dns,%(ldap/base)s' % configRegistry,
	'cn=mail,%(ldap/base)s' % configRegistry,
	'cn=samba,%(ldap/base)s' % configRegistry,
	'cn=nagios,%(ldap/base)s' % configRegistry,
	'cn=System,%(connector/ad/ldap/base)s' % configRegistry,
	'ou=Grp Policy Users,%(connector/ad/ldap/base)s' % configRegistry,
	'cn=Builtin,%(connector/ad/ldap/base)s' % configRegistry,
	'cn=ForeignSecurityPrincipals,%(connector/ad/ldap/base)s' % configRegistry,
	'ou=Domain Controllers,%(connector/ad/ldap/base)s' % configRegistry,
	'cn=Program Data,%(connector/ad/ldap/base)s' % configRegistry,
	'cn=Configuration,%(connector/ad/ldap/base)s' % configRegistry,
	'cn=opsi,%(ldap/base)s' % configRegistry,
	'cn=Microsoft Exchange System Objects,%(connector/ad/ldap/base)s' % configRegistry
]

for k in configRegistry.keys():
	if k.startswith('connector/ad/mapping/ignoresubtree/'):
		global_ignore_subtree.append(configRegistry.get(k))

user_ignore_list = ignore_filter_from_tmpl('(uid={0!e})(CN={0!e})', 'connector/ad/mapping/user/ignorelist')
user_ignore_filter = configRegistry.get('connector/ad/mapping/user/ignorefilter', '')
if user_ignore_filter and not user_ignore_filter.startswith('('):
	user_ignore_filter = '({})'.format(user_ignore_filter)
user_ignore_filter = '(|{}{}{})'.format('(userAccountControl=2080)', user_ignore_filter, user_ignore_list)

ignore_filter_parts = '(groupType=-2147483643)(groupType=4)(univentionGroupType=-2147483643)(univentionGroupType=4)'
if configRegistry.is_false('connector/ad/mapping/group/grouptype', False):
	ignore_filter_parts += '(sambaGroupType=5)(groupType=5)'
ignore_filter_parts += ignore_filter_from_attr('cn', 'connector/ad/mapping/group/ignorelist')
group_ignore_filter = '(|{})'.format(ignore_filter_parts)