<commit_before># Copyright (c) 2011 OpenStack Foundation
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""
Manages packages on the Guest VM.
"""
import commands
import re
import subprocess
from tempfile import NamedTemporaryFile
import os
import pexpect
import six

from trove.common import exception
from trove.common import utils
from trove.common.exception import ProcessExecutionError
from trove.guestagent.common import operating_system
from trove.openstack.common import log as logging
from trove.openstack.common.gettextutils import _


LOG = logging.getLogger(__name__)
OK = 0
RUN_DPKG_FIRST = 1
REINSTALL_FIRST = 2
CONFLICT_REMOVED = 3


class PkgAdminLockError(exception.TroveError):
    pass


class PkgPermissionError(exception.TroveError):
    pass


class PkgPackageStateError(exception.TroveError):
    pass


class PkgNotFoundError(exception.NotFound):
    pass


class PkgTimeout(exception.TroveError):
    pass


class PkgScriptletError(exception.TroveError):
    pass


class PkgDownloadError(exception.TroveError):
    pass


class PkgSignError(exception.TroveError):
    pass


class PkgBrokenError(exception.TroveError):
    pass


class BasePackagerMixin:

    def pexpect_kill_proc(self, child):
        child.delayafterclose = 1
        child.delayafterterminate = 1
        try:
            child.close(force=True)
        except pexpect.ExceptionPexpect:
            # Close fails to terminate a sudo process on some OSes.
            subprocess.call(['sudo', 'kill', str(child.pid)])

    def pexpect_wait_and_close_proc(self, child):
        child.expect(pexpect.EOF)
        child.close()

    def pexpect_run(self, cmd, output_expects, time_out):
        child = pexpect.spawn(cmd, timeout=time_out)
        try:
            i = child.expect(output_expects)
            match = child.match
            self.pexpect_wait_and_close_proc(child)
        except pexpect.TIMEOUT:
            self.pexpect_kill_proc(child)
            raise PkgTimeout("Process timeout after %i seconds." % time_out)
        return (i, match)


class RedhatPackagerMixin(BasePackagerMixin):

    def _rpm_remove_nodeps(self, package_name):
        """
        Sometimes transaction errors happens, easy way is to remove
        conflicted package without dependencies and hope it will replaced
        by another package
        """
        try:
            utils.execute("rpm", "-e", "--nodeps", package_name,
                          run_as_root=True, root_helper="sudo")
        except ProcessExecutionError:
            LOG.exception(_("Error removing conflict %(package)s") %
                          package_name)

    def _install(self, packages, time_out):
        """Attempts to install packages.

        Returns OK if the packages are installed or a result code if a
        recoverable-error occurred.
        Raises an exception if a non-recoverable error or timeout occurs.

        """
        cmd = "sudo yum --color=never -y install %s" % packages
        output_expects = ['\[sudo\] password for .*:',
                          'No package (.*) available.',
                          ('file .* from install of .* conflicts with file'
                           ' from package (.*?)\r\n'),
                          'Error: (.*?) conflicts with .*?\r\n',
                          'Processing Conflict: .* conflicts (.*?)\r\n',
                          '.*scriptlet failed*',
                          'HTTP Error',
                          'No more mirrors to try.',
                          'GPG key retrieval failed:',
                          '.*already installed and latest version',
                          'Updated:',
                          'Installed:']
        LOG.debug("Running package install command: %s" % cmd)
        i, match = self.pexpect_run(cmd, output_expects, time_out)
        if i == 0:
            raise PkgPermissionError("Invalid permissions.")
        elif i == 1:<commit_msg>Yum install should get a list of packages as a string<commit_after># Copyright (c) 2011 OpenStack Foundation
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""
Manages packages on the Guest VM.
"""
import commands
import re
import subprocess
from tempfile import NamedTemporaryFile
import os
import pexpect
import six

from trove.common import exception
from trove.common import utils
from trove.common.exception import ProcessExecutionError
from trove.guestagent.common import operating_system
from trove.openstack.common import log as logging
from trove.openstack.common.gettextutils import _


LOG = logging.getLogger(__name__)
OK = 0
RUN_DPKG_FIRST = 1
REINSTALL_FIRST = 2
CONFLICT_REMOVED = 3


class PkgAdminLockError(exception.TroveError):
    pass


class PkgPermissionError(exception.TroveError):
    pass


class PkgPackageStateError(exception.TroveError):
    pass


class PkgNotFoundError(exception.NotFound):
    pass


class PkgTimeout(exception.TroveError):
    pass


class PkgScriptletError(exception.TroveError):
    pass


class PkgDownloadError(exception.TroveError):
    pass


class PkgSignError(exception.TroveError):
    pass


class PkgBrokenError(exception.TroveError):
    pass


class BasePackagerMixin:

    def pexpect_kill_proc(self, child):
        child.delayafterclose = 1
        child.delayafterterminate = 1
        try:
            child.close(force=True)
        except pexpect.ExceptionPexpect:
            # Close fails to terminate a sudo process on some OSes.
            subprocess.call(['sudo', 'kill', str(child.pid)])

    def pexpect_wait_and_close_proc(self, child):
        child.expect(pexpect.EOF)
        child.close()

    def pexpect_run(self, cmd, output_expects, time_out):
        child = pexpect.spawn(cmd, timeout=time_out)
        try:
            i = child.expect(output_expects)
            match = child.match
            self.pexpect_wait_and_close_proc(child)
        except pexpect.TIMEOUT:
            self.pexpect_kill_proc(child)
            raise PkgTimeout("Process timeout after %i seconds." % time_out)
        return (i, match)


class RedhatPackagerMixin(BasePackagerMixin):

    def _rpm_remove_nodeps(self, package_name):
        """
        Sometimes transaction errors happens, easy way is to remove
        conflicted package without dependencies and hope it will replaced
        by another package
        """
        try:
            utils.execute("rpm", "-e", "--nodeps", package_name,
                          run_as_root=True, root_helper="sudo")
        except ProcessExecutionError:
            LOG.exception(_("Error removing conflict %(package)s") %
                          package_name)

    def _install(self, packages, time_out):
        """Attempts to install packages.

        Returns OK if the packages are installed or a result code if a
        recoverable-error occurred.
        Raises an exception if a non-recoverable error or timeout occurs.

        """
        cmd = "sudo yum --color=never -y install %s" % " ".join(packages)
        output_expects = ['\[sudo\] password for .*:',
                          'No package (.*) available.',
                          ('file .* from install of .* conflicts with file'
                           ' from package (.*?)\r\n'),
                          'Error: (.*?) conflicts with .*?\r\n',
                          'Processing Conflict: .* conflicts (.*?)\r\n',
                          '.*scriptlet failed*',
                          'HTTP Error',
                          'No more mirrors to try.',
                          'GPG key retrieval failed:',
                          '.*already installed and latest version',
                          'Updated:',
                          'Installed:']
        LOG.debug("Running package install command: %s" % cmd)
        i, match = self.pexpect_run(cmd, output_expects, time_out)
        if i == 0:
            raise PkgPermissionError("Invalid permissions.")
        elif i == 1:
{'fraction_non_alphanumeric': 0.08469884853852967, 'fraction_numerical': 0.00354295837023915, 'mean_word_length': 2.32707182320442, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4003616', 'n_tokens_mistral': 2511, 'n_tokens_neox': 2412, 'n_words': 759}