Current File : //proc/self/root/lib/python3/dist-packages/sos/collector/clusters/__init__.py
# Copyright Red Hat 2020, Jake Hunsaker <jhunsake@redhat.com>

# This file is part of the sos project: https://github.com/sosreport/sos
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# version 2 of the GNU General Public License.
#
# See the LICENSE file in the source distribution for further information.

import logging

from threading import Lock
from sos.options import ClusterOption
from sos.utilities import bold


class Cluster():
    """This is the class that cluster profiles should subclass in order to
    add support for different clustering technologies and environments to
    sos collect.

    A profile should at minimum define a package that indicates the node is
    configured for the type of cluster the profile is intended to serve and
    then additionally be able to return a list of enumerated nodes via the
    ``get_nodes()`` method


    :param commons: The commons dict containing system information. The same as
                    what is handed to ``Plugin()``
    :type commons: ``dict``


    :cvar option_list:  Options supported by the profile, and set by the
                        --cluster-option cmdline arg
    :vartype option_list: ``list`` of ``tuples``

    :cvar packages: What package(s) should this profile enable on
    :vartype packages: ``tuple``

    :cvar sos_plugins: Which plugins to forcibly enable for node reports
    :vartype sos_plugins: ``list``

    :cvar sos_options: Options to pass to report on every node
    :vartype sos_options: ``dict``

    :cvar sos_plugin_options: Plugin options to forcibly set for nodes
    :vartype sos_plugin_options: ``dict``

    :cvar sos_preset: A SoSReport preset to forcibly enable on nodes
    :vartype sos_preset: ``str``

    :cvar cluster_name: The name of the cluster type
    :vartype cluster_name: ``str``
    """

    option_list = []
    packages = ('',)
    sos_plugins = []
    sos_options = {}
    sos_plugin_options = {}
    sos_preset = ''
    cluster_name = None
    # set this to True if the local host running collect should *not* be
    # forcibly added to the node list. This can be helpful in situations where
    # the host's fqdn and the name the cluster uses are different
    strict_node_list = False

    def __init__(self, commons):
        self.primary = None
        self.cluster_ssh_key = None
        self.tmpdir = commons['tmpdir']
        self.opts = commons['cmdlineopts']
        self.cluster_type = [self.__class__.__name__]
        for cls in self.__class__.__bases__:
            if cls.__name__ != 'Cluster':
                self.cluster_type.append(cls.__name__)
        self.node_list = None
        self.lock = Lock()
        self.soslog = logging.getLogger('sos')
        self.ui_log = logging.getLogger('sos_ui')
        self.options = []
        self._get_options()

    @classmethod
    def name(cls):
        """Returns the cluster's name as a string.
        """
        if cls.cluster_name:
            return cls.cluster_name
        return cls.__name__.lower()

    @classmethod
    def display_help(cls, section):  # pylint: disable=too-many-branches
        if cls is Cluster:
            cls.display_self_help(section)
            return
        section.set_title(f"{cls.cluster_name} Cluster Profile Detailed Help")
        if cls.__doc__ and cls.__doc__ is not Cluster.__doc__:
            section.add_text(cls.__doc__)
        # [1] here is the actual cluster profile
        elif cls.__mro__[1].__doc__ and cls.__mro__[1] is not Cluster:
            section.add_text(cls.__mro__[1].__doc__)
        else:
            section.add_text(
                "\n\tDetailed help not available for this profile\n"
            )

        if cls.packages:
            section.add_text(
                "Enabled by the following packages: "
                f"{', '.join(p for p in cls.packages)}",
                newline=False
            )

        if cls.sos_preset:
            section.add_text(
                f"Uses the following sos preset: {cls.sos_preset}",
                newline=False
            )

        if cls.sos_options:
            _opts = ', '.join(f'--{k} {v}' for k, v in cls.sos_options.items())
            section.add_text(f"Sets the following sos options: {_opts}")

        if cls.sos_plugins:
            section.add_text(
                "Enables the following plugins: "
                f"{', '.join(plug for plug in cls.sos_plugins)}",
                newline=False
            )

        if cls.sos_plugin_options:
            _opts = cls.sos_plugin_options
            opts = ', '.join(f"{k}={v}" for k, v in _opts.items())
            section.add_text(
                f"Sets the following plugin options: {opts}",
                newline=False
            )

        if cls.option_list:
            optsec = section.add_section("Available cluster options")
            optsec.add_text(
                "These options may be toggled or changed using "
                f"'{bold(f'-c {cls.__name__}.$option=$value')}'"
            )
            optsec.add_text(
                bold(
                    f"\n{' ':<4}{'Option Name':<20}{'Default':<30}"
                    f"{'Description':<20}\n"),
                newline=False
            )
            for opt in cls.option_list:
                val = opt[1]
                if isinstance(val, bool):
                    if val:
                        val = 'True/On'
                    else:
                        val = 'False/Off'
                _ln = f"{' ':<4}{opt[0]:<20}{val:<30}{opt[2]:<20}"
                optsec.add_text(_ln, newline=False)

    @classmethod
    def display_self_help(cls, section):
        section.set_title('SoS Collect Cluster Profiles Detailed Help')
        section.add_text(
            '\nCluster profiles are used to represent different clustering '
            'technologies or platforms. Profiles define how cluster nodes are '
            'discovered, and optionally filtered, for default executions of '
            'collector.'
        )
        section.add_text(
            'Cluster profiles are enabled similarly to SoS report plugins; '
            'usually by package, command, or configuration file presence. '
            'Clusters may also define default transports for SoS collect.'
        )

        from sos.collector import SoSCollector
        import inspect
        clusters = SoSCollector._load_modules(inspect.getmodule(cls),
                                              'clusters')

        section.add_text(
            'The following cluster profiles are locally available:\n'
        )
        section.add_text(
            f"{' ':>8}{'Name':<40}{'Description':<30}",
            newline=False
        )
        for cluster in clusters:
            _sec = bold(f"collect.clusters.{cluster[0]}")
            section.add_text(
                f"{' ':>8}{_sec:<40}{cluster[1].cluster_name:<30}",
                newline=False
            )

    def _get_options(self):
        """Loads the options defined by a cluster and sets the default value"""
        for opt in self.option_list:
            option = ClusterOption(name=opt[0], opt_type=opt[1].__class__,
                                   value=opt[1], cluster=self.cluster_type,
                                   description=opt[2])
            self.options.append(option)

    def _fmt_msg(self, msg):
        return f'[{self.cluster_type[0]}] {msg}'

    def log_info(self, msg):
        """Used to print info messages"""
        self.soslog.info(self._fmt_msg(msg))

    def log_error(self, msg):
        """Used to print error messages"""
        self.soslog.error(msg)

    def log_debug(self, msg):
        """Used to print debug messages"""
        self.soslog.debug(self._fmt_msg(msg))

    def log_warn(self, msg):
        """Used to print warning messages"""
        self.soslog.warning(self._fmt_msg(msg))

    def get_option(self, option):
        """
        This is used to by clusters to check if a cluster option was
        supplied to sos collect

        :param option: The name of the option to fetch
        :type option: ``str``

        :returns: The value of the requested option if it exists, or ``False``
        """
        # check CLI before defaults
        for opt in self.opts.cluster_options:
            if opt.name == option and opt.cluster in self.cluster_type:
                return opt.value
        # provide defaults otherwise
        for opt in self.options:
            if opt.name == option:
                return opt.value
        return False

    def add_default_ssh_key(self, key):
        """Some clusters generate and/or deploy well-known and consistent
        SSH keys across environments. If this is the case, the cluster profile
        may call this command so that subsequent node connections will use that
        key rather than prompting the user for one or a password.

        Note this will only function if collector is being run locally on the
        primary node.
        """
        self.cluster_ssh_key = key

    def set_node_options(self, node):
        """If there is a need to set specific options on ONLY the non-primary
        nodes in a collection, override this method in the cluster profile
        and do that here.

        :param node:        The non-primary node
        :type node:         ``SoSNode``
        """

    def set_transport_type(self):
        """The default connection type used by sos collect is to leverage the
        local system's SSH installation using ControlPersist, however certain
        cluster types may want to use something else.

        Override this in a specific cluster profile to set the ``transport``
        option according to what type of transport should be used.
        """
        return 'control_persist'

    def set_primary_options(self, node):
        """If there is a need to set specific options in the sos command being
        run on the cluster's primary nodes, override this method in the cluster
        profile and do that here.

        :param node:       The primary node
        :type node:        ``SoSNode``
        """

    def check_node_is_primary(self, node):
        """In the event there are multiple primaries, or if the collect command
        is being run from a system that is technically capable of enumerating
        nodes but the cluster profiles needs to specify primary-specific
        options for other nodes, override this method in the cluster profile

        :param node:        The node for the cluster to check
        :type node:         ``SoSNode``
        """
        return node.address == self.primary.address

    def exec_primary_cmd(self, cmd, need_root=False, timeout=180,
                         use_shell='auto'):
        """Used to retrieve command output from a (primary) node in a cluster

        :param cmd: The command to run
        :type cmd: ``str``

        :param need_root: Does the command require root privileges
        :type need_root: ``bool``

        :param timeout:  Amount of time to allow cmd to run in seconds
        :type timeout: ``int``

        :param use_shell:   Does the command required execution within a shell?
        :type use_shell:    ``auto`` or ``bool``

        :returns: The output and status of `cmd`
        :rtype: ``dict``
        """
        res = self.primary.run_command(cmd, need_root=need_root,
                                       use_shell=use_shell, timeout=timeout)
        if res['output']:
            res['output'] = res['output'].replace('Password:', '')
        return res

    def setup(self):
        """
        This MAY be used by a cluster to do prep work in case there are
        extra commands to be run even if a node list is given by the user, and
        thus get_nodes() would not be called
        """

    def check_enabled(self):
        """
        This may be overridden by clusters

        This is called by sos collect on each cluster type that exists, and
        is meant to return True when the cluster type matches a criteria
        that indicates that is the cluster type is in use.

        Only the first cluster type to determine a match is run

        :returns: ``True`` if the cluster profile should be used, or ``False``
        :rtype: ``bool``
        """
        for pkg in self.packages:
            if self.primary.is_installed(pkg):
                return True
        return False

    def cleanup(self):
        """
        This may be overridden by clusters

        Perform any necessary cleanup steps required by the cluster profile.
        This helps ensure that sos does make lasting changes to the environment
        in which we are running
        """

    def get_nodes(self):
        """
        This MUST be overridden by a cluster profile subclassing this class

        A cluster should use this method to return a list or string that
        contains all the nodes that a report should be collected from

        :returns: A list of node FQDNs or IP addresses
        :rtype: ``list`` or ``None``
        """
        raise NotImplementedError

    def _get_nodes(self):
        try:
            return self.format_node_list()
        except Exception as e:
            self.log_debug(f'Failed to get node list: {e}')
            return []

    def get_node_label(self, node):
        """
        Used by ``SosNode()`` to retrieve the appropriate label from the
        cluster as set by ``set_node_label()`` in the cluster profile.

        :param node: The name of the node to get a label for
        :type node: ``str``

        :returns: The label to use for the node's report
        :rtype: ``str``
        """
        label = self.set_node_label(node)
        node.manifest.add_field('label', label)
        return label

    def set_node_label(self, node):  # pylint: disable=unused-argument
        """This may be overridden by clusters profiles subclassing this class

        If there is a distinction between primaries and nodes, or types of
        nodes, then this can be used to label the sos report archives as needed
        """
        return ''

    def format_node_list(self):
        """
        Format the returned list of nodes from a cluster into a known
        format. This being a list that contains no duplicates

        :returns: A list of nodes, without extraneous entries from cmd output
        :rtype: ``list``
        """
        try:
            nodes = self.get_nodes()
        except Exception as err:
            raise Exception(f"Cluster failed to enumerate nodes: {err}") \
                from err
        if isinstance(nodes, list):
            node_list = [n.strip() for n in nodes if n]
        elif isinstance(nodes, str):
            node_list = [n.split(',').strip() for n in nodes]
        else:
            raise Exception(f"Cluster returned unexpected node list: {nodes}")
        node_list = list(set(node_list))
        for node in node_list:
            if node.startswith(('-', '_', '(', ')', '[', ']', '/', '\\')):
                node_list.remove(node)
        return node_list

    def _run_extra_cmd(self):
        """
        Ensures that any files returned by a cluster's run_extra_cmd()
        method are properly typed as a list for iterative collection. If any
        of the files are an additional sos report (e.g. the ovirt db dump) then
        the md5 sum file is automatically added to the list
        """
        files = []
        try:
            res = self.run_extra_cmd()
            if res:
                if not isinstance(res, list):
                    res = [res]
                for extra_file in res:
                    extra_file = extra_file.strip()
                    files.append(extra_file)
                    if 'sosreport' in extra_file:
                        files.append(extra_file + '.md5')
        except AttributeError:
            # run_extra_cmd() not defined for cluster profile
            pass
        return files
¿Qué es la limpieza dental de perros? - Clínica veterinaria


Es la eliminación del sarro y la placa adherida a la superficie de los dientes mediante un equipo de ultrasonidos que garantiza la integridad de las piezas dentales a la vez que elimina en profundidad cualquier resto de suciedad.

A continuación se procede al pulido de los dientes mediante una fresa especial que elimina la placa bacteriana y devuelve a los dientes el aspecto sano que deben tener.

Una vez terminado todo el proceso, se mantiene al perro en observación hasta que se despierta de la anestesia, bajo la atenta supervisión de un veterinario.

¿Cada cuánto tiempo tengo que hacerle una limpieza dental a mi perro?

A partir de cierta edad, los perros pueden necesitar una limpieza dental anual o bianual. Depende de cada caso. En líneas generales, puede decirse que los perros de razas pequeñas suelen acumular más sarro y suelen necesitar una atención mayor en cuanto a higiene dental.


Riesgos de una mala higiene


Los riesgos más evidentes de una mala higiene dental en los perros son los siguientes:

  • Cuando la acumulación de sarro no se trata, se puede producir una inflamación y retracción de las encías que puede descalzar el diente y provocar caídas.
  • Mal aliento (halitosis).
  • Sarro perros
  • Puede ir a más
  • Las bacterias de la placa pueden trasladarse a través del torrente circulatorio a órganos vitales como el corazón ocasionando problemas de endocarditis en las válvulas. Las bacterias pueden incluso acantonarse en huesos (La osteomielitis es la infección ósea, tanto cortical como medular) provocando mucho dolor y una artritis séptica).

¿Cómo se forma el sarro?

El sarro es la calcificación de la placa dental. Los restos de alimentos, junto con las bacterias presentes en la boca, van a formar la placa bacteriana o placa dental. Si la placa no se retira, al mezclarse con la saliva y los minerales presentes en ella, reaccionará formando una costra. La placa se calcifica y se forma el sarro.

El sarro, cuando se forma, es de color blanquecino pero a medida que pasa el tiempo se va poniendo amarillo y luego marrón.

Síntomas de una pobre higiene dental
La señal más obvia de una mala salud dental canina es el mal aliento.

Sin embargo, a veces no es tan fácil de detectar
Y hay perros que no se dejan abrir la boca por su dueño. Por ejemplo…

Recientemente nos trajeron a la clínica a un perro que parpadeaba de un ojo y decía su dueño que le picaba un lado de la cara. Tenía molestias y dificultad para comer, lo que había llevado a sus dueños a comprarle comida blanda (que suele ser un poco más cara y llevar más contenido en grasa) durante medio año. Después de una exploración oftalmológica, nos dimos cuenta de que el ojo tenía una úlcera en la córnea probablemente de rascarse . Además, el canto lateral del ojo estaba inflamado. Tenía lo que en humanos llamamos flemón pero como era un perro de pelo largo, no se le notaba a simple vista. Al abrirle la boca nos llamó la atención el ver una muela llena de sarro. Le realizamos una radiografía y encontramos una fístula que llegaba hasta la parte inferior del ojo.

Le tuvimos que extraer la muela. Tras esto, el ojo se curó completamente con unos colirios y una lentilla protectora de úlcera. Afortunadamente, la úlcera no profundizó y no perforó el ojo. Ahora el perro come perfectamente a pesar de haber perdido una muela.

¿Cómo mantener la higiene dental de tu perro?
Hay varias maneras de prevenir problemas derivados de la salud dental de tu perro.

Limpiezas de dientes en casa
Es recomendable limpiar los dientes de tu perro semanal o diariamente si se puede. Existe una gran variedad de productos que se pueden utilizar:

Pastas de dientes.
Cepillos de dientes o dedales para el dedo índice, que hacen más fácil la limpieza.
Colutorios para echar en agua de bebida o directamente sobre el diente en líquido o en spray.

En la Clínica Tus Veterinarios enseñamos a nuestros clientes a tomar el hábito de limpiar los dientes de sus perros desde que son cachorros. Esto responde a nuestro compromiso con la prevención de enfermedades caninas.

Hoy en día tenemos muchos clientes que limpian los dientes todos los días a su mascota, y como resultado, se ahorran el dinero de hacer limpiezas dentales profesionales y consiguen una mejor salud de su perro.


Limpiezas dentales profesionales de perros y gatos

Recomendamos hacer una limpieza dental especializada anualmente. La realizamos con un aparato de ultrasonidos que utiliza agua para quitar el sarro. Después, procedemos a pulir los dientes con un cepillo de alta velocidad y una pasta especial. Hacemos esto para proteger el esmalte.

La frecuencia de limpiezas dentales necesaria varía mucho entre razas. En general, las razas grandes tienen buena calidad de esmalte, por lo que no necesitan hacerlo tan a menudo e incluso pueden pasarse la vida sin requerir una limpieza. Sin embargo, razas pequeñas como el Yorkshire o el Maltés, deben hacérselas todos los años desde cachorros si se quiere conservar sus piezas dentales.

Otro factor fundamental es la calidad del pienso. Algunas marcas han diseñado croquetas que limpian la superficie del diente y de la muela al masticarse.

Ultrasonido para perros

¿Se necesita anestesia para las limpiezas dentales de perros y gatos?

La limpieza dental en perros no es una técnica que pueda practicarse sin anestesia general , aunque hay veces que los propietarios no quieren anestesiar y si tiene poco sarro y el perro es muy bueno se puede intentar…… , pero no se va a poder pulir ni acceder a todas la zona de la boca …. Además los limpiadores dentales van a irrigar agua y hay riesgo de aspiración a vías respiratorias si no se realiza una anestesia correcta con intubación traqueal . En resumen , sin anestesia no se va hacer una correcta limpieza dental.

Tampoco sirve la sedación ya que necesitamos que el animal esté totalmente quieto, y el veterinario tenga un acceso completo a todas sus piezas dentales y encías.

Alimentos para la limpieza dental

Hay que tener cierto cuidado a la hora de comprar determinados alimentos porque no todos son saludables. Algunos tienen demasiado contenido graso, que en exceso puede causar problemas cardiovasculares y obesidad.

Los mejores alimentos para los dientes son aquellos que están elaborados por empresas farmacéuticas y llevan componentes químicos con tratamientos específicos para el diente del perro. Esto implica no solo limpieza a través de la acción mecánica de morder sino también un tratamiento antibacteriano para prevenir el sarro.

Conclusión

Si eres como la mayoría de dueños, por falta de tiempo , es probable que no estés prestando la suficiente atención a la limpieza dental de tu perro. Por eso te animamos a que comiences a limpiar los dientes de tu perro y consideres atender a su higiene bucal con frecuencia.

Estas simples medidas pueden conllevar a que tu perro tenga una vida más larga y mucho más saludable.

Si te resulta imposible introducir un cepillo de dientes a tu perro en la boca, pásate con él por clínica Tus Veterinarios y te explicamos cómo hacerlo.

Necesitas hacer una limpieza dental profesional a tu mascota?
Llámanos al 622575274 o contacta con nosotros

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

¡Hola!