예제 #1
0
def assess_status_helper():
    """Assess status of unit

    @returns status, message - status is workload status and message is any
                               corresponding messages
    """
    if config('stonith_enabled') in ['true', 'True', True]:
        return ('blocked',
                'stonith_enabled config option is no longer supported')

    if is_unit_upgrading_set():
        return ("blocked",
                "Ready for do-release-upgrade. Set complete when finished")
    if is_waiting_unit_series_upgrade_set():
        return ("blocked",
                "HA services shutdown, peers are ready for series upgrade")
    if is_unit_paused_set():
        return ("maintenance",
                "Paused. Use 'resume' action to resume normal service.")

    node_count = int(config('cluster_count'))
    status = 'active'
    message = 'Unit is ready and clustered'
    try:
        try_pcmk_wait()
    except pcmk.ServicesNotUp:
        message = 'Pacemaker is down'
        status = 'blocked'
    for relid in relation_ids('hanode'):
        if len(related_units(relid)) + 1 < node_count:
            status = 'blocked'
            message = ("Insufficient peer units for ha cluster "
                       "(require {})".format(node_count))

    # if the status was not changed earlier, we verify the maintenance status
    try:
        if status == 'active':
            prop = pcmk.get_property('maintenance-mode').strip()
    except pcmk.PropertyNotFound:
        # the property is not the output of 'crm configure show xml', so we use
        # the default value for this property. For crmsh>=2.2.0 the default
        # value is automatically provided by show-property or get-property.
        prop = 'false'

    if (status == 'active' and prop == 'true'):
        # maintenance mode enabled in pacemaker
        status = 'maintenance'
        message = 'Pacemaker in maintenance mode'

    for resource in get_resources().keys():
        if not pcmk.is_resource_present(resource):
            return ("waiting",
                    "Resource: {} not yet configured".format(resource))
        if not pcmk.crm_res_running_on_node(resource, get_hostname()):
            return ("blocked", "Resource: {} not running".format(resource))

    return status, message
예제 #2
0
def configure_legacy_stonith():
    if config('stonith_enabled') not in ['true', 'True', True]:
        if configure_pacemaker_remote_stonith_resource():
            log('Not disabling STONITH as pacemaker remotes are present',
                level=INFO)
        else:
            log('Disabling STONITH', level=INFO)
            cmd = "crm configure property stonith-enabled=false"
            pcmk.commit(cmd)
    else:
        log('Enabling STONITH for all nodes in cluster.', level=INFO)
        # configure stontih resources for all nodes in cluster.
        # note: this is totally provider dependent and requires
        # access to the MAAS API endpoint, using endpoint and credentials
        # set in config.
        url = config('maas_url')
        creds = config('maas_credentials')
        if None in [url, creds]:
            msg = 'maas_url and maas_credentials must be set ' \
                  'in config to enable STONITH.'
            status_set('blocked', msg)
            raise Exception(msg)

        nodes = maas.MAASHelper(url, creds).list_nodes()
        if not nodes:
            msg = 'Could not obtain node inventory from ' \
                  'MAAS @ %s.' % url
            status_set('blocked', msg)
            raise Exception(msg)

        cluster_nodes = pcmk.list_nodes()
        for node in cluster_nodes:
            rsc, constraint = pcmk.maas_stonith_primitive(nodes, node)
            if not rsc:
                msg = 'Failed to determine STONITH primitive for ' \
                      'node %s' % node
                status_set('blocked', msg)
                raise Exception(msg)

            rsc_name = str(rsc).split(' ')[1]
            if not pcmk.is_resource_present(rsc_name):
                log('Creating new STONITH primitive %s.' % rsc_name,
                    level=DEBUG)
                cmd = 'crm -F configure %s' % rsc
                pcmk.commit(cmd)
                if constraint:
                    cmd = 'crm -F configure %s' % constraint
                    pcmk.commit(cmd)
            else:
                log('STONITH primitive already exists for node.', level=DEBUG)

        pcmk.commit("crm configure property stonith-enabled=true")
예제 #3
0
def configure_stonith():
    if config('stonith_enabled') not in ['true', 'True', True]:
        if configure_pacemaker_remote_stonith_resource():
            log('Not disabling STONITH as pacemaker remotes are present',
                level=INFO)
        else:
            log('Disabling STONITH', level=INFO)
            cmd = "crm configure property stonith-enabled=false"
            pcmk.commit(cmd)
    else:
        log('Enabling STONITH for all nodes in cluster.', level=INFO)
        # configure stontih resources for all nodes in cluster.
        # note: this is totally provider dependent and requires
        # access to the MAAS API endpoint, using endpoint and credentials
        # set in config.
        url = config('maas_url')
        creds = config('maas_credentials')
        if None in [url, creds]:
            msg = 'maas_url and maas_credentials must be set ' \
                  'in config to enable STONITH.'
            status_set('blocked', msg)
            raise Exception(msg)

        nodes = maas.MAASHelper(url, creds).list_nodes()
        if not nodes:
            msg = 'Could not obtain node inventory from ' \
                  'MAAS @ %s.' % url
            status_set('blocked', msg)
            raise Exception(msg)

        cluster_nodes = pcmk.list_nodes()
        for node in cluster_nodes:
            rsc, constraint = pcmk.maas_stonith_primitive(nodes, node)
            if not rsc:
                msg = 'Failed to determine STONITH primitive for ' \
                      'node %s' % node
                status_set('blocked', msg)
                raise Exception(msg)

            rsc_name = str(rsc).split(' ')[1]
            if not pcmk.is_resource_present(rsc_name):
                log('Creating new STONITH primitive %s.' % rsc_name,
                    level=DEBUG)
                cmd = 'crm -F configure %s' % rsc
                pcmk.commit(cmd)
                if constraint:
                    cmd = 'crm -F configure %s' % constraint
                    pcmk.commit(cmd)
            else:
                log('STONITH primitive already exists for node.', level=DEBUG)

        pcmk.commit("crm configure property stonith-enabled=true")
예제 #4
0
def configure_pacemaker_remote(remote_hostname, remote_ip):
    """Create a resource corresponding to the pacemaker remote node.

    :param remote_hostname: Remote hostname used for registering remote node.
    :type remote_hostname: str
    :param remote_ip: Remote IP used for registering remote node.
    :type remote_ip: str
    :returns: Name of resource for pacemaker remote node.
    :rtype: str
    """
    resource_name = remote_hostname
    if not pcmk.is_resource_present(resource_name):
        cmd = ("crm configure primitive {} ocf:pacemaker:remote "
               "params server={} reconnect_interval=60 "
               "op monitor interval=30s").format(resource_name, remote_ip)
        pcmk.commit(cmd, failure_is_fatal=True)
    return resource_name
예제 #5
0
def configure_maas_stonith_resource(stonith_hostnames):
    """Create stonith resource for the given hostname.

    :param stonith_hostnames: The hostnames that the stonith management system
                             refers to the remote node as.
    :type stonith_hostname: List
    """
    hostnames = []
    for host in stonith_hostnames:
        hostnames.append(host)
        if '.' in host:
            hostnames.append(host.split('.')[0])
    hostnames = list(set(hostnames))
    ctxt = {
        'url': config('maas_url'),
        'apikey': config('maas_credentials'),
        'hostnames': ' '.join(sorted(hostnames))}
    if all(ctxt.values()):
        maas_login_params = "url='{url}' apikey='{apikey}'".format(**ctxt)
        maas_rsc_hash = pcmk.resource_checksum(
            'st',
            'stonith:external/maas',
            res_params=maas_login_params)[:7]
        ctxt['stonith_resource_name'] = 'st-maas-{}'.format(maas_rsc_hash)
        ctxt['resource_params'] = (
            "params url='{url}' apikey='{apikey}' hostnames='{hostnames}' "
            "op monitor interval=25 start-delay=25 "
            "timeout=25").format(**ctxt)
        if pcmk.is_resource_present(ctxt['stonith_resource_name']):
            pcmk.crm_update_resource(
                ctxt['stonith_resource_name'],
                'stonith:external/maas',
                ctxt['resource_params'])
        else:
            cmd = (
                "crm configure primitive {stonith_resource_name} "
                "stonith:external/maas {resource_params}").format(**ctxt)
            pcmk.commit(cmd, failure_is_fatal=True)
        pcmk.commit(
            "crm configure property stonith-enabled=true",
            failure_is_fatal=True)
    else:
        raise ValueError("Missing configuration: {}".format(ctxt))
    return {ctxt['stonith_resource_name']: 'stonith:external/maas'}
예제 #6
0
def configure_maas_stonith_resource(stonith_hostnames):
    """Create stonith resource for the given hostname.

    :param stonith_hostnames: The hostnames that the stonith management system
                             refers to the remote node as.
    :type stonith_hostname: List
    """
    hostnames = []
    for host in stonith_hostnames:
        hostnames.append(host)
        if '.' in host:
            hostnames.append(host.split('.')[0])
    hostnames = list(set(hostnames))
    ctxt = {
        'url': config('maas_url'),
        'apikey': config('maas_credentials'),
        'hostnames': ' '.join(sorted(hostnames))}
    if all(ctxt.values()):
        maas_login_params = "url='{url}' apikey='{apikey}'".format(**ctxt)
        maas_rsc_hash = pcmk.resource_checksum(
            'st',
            'stonith:external/maas',
            res_params=maas_login_params)[:7]
        ctxt['stonith_resource_name'] = 'st-maas-{}'.format(maas_rsc_hash)
        ctxt['resource_params'] = (
            "params url='{url}' apikey='{apikey}' hostnames='{hostnames}' "
            "op monitor interval=25 start-delay=25 "
            "timeout=25").format(**ctxt)
        if pcmk.is_resource_present(ctxt['stonith_resource_name']):
            pcmk.crm_update_resource(
                ctxt['stonith_resource_name'],
                'stonith:external/maas',
                ctxt['resource_params'])
        else:
            cmd = (
                "crm configure primitive {stonith_resource_name} "
                "stonith:external/maas {resource_params}").format(**ctxt)
            pcmk.commit(cmd, failure_is_fatal=True)
        pcmk.commit(
            "crm configure property stonith-enabled=true",
            failure_is_fatal=True)
    else:
        raise ValueError("Missing configuration: {}".format(ctxt))
    return {ctxt['stonith_resource_name']: 'stonith:external/maas'}
예제 #7
0
def _configure_stonith_resource(ctxt):
    hostnames = []
    for host in ctxt['stonith_hostnames']:
        hostnames.append(host)
        if '.' in host:
            hostnames.append(host.split('.')[0])
    ctxt['hostnames'] = ' '.join(sorted(list(set(hostnames))))
    if all(ctxt.values()):
        ctxt['resource_params'] = ctxt['resource_params'].format(**ctxt)
        if pcmk.is_resource_present(ctxt['stonith_resource_name']):
            pcmk.crm_update_resource(ctxt['stonith_resource_name'],
                                     ctxt['stonith_plugin'],
                                     ctxt['resource_params'])
        else:
            cmd = ("crm configure primitive {stonith_resource_name} "
                   "{stonith_plugin} {resource_params}").format(**ctxt)
            pcmk.commit(cmd, failure_is_fatal=True)
    else:
        raise ValueError("Missing configuration: {}".format(ctxt))
예제 #8
0
def configure_pacemaker_remote(remote_hostname, remote_ip):
    """Create a resource corresponding to the pacemaker remote node.

    :param remote_hostname: Remote hostname used for registering remote node.
    :type remote_hostname: str
    :param remote_ip: Remote IP used for registering remote node.
    :type remote_ip: str
    :returns: Name of resource for pacemaker remote node.
    :rtype: str
    """
    resource_name = remote_hostname.split('.')[0]
    if not pcmk.is_resource_present(resource_name):
        cmd = (
            "crm configure primitive {} ocf:pacemaker:remote "
            "params server={} reconnect_interval=60 "
            "op monitor interval=30s").format(resource_name,
                                              remote_ip)
        pcmk.commit(cmd, failure_is_fatal=True)
    return resource_name