docs: def valid_hacluster_config():
      '''
      Check that either vip or dns-ha is set. If dns-ha then one of os-*-hostname
      must be set.
  
      Note: ha-bindiface and ha-macastport both have defaults and will always
      be set. We only care that either vip or dns-ha is set.
  
      :returns: boolean: valid config returns true.
      raises: HAIncompatibileConfig if settings conflict.
      raises: HAIncompleteConfig if settings are missing.
      '''
      vip = config_get('vip')
      dns = config_get('dns-ha')
      if not(bool(vip) ^ bool(dns)):
          msg = ('HA: Either vip or dns-ha must be set but not both in order to '
                 'use high availability')
          status_set('blocked', msg)
          raise HAIncorrectConfig(msg)
  
      # If dns-ha then one of os-*-hostname must be set
      if dns:
          dns_settings = ['os-internal-hostname', 'os-admin-hostname',
                          'os-public-hostname', 'os-access-hostname']
          # At this point it is unknown if one or all of the possible
          # network spaces are in HA. Validate at least one is set which is
          # the minimum required.
          for setting in dns_settings:
              if config_get(setting):
                  log('DNS HA: At least one hostname is set {}: {}'
                      ''.format(setting, config_get(setting)),
                      level=DEBUG)
                  return True
  
          msg = ('DNS HA: At least one os-*-hostname(s) must be set to use '
                 'DNS HA')
          status_set('blocked', msg)
          raise HAIncompleteConfig(msg)
  
      log('VIP HA: VIP is set {}'.format(vip), level=DEBUG)
      return True