Beispiel #1
0
 def test_decrement(self):
     src_v = FlexibleVersion('1.0.0.0.10')
     dst_v = FlexibleVersion(str(src_v))
     for i in range(1, 10):
         dst_v -= 1
         self.assertEqual(i, src_v.version[-1] - dst_v.version[-1])
     return
Beispiel #2
0
 def test_increment(self):  # pylint: disable=useless-return
     src_v = FlexibleVersion('1.0.0.0.0')
     dst_v = FlexibleVersion(str(src_v))
     for i in range(1, 10):
         dst_v += 1
         self.assertEqual(i, dst_v.version[-1] - src_v.version[-1])
     return
Beispiel #3
0
    def decide_version(self, target_state=None):
        self.logger.verbose("Decide which version to use")
        try:
            pkg_list = self.protocol.get_ext_handler_pkgs(self.ext_handler)
        except ProtocolError as e:
            raise ExtensionError("Failed to get ext handler pkgs", e)

        # Determine the desired and installed versions
        requested_version = FlexibleVersion(str(self.ext_handler.properties.version))
        installed_version_string = self.get_installed_version()
        installed_version = requested_version \
            if installed_version_string is None \
            else FlexibleVersion(installed_version_string)

        # Divide packages
        # - Find the installed package (its version must exactly match)
        # - Find the internal candidate (its version must exactly match)
        # - Separate the public packages
        selected_pkg = None
        installed_pkg = None
        pkg_list.versions.sort(key=lambda p: FlexibleVersion(p.version))
        for pkg in pkg_list.versions:
            pkg_version = FlexibleVersion(pkg.version)
            if pkg_version == installed_version:
                installed_pkg = pkg
            if requested_version.matches(pkg_version):
                selected_pkg = pkg

        # Finally, update the version only if not downgrading
        # Note:
        #  - A downgrade, which will be bound to the same major version,
        #    is allowed if the installed version is no longer available
        if target_state == u"uninstall" or target_state == u"disabled":
            if installed_pkg is None:
                msg = "Failed to find installed version of {0} " \
                    "to uninstall".format(self.ext_handler.name)
                self.logger.warn(msg)
            self.pkg = installed_pkg
            self.ext_handler.properties.version = str(installed_version) \
                                    if installed_version is not None else None
        else:
            self.pkg = selected_pkg
            if self.pkg is not None:
                self.ext_handler.properties.version = str(selected_pkg.version)

        # Note if the selected package is different than that installed
        if installed_pkg is None \
                or (self.pkg is not None and FlexibleVersion(self.pkg.version) != FlexibleVersion(installed_pkg.version)):
            self.is_upgrade = True

        if self.pkg is not None:
            self.logger.verbose("Use version: {0}", self.pkg.version)
        self.set_logger()
        return self.pkg
Beispiel #4
0
def get_daemon_version():
    """
    Retrieves the value of the _AZURE_GUEST_AGENT_DAEMON_VERSION_ environment variable.
    The value indicates the version of the daemon that started the current agent process or, if the current
    process is the daemon, the version of the current process.
    If the variable is not set (because the agent is < 2.2.53, or the process was not started by the daemon and
    the process is not the daemon itself) the function returns "0.0.0.0"
    """
    if __DAEMON_VERSION_ENV_VARIABLE in os.environ:
        return FlexibleVersion(os.environ[__DAEMON_VERSION_ENV_VARIABLE])
    return FlexibleVersion("0.0.0.0")
    def test_creation_from_flexible_version(self):
        tests = [
            '1',
            '1.2',
            '1.2.3',
            '1.2.3.4',
            '1.2.3.4.5',

            '1alpha',
            '1.alpha',
            '1-alpha',
            '1alpha0',
            '1.alpha0',
            '1-alpha0',
            '1.2alpha',
            '1.2.alpha',
            '1.2-alpha',
            '1.2alpha0',
            '1.2.alpha0',
            '1.2-alpha0',

            '1beta',
            '1.beta',
            '1-beta',
            '1beta0',
            '1.beta0',
            '1-beta0',
            '1.2beta',
            '1.2.beta',
            '1.2-beta',
            '1.2beta0',
            '1.2.beta0',
            '1.2-beta0',

            '1rc',
            '1.rc',
            '1-rc',
            '1rc0',
            '1.rc0',
            '1-rc0',
            '1.2rc',
            '1.2.rc',
            '1.2-rc',
            '1.2rc0',
            '1.2.rc0',
            '1.2-rc0',

            '1.2.3.4alpha5',
        ]
        for test in tests:
            v = FlexibleVersion(test)
            self.assertEqual(test, str(FlexibleVersion(v)))
        return
Beispiel #6
0
 def test_ensure_compatible_prerel_order(self):
     v1 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b'))
     v2 = FlexibleVersion('1.2.3', prerel_tags=('b', 'a'))
     try:
         v1 == v2
         self.assertTrue(False, "Incompatible prerel_tags failed to raise an exception")
     except ValueError:
         pass
     except Exception as e:
         t = e.__class__.__name__
         self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
             .format(t))
     return
Beispiel #7
0
 def test_ensure_compatible_separators(self):
     v1 = FlexibleVersion('1.2.3')
     v2 = FlexibleVersion('1-2-3', sep='-')
     try:
         v1 == v2
         self.assertTrue(False, "Incompatible separators failed to raise an exception")
     except ValueError:
         pass
     except Exception as e:
         t = e.__class__.__name__
         self.assertTrue(False, "Incompatible separators raised an unexpected exception: {0}" \
             .format(t))
     return
Beispiel #8
0
 def test_creation_from_flexible_version(self):  # pylint: disable=useless-return
     tests = [
         '1',
         '1.2',
         '1.2.3',
         '1.2.3.4',
         '1.2.3.4.5',
         '1alpha',
         '1.alpha',
         '1-alpha',
         '1alpha0',
         '1.alpha0',
         '1-alpha0',
         '1.2alpha',
         '1.2.alpha',
         '1.2-alpha',
         '1.2alpha0',
         '1.2.alpha0',
         '1.2-alpha0',
         '1beta',
         '1.beta',
         '1-beta',
         '1beta0',
         '1.beta0',
         '1-beta0',
         '1.2beta',
         '1.2.beta',
         '1.2-beta',
         '1.2beta0',
         '1.2.beta0',
         '1.2-beta0',
         '1rc',
         '1.rc',
         '1-rc',
         '1rc0',
         '1.rc0',
         '1-rc0',
         '1.2rc',
         '1.2.rc',
         '1.2-rc',
         '1.2rc0',
         '1.2.rc0',
         '1.2-rc0',
         '1.2.3.4alpha5',
     ]
     for test in tests:
         v = FlexibleVersion(test)  # pylint: disable=invalid-name
         self.assertEqual(test, str(FlexibleVersion(v)))
     return
Beispiel #9
0
 def test_ensure_compatible_prerel_order(self):  # pylint: disable=useless-return
     v1 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b'))  # pylint: disable=invalid-name
     v2 = FlexibleVersion('1.2.3', prerel_tags=('b', 'a'))  # pylint: disable=invalid-name
     try:
         v1 == v2  # pylint: disable=pointless-statement
         self.assertTrue(
             False, "Incompatible prerel_tags failed to raise an exception")  # pylint: disable=redundant-unittest-assert
     except ValueError:
         pass
     except Exception as e:  # pylint: disable=invalid-name
         t = e.__class__.__name__  # pylint: disable=invalid-name
         # pylint: disable=redundant-unittest-assert
         self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
             .format(t))
         # pylint: enable=redundant-unittest-assert
     return
Beispiel #10
0
    def _purge_agents(self):
        """
        Remove from disk all directories and .zip files of unknown agents
        (without removing the current, running agent).
        """
        path = os.path.join(conf.get_lib_dir(), "{0}-*".format(AGENT_NAME))

        known_versions = [agent.version for agent in self.agents]
        if not is_current_agent_installed(
        ) and CURRENT_VERSION not in known_versions:
            logger.warn(
                u"Running Agent {0} was not found in the agent manifest - adding to list",
                CURRENT_VERSION)
            known_versions.append(CURRENT_VERSION)

        for agent_path in glob.iglob(path):
            try:
                name = fileutil.trim_ext(agent_path, "zip")
                m = AGENT_DIR_PATTERN.match(name)
                if m is not None and FlexibleVersion(
                        m.group(1)) not in known_versions:
                    if os.path.isfile(agent_path):
                        logger.info(u"Purging outdated Agent file {0}",
                                    agent_path)
                        os.remove(agent_path)
                    else:
                        logger.info(u"Purging outdated Agent directory {0}",
                                    agent_path)
                        shutil.rmtree(agent_path)
            except Exception as e:
                logger.warn(u"Purging {0} raised exception: {1}", agent_path,
                            ustr(e))
        return
Beispiel #11
0
    def run_exthandlers(self, debug=False):
        """
        Run the update and extension handler
        """
        logger.set_prefix("ExtHandler")
        threading.current_thread().setName("ExtHandler")

        #
        # Agents < 2.2.53 used to echo the log to the console. Since the extension handler could have been started by
        # one of those daemons, output a message indicating that output to the console will stop, otherwise users
        # may think that the agent died if they noticed that output to the console stops abruptly.
        #
        # Feel free to remove this code if telemetry shows there are no more agents <= 2.2.53 in the field.
        #
        if conf.get_logs_console(
        ) and get_daemon_version() < FlexibleVersion("2.2.53"):
            self.__add_console_appender(logger.LogLevel.INFO)
            try:
                logger.info(
                    u"The agent will now check for updates and then will process extensions. Output to /dev/console will be suspended during those operations."
                )
            finally:
                logger.disable_console_output()

        from azurelinuxagent.ga.update import get_update_handler
        update_handler = get_update_handler()
        update_handler.run(debug)
Beispiel #12
0
    def __init__(self, path=None, pkg=None, host=None):
        self.pkg = pkg
        self.host = host
        version = None
        if path is not None:
            m = AGENT_DIR_PATTERN.match(path)
            if m == None:
                raise UpdateError(u"Illegal agent directory: {0}".format(path))
            version = m.group(1)
        elif self.pkg is not None:
            version = pkg.version

        if version == None:
            raise UpdateError(u"Illegal agent version: {0}".format(version))
        self.version = FlexibleVersion(version)

        location = u"disk" if path is not None else u"package"
        logger.verbose(u"Instantiating Agent {0} from {1}", self.name,
                       location)

        self.error = None
        self.supported = None

        self._load_error()
        self._load_supported()

        self._ensure_downloaded()
        return
Beispiel #13
0
 def test_ensure_compatible_separators(self):
     v1 = FlexibleVersion('1.2.3')
     v2 = FlexibleVersion('1-2-3', sep='-')
     try:
         v1 == v2  # pylint: disable=pointless-statement
         self.assertTrue(
             False, "Incompatible separators failed to raise an exception")  # pylint: disable=redundant-unittest-assert
     except ValueError:
         pass
     except Exception as e:
         t = e.__class__.__name__
         # pylint: disable=redundant-unittest-assert
         self.assertTrue(False, "Incompatible separators raised an unexpected exception: {0}" \
             .format(t))
         # pylint: enable=redundant-unittest-assert
     return
Beispiel #14
0
def set_daemon_version(version):
    """
    Sets the value of the _AZURE_GUEST_AGENT_DAEMON_VERSION_ environment variable.

    The given 'version' can be a FlexibleVersion or a string that can be parsed into a FlexibleVersion
    """
    flexible_version = version if isinstance(version, FlexibleVersion) else FlexibleVersion(version)
    os.environ[__DAEMON_VERSION_ENV_VARIABLE] = ustr(flexible_version)
Beispiel #15
0
 def cgroups_supported():
     distro_info = get_distro()
     distro_name = distro_info[0]
     try:
         distro_version = FlexibleVersion(distro_info[1])
     except ValueError:
         return False
     return distro_name.lower() == 'ubuntu' and distro_version.major >= 16
    def decide_version(self, target_state=None):
        self.logger.verbose("Decide which version to use")
        try:
            pkg_list = self.protocol.get_ext_handler_pkgs(self.ext_handler)
        except ProtocolError as e:
            raise ExtensionError("Failed to get ext handler pkgs", e)

        # Determine the desired and installed versions
        requested_version = FlexibleVersion(
            str(self.ext_handler.properties.version))
        installed_version_string = self.get_installed_version()
        installed_version = requested_version \
            if installed_version_string is None \
            else FlexibleVersion(installed_version_string)

        # Divide packages
        # - Find the installed package (its version must exactly match)
        # - Find the internal candidate (its version must exactly match)
        # - Separate the public packages
        selected_pkg = None
        installed_pkg = None
        pkg_list.versions.sort(key=lambda p: FlexibleVersion(p.version))
        for pkg in pkg_list.versions:
            pkg_version = FlexibleVersion(pkg.version)
            if pkg_version == installed_version:
                installed_pkg = pkg
            if requested_version.matches(pkg_version):
                selected_pkg = pkg

        # Finally, update the version only if not downgrading
        # Note:
        #  - A downgrade, which will be bound to the same major version,
        #    is allowed if the installed version is no longer available
        if target_state == u"uninstall" or target_state == u"disabled":
            if installed_pkg is None:
                msg = "Failed to find installed version of {0} " \
                    "to uninstall".format(self.ext_handler.name)
                self.logger.warn(msg)
            self.pkg = installed_pkg
            self.ext_handler.properties.version = str(installed_version) \
                                    if installed_version is not None else None
        else:
            self.pkg = selected_pkg
            if self.pkg is not None:
                self.ext_handler.properties.version = str(selected_pkg.version)

        # Note if the selected package is different than that installed
        if installed_pkg is None \
                or (self.pkg is not None and FlexibleVersion(self.pkg.version) != FlexibleVersion(installed_pkg.version)):
            self.is_upgrade = True

        if self.pkg is not None:
            self.logger.verbose("Use version: {0}", self.pkg.version)
        self.set_logger()
        return self.pkg
Beispiel #17
0
    def cleanup_outdated_handlers(self):
        handlers = []
        pkgs = []

        # Build a collection of uninstalled handlers and orphaned packages
        # Note:
        # -- An orphaned package is one without a corresponding handler
        #    directory
        for item in os.listdir(conf.get_lib_dir()):
            path = os.path.join(conf.get_lib_dir(), item)

            if version.is_agent_package(path) or version.is_agent_path(path):
                continue

            if os.path.isdir(path):
                if re.match(HANDLER_NAME_PATTERN, item) is None:
                    continue
                try:
                    eh = ExtHandler()

                    separator = item.rfind('-')

                    eh.name = item[0:separator]
                    eh.properties.version = str(FlexibleVersion(item[separator+1:]))

                    handler = ExtHandlerInstance(eh, self.protocol)
                except Exception:
                    continue
                if handler.get_handler_state() != ExtHandlerState.NotInstalled:
                    continue
                handlers.append(handler)

            elif os.path.isfile(path) and \
                    not os.path.isdir(path[0:-len(HANDLER_PKG_EXT)]):
                if not re.match(HANDLER_PKG_PATTERN, item):
                    continue
                pkgs.append(path)

        # Then, remove the orphaned packages
        for pkg in pkgs:
            try:
                os.remove(pkg)
                logger.verbose("Removed orphaned extension package {0}".format(pkg))
            except OSError as e:
                logger.warn("Failed to remove orphaned package {0}: {1}".format(pkg, e.strerror))

        # Finally, remove the directories and packages of the
        # uninstalled handlers
        for handler in handlers:
            handler.rm_ext_handler_dir()
            pkg = os.path.join(conf.get_lib_dir(), handler.get_full_name() + HANDLER_PKG_EXT)
            if os.path.isfile(pkg):
                try:
                    os.remove(pkg)
                    logger.verbose("Removed extension package {0}".format(pkg))
                except OSError as e:
                    logger.warn("Failed to remove extension package {0}: {1}".format(pkg, e.strerror))
Beispiel #18
0
    def _mock_iptables(version=osutil._IPTABLES_LOCKING_VERSION, destination='168.63.129.16'):
        """
        Mock for the iptable commands used to set up the firewall.

        Returns a patch of subprocess.Popen augmented with these properties:

            * wait - True if the iptable commands use the -w option
            * destination - The target IP address
            * uid - The uid used for the -owner option
            * command_calls - A list of the iptable commands executed by the mock (the --version and -L commands are omitted)
            * set_command - By default all the mocked commands succeed and produce no output; this method can be used to override
                  the return value and output of these commands (or to add other commands)
        """
        mocked_commands = {}

        def set_command(command, output='', exit_code=0):
            command_string = TestOSUtil._command_to_string(command)
            mocked_commands[command_string] = (output.replace("'", "'\"'\"'"), exit_code)
            return command_string

        wait = FlexibleVersion(version) >= osutil._IPTABLES_LOCKING_VERSION
        uid = 42

        version_command = set_command(osutil._get_iptables_version_command(), output=str(version))
        list_command = set_command(osutil._get_firewall_list_command(wait), output="Mock Output")
        set_command(osutil._get_firewall_packets_command(wait))
        set_command(osutil._get_firewall_drop_command(wait, "-C", destination))
        set_command(osutil._get_firewall_drop_command(wait, "-A", destination))
        set_command(osutil._get_firewall_accept_command(wait, "-A", destination, uid))
        # the agent assumes the rules have been deleted when these commands return 1
        set_command(osutil._get_firewall_delete_conntrack_accept_command(wait, destination), exit_code=1)
        set_command(osutil._get_firewall_delete_owner_accept_command(wait, destination, uid), exit_code=1)
        set_command(osutil._get_firewall_delete_conntrack_drop_command(wait, destination), exit_code=1)

        command_calls = []

        def mock_popen(command, *args, **kwargs):
            command_string = TestOSUtil._command_to_string(command)
            if command_string in mocked_commands:
                if command_string != version_command and command_string != list_command:
                    command_calls.append(command_string)
                output, exit_code = mocked_commands[command_string]
                command = "echo '{0}' && exit {1}".format(output, exit_code)
                kwargs["shell"] = True
            return mock_popen.original(command, *args, **kwargs)
        mock_popen.original = subprocess.Popen

        with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen", side_effect=mock_popen) as popen_patcher:
            with patch('os.getuid', return_value=uid):
                popen_patcher.wait = wait
                popen_patcher.destination = destination
                popen_patcher.uid = uid
                popen_patcher.set_command = set_command
                popen_patcher.command_calls = command_calls

                yield popen_patcher
Beispiel #19
0
 def test_decrement_disallows_below_zero(self):
     try:
         FlexibleVersion('1.0') - 1
         self.assertTrue(False, "Decrement failed to raise an exception")
     except ArithmeticError:
         pass
     except Exception as e:
         t = e.__class__.__name__
         self.assertTrue(False, "Decrement raised an unexpected exception: {0}".format(t))
     return
Beispiel #20
0
    def test_get_daemon_version_should_return_the_version_that_was_previously_set(
            self):
        set_daemon_version("1.2.3.4")

        try:
            self.assertEqual(
                FlexibleVersion("1.2.3.4"), get_daemon_version(),
                "The daemon version should be 1.2.3.4. Environment={0}".format(
                    os.environ))
        finally:
            os.environ.pop(DAEMON_VERSION_ENV_VARIABLE)
Beispiel #21
0
 def test_decrement_disallows_below_zero(self):  # pylint: disable=useless-return
     try:
         FlexibleVersion('1.0') - 1  # pylint: disable=expression-not-assigned
         self.assertTrue(False, "Decrement failed to raise an exception")  # pylint: disable=redundant-unittest-assert
     except ArithmeticError:
         pass
     except Exception as e:  # pylint: disable=invalid-name
         t = e.__class__.__name__  # pylint: disable=invalid-name
         self.assertTrue(
             False,
             "Decrement raised an unexpected exception: {0}".format(t))  # pylint: disable=redundant-unittest-assert
     return
Beispiel #22
0
        def _is_match_walk(doci, keys):
            key = keys.pop(0).upper()
            if key is None:
                return False

            if key not in doci:
                return False

            if 'List' in doci[key] and keys[0] in doci[key]['List']:
                return True

            if 'Match' in doci[key] and re.match(doci[key]['Match'], keys[0]):
                return True

            if 'Minimum' in doci[key]:
                try:
                    return FlexibleVersion(keys[0]) >= FlexibleVersion(doci[key]['Minimum'])
                except ValueError:
                    pass

            return _is_match_walk(doci[key], keys)
Beispiel #23
0
def set_current_agent():
    path = os.getcwd()
    lib_dir = conf.get_lib_dir()
    if lib_dir[-1] != os.path.sep:
        lib_dir += os.path.sep
    if path[:len(lib_dir)] != lib_dir:
        agent = AGENT_LONG_VERSION
        version = AGENT_VERSION
    else:
        agent = path[len(lib_dir):].split(os.path.sep)[0]
        version = AGENT_NAME_PATTERN.match(agent).group(1)
    return agent, FlexibleVersion(version)
Beispiel #24
0
 def test_patch(self):
     tests = {
         '1' : 0,
         '1.2' : 0,
         '1.2.3' : 3,
         '1.2.3.4' : 3
     }
     for test in iter(tests):
         expectation = tests[test]
         self.assertEqual(
             expectation,
             FlexibleVersion(test).patch)
     return
Beispiel #25
0
 def test_minor(self):
     tests = {
         '1' : 0,
         '1.2' : 2,
         '1.2.3' : 2,
         '1.2.3.4' : 2
     }
     for test in iter(tests):
         expectation = tests[test]
         self.assertEqual(
             expectation,
             FlexibleVersion(test).minor)
     return
Beispiel #26
0
    def __init__(self, path=None, pkg=None, host=None):
        self.pkg = pkg
        self.host = host
        version = None
        if path is not None:
            m = AGENT_DIR_PATTERN.match(path)
            if m == None:
                raise UpdateError(u"Illegal agent directory: {0}".format(path))
            version = m.group(1)
        elif self.pkg is not None:
            version = pkg.version

        if version == None:
            raise UpdateError(u"Illegal agent version: {0}".format(version))
        self.version = FlexibleVersion(version)

        location = u"disk" if path is not None else u"package"
        logger.verbose(u"Loading Agent {0} from {1}", self.name, location)

        self.error = GuestAgentError(self.get_agent_error_file())
        self.error.load()

        try:
            self._ensure_downloaded()
            self._ensure_loaded()
        except Exception as e:
            if isinstance(e, ResourceGoneError):
                raise

            # The agent was improperly blacklisting versions due to a timeout
            # encountered while downloading a later version. Errors of type
            # socket.error are IOError, so this should provide sufficient
            # protection against a large class of I/O operation failures.
            if isinstance(e, IOError):
                raise

            # Note the failure, blacklist the agent if the package downloaded
            # - An exception with a downloaded package indicates the package
            #   is corrupt (e.g., missing the HandlerManifest.json file)
            self.mark_failure(
                is_fatal=os.path.isfile(self.get_agent_pkg_path()))

            msg = u"Agent {0} install failed with exception: {1}".format(
                self.name, ustr(e))
            detailed_msg = '{0} {1}'.format(
                msg, traceback.extract_tb(get_traceback(e)))
            add_event(AGENT_NAME,
                      version=self.version,
                      op=WALAEventOperation.Install,
                      is_success=False,
                      message=detailed_msg)
Beispiel #27
0
    def get_installed_version(self):
        lastest_version = None

        for path in glob.iglob(os.path.join(conf.get_lib_dir(), self.ext_handler.name + "-*")):
            if not os.path.isdir(path):
                continue

            separator = path.rfind('-')
            version = FlexibleVersion(path[separator+1:])

            if lastest_version is None or lastest_version < version:
                lastest_version = version

        return str(lastest_version) if lastest_version is not None else None
Beispiel #28
0
 def test_str(self):  # pylint: disable=useless-return
     tests = [
         '1',
         '1.2',
         '1.2.3',
         '1.2.3.4',
         '1.2.3.4.5',
         '1alpha',
         '1.alpha',
         '1-alpha',
         '1alpha0',
         '1.alpha0',
         '1-alpha0',
         '1.2alpha',
         '1.2.alpha',
         '1.2-alpha',
         '1.2alpha0',
         '1.2.alpha0',
         '1.2-alpha0',
         '1beta',
         '1.beta',
         '1-beta',
         '1beta0',
         '1.beta0',
         '1-beta0',
         '1.2beta',
         '1.2.beta',
         '1.2-beta',
         '1.2beta0',
         '1.2.beta0',
         '1.2-beta0',
         '1rc',
         '1.rc',
         '1-rc',
         '1rc0',
         '1.rc0',
         '1-rc0',
         '1.2rc',
         '1.2.rc',
         '1.2-rc',
         '1.2rc0',
         '1.2.rc0',
         '1.2-rc0',
         '1.2.3.4alpha5',
     ]
     for test in tests:
         self.assertEqual(test, str(FlexibleVersion(test)))
     return
Beispiel #29
0
    def get_latest_agent(self):
        """
        If autoupdate is enabled, return the most current, downloaded,
        non-blacklisted agent which is not the current version (if any).
        Otherwise, return None (implying to use the installed agent).
        """

        if not conf.get_autoupdate_enabled():
            return None
        
        self._load_agents()
        available_agents = [agent for agent in self.agents
                            if agent.is_available
                            and agent.version > FlexibleVersion(AGENT_VERSION)]

        return available_agents[0] if len(available_agents) >= 1 else None
Beispiel #30
0
    def get_firewall_will_wait(self):
        # Determine if iptables will serialize access
        rc, output = shellutil.run_get_output(IPTABLES_VERSION)
        if rc != 0:
            msg = "Unable to determine version of iptables"
            logger.warn(msg)
            raise Exception(msg)

        m = IPTABLES_VERSION_PATTERN.match(output)
        if m is None:
            msg = "iptables did not return version information"
            logger.warn(msg)
            raise Exception(msg)

        wait = "-w" \
                if FlexibleVersion(m.group(1)) >= IPTABLES_LOCKING_VERSION \
                else ""
        return wait
Beispiel #31
0
    def __init__(self, path=None, pkg=None, host=None):
        self.pkg = pkg
        self.host = host
        version = None
        if path is not None:
            m = AGENT_DIR_PATTERN.match(path)
            if m == None:
                raise UpdateError(u"Illegal agent directory: {0}".format(path))
            version = m.group(1)
        elif self.pkg is not None:
            version = pkg.version

        if version == None:
            raise UpdateError(u"Illegal agent version: {0}".format(version))
        self.version = FlexibleVersion(version)

        location = u"disk" if path is not None else u"package"
        logger.verbose(u"Loading Agent {0} from {1}", self.name, location)

        self.error = GuestAgentError(self.get_agent_error_file())
        self.error.load()
        self.safe_deploy = safedeploy.SafeDeploy()

        try:
            self._ensure_downloaded()
            self._ensure_loaded()
        except Exception as e:
            if isinstance(e, ResourceGoneError):
                raise

            # Note the failure, blacklist the agent if the package downloaded
            # - An exception with a downloaded package indicates the package
            #   is corrupt (e.g., missing the HandlerManifest.json file)
            self.mark_failure(
                is_fatal=os.path.isfile(self.get_agent_pkg_path()))

            msg = u"Agent {0} install failed with exception: {1}".format(
                self.name, ustr(e))
            logger.warn(msg)
            add_event(AGENT_NAME,
                      version=self.version,
                      op=WALAEventOperation.Install,
                      is_success=False,
                      message=msg)
class TestFlexibleVersion(unittest.TestCase):

    def setUp(self):
        self.v = FlexibleVersion()

    def test_compile_separator(self):
        tests = [
            '.',
            '',
            '-'
        ]
        for t in tests:
            t_escaped = re.escape(t)
            t_re = re.compile(t_escaped)
            self.assertEqual((t_escaped, t_re), self.v._compile_separator(t))
        self.assertEqual(('', re.compile('')),  self.v._compile_separator(None))
        return

    def test_compile_pattern(self):
        self.v._compile_pattern()
        tests = {
            '1': True,
            '1.2': True,
            '1.2.3': True,
            '1.2.3.4': True,
            '1.2.3.4.5': True,

            '1alpha': True,
            '1.alpha': True,
            '1-alpha': True,
            '1alpha0': True,
            '1.alpha0': True,
            '1-alpha0': True,
            '1.2alpha': True,
            '1.2.alpha': True,
            '1.2-alpha': True,
            '1.2alpha0': True,
            '1.2.alpha0': True,
            '1.2-alpha0': True,

            '1beta': True,
            '1.beta': True,
            '1-beta': True,
            '1beta0': True,
            '1.beta0': True,
            '1-beta0': True,
            '1.2beta': True,
            '1.2.beta': True,
            '1.2-beta': True,
            '1.2beta0': True,
            '1.2.beta0': True,
            '1.2-beta0': True,

            '1rc': True,
            '1.rc': True,
            '1-rc': True,
            '1rc0': True,
            '1.rc0': True,
            '1-rc0': True,
            '1.2rc': True,
            '1.2.rc': True,
            '1.2-rc': True,
            '1.2rc0': True,
            '1.2.rc0': True,
            '1.2-rc0': True,

            '1.2.3.4alpha5': True,

            ' 1': False,
            'beta': False,
            '1delta0': False,
            '': False
        }
        for test in iter(tests):
            expectation = tests[test]
            self.assertEqual(
                expectation,
                self.v.version_re.match(test) is not None,
                "test: {0} expected: {1} ".format(test, expectation))
        return

    def test_compile_pattern_sep(self):
        self.v.sep = '-'
        self.v._compile_pattern()
        tests = {
            '1': True,
            '1-2': True,
            '1-2-3': True,
            '1-2-3-4': True,
            '1-2-3-4-5': True,

            '1alpha': True,
            '1-alpha': True,
            '1-alpha': True,
            '1alpha0': True,
            '1-alpha0': True,
            '1-alpha0': True,
            '1-2alpha': True,
            '1-2.alpha': True,
            '1-2-alpha': True,
            '1-2alpha0': True,
            '1-2.alpha0': True,
            '1-2-alpha0': True,

            '1beta': True,
            '1-beta': True,
            '1-beta': True,
            '1beta0': True,
            '1-beta0': True,
            '1-beta0': True,
            '1-2beta': True,
            '1-2.beta': True,
            '1-2-beta': True,
            '1-2beta0': True,
            '1-2.beta0': True,
            '1-2-beta0': True,

            '1rc': True,
            '1-rc': True,
            '1-rc': True,
            '1rc0': True,
            '1-rc0': True,
            '1-rc0': True,
            '1-2rc': True,
            '1-2.rc': True,
            '1-2-rc': True,
            '1-2rc0': True,
            '1-2.rc0': True,
            '1-2-rc0': True,

            '1-2-3-4alpha5': True,

            ' 1': False,
            'beta': False,
            '1delta0': False,
            '': False
        }
        for test in iter(tests):
            expectation = tests[test]
            self.assertEqual(
                expectation,
                self.v.version_re.match(test) is not None,
                "test: {0} expected: {1} ".format(test, expectation))
        return

    def test_compile_pattern_prerel(self):
        self.v.prerel_tags = ('a', 'b', 'c')
        self.v._compile_pattern()
        tests = {
            '1': True,
            '1.2': True,
            '1.2.3': True,
            '1.2.3.4': True,
            '1.2.3.4.5': True,

            '1a': True,
            '1.a': True,
            '1-a': True,
            '1a0': True,
            '1.a0': True,
            '1-a0': True,
            '1.2a': True,
            '1.2.a': True,
            '1.2-a': True,
            '1.2a0': True,
            '1.2.a0': True,
            '1.2-a0': True,

            '1b': True,
            '1.b': True,
            '1-b': True,
            '1b0': True,
            '1.b0': True,
            '1-b0': True,
            '1.2b': True,
            '1.2.b': True,
            '1.2-b': True,
            '1.2b0': True,
            '1.2.b0': True,
            '1.2-b0': True,

            '1c': True,
            '1.c': True,
            '1-c': True,
            '1c0': True,
            '1.c0': True,
            '1-c0': True,
            '1.2c': True,
            '1.2.c': True,
            '1.2-c': True,
            '1.2c0': True,
            '1.2.c0': True,
            '1.2-c0': True,

            '1.2.3.4a5': True,

            ' 1': False,
            '1.2.3.4alpha5': False,
            'beta': False,
            '1delta0': False,
            '': False
        }
        for test in iter(tests):
            expectation = tests[test]
            self.assertEqual(
                expectation,
                self.v.version_re.match(test) is not None,
                "test: {0} expected: {1} ".format(test, expectation))
        return

    def test_ensure_compatible_separators(self):
        v1 = FlexibleVersion('1.2.3')
        v2 = FlexibleVersion('1-2-3', sep='-')
        try:
            v1 == v2
            self.assertTrue(False, "Incompatible separators failed to raise an exception")
        except ValueError:
            pass
        except Exception as e:
            t = e.__class__.__name__
            self.assertTrue(False, "Incompatible separators raised an unexpected exception: {0}" \
                .format(t))
        return

    def test_ensure_compatible_prerel(self):
        v1 = FlexibleVersion('1.2.3', prerel_tags=('alpha', 'beta', 'rc'))
        v2 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b', 'c'))
        try:
            v1 == v2
            self.assertTrue(False, "Incompatible prerel_tags failed to raise an exception")
        except ValueError:
            pass
        except Exception as e:
            t = e.__class__.__name__
            self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
                .format(t))
        return

    def test_ensure_compatible_prerel_length(self):
        v1 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b', 'c'))
        v2 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b'))
        try:
            v1 == v2
            self.assertTrue(False, "Incompatible prerel_tags failed to raise an exception")
        except ValueError:
            pass
        except Exception as e:
            t = e.__class__.__name__
            self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
                .format(t))
        return

    def test_ensure_compatible_prerel_order(self):
        v1 = FlexibleVersion('1.2.3', prerel_tags=('a', 'b'))
        v2 = FlexibleVersion('1.2.3', prerel_tags=('b', 'a'))
        try:
            v1 == v2
            self.assertTrue(False, "Incompatible prerel_tags failed to raise an exception")
        except ValueError:
            pass
        except Exception as e:
            t = e.__class__.__name__
            self.assertTrue(False, "Incompatible prerel_tags raised an unexpected exception: {0}" \
                .format(t))
        return

    def test_major(self):
        tests = {
            '1' : 1,
            '1.2' : 1,
            '1.2.3' : 1,
            '1.2.3.4' : 1
        }
        for test in iter(tests):
            expectation = tests[test]
            self.assertEqual(
                expectation,
                FlexibleVersion(test).major)
        return

    def test_minor(self):
        tests = {
            '1' : 0,
            '1.2' : 2,
            '1.2.3' : 2,
            '1.2.3.4' : 2
        }
        for test in iter(tests):
            expectation = tests[test]
            self.assertEqual(
                expectation,
                FlexibleVersion(test).minor)
        return

    def test_patch(self):
        tests = {
            '1' : 0,
            '1.2' : 0,
            '1.2.3' : 3,
            '1.2.3.4' : 3
        }
        for test in iter(tests):
            expectation = tests[test]
            self.assertEqual(
                expectation,
                FlexibleVersion(test).patch)
        return

    def test_parse(self):
        tests = {
            "1.2.3.4": ((1, 2, 3, 4), None),
            "1.2.3.4alpha5": ((1, 2, 3, 4), ('alpha', 5)),
            "1.2.3.4-alpha5": ((1, 2, 3, 4), ('alpha', 5)),
            "1.2.3.4.alpha5": ((1, 2, 3, 4), ('alpha', 5))
        }
        for test in iter(tests):
            expectation = tests[test]
            self.v._parse(test)
            self.assertEqual(expectation, (self.v.version, self.v.prerelease))
        return

    def test_decrement(self):
        src_v = FlexibleVersion('1.0.0.0.10')
        dst_v = FlexibleVersion(str(src_v))
        for i in range(1,10):
            dst_v -= 1
            self.assertEqual(i, src_v.version[-1] - dst_v.version[-1])
        return

    def test_decrement_disallows_below_zero(self):
        try:
            FlexibleVersion('1.0') - 1
            self.assertTrue(False, "Decrement failed to raise an exception")
        except ArithmeticError:
            pass
        except Exception as e:
            t = e.__class__.__name__
            self.assertTrue(False, "Decrement raised an unexpected exception: {0}".format(t))
        return

    def test_increment(self):
        src_v = FlexibleVersion('1.0.0.0.0')
        dst_v = FlexibleVersion(str(src_v))
        for i in range(1,10):
            dst_v += 1
            self.assertEqual(i, dst_v.version[-1] - src_v.version[-1])
        return

    def test_str(self):
        tests = [
            '1',
            '1.2',
            '1.2.3',
            '1.2.3.4',
            '1.2.3.4.5',

            '1alpha',
            '1.alpha',
            '1-alpha',
            '1alpha0',
            '1.alpha0',
            '1-alpha0',
            '1.2alpha',
            '1.2.alpha',
            '1.2-alpha',
            '1.2alpha0',
            '1.2.alpha0',
            '1.2-alpha0',

            '1beta',
            '1.beta',
            '1-beta',
            '1beta0',
            '1.beta0',
            '1-beta0',
            '1.2beta',
            '1.2.beta',
            '1.2-beta',
            '1.2beta0',
            '1.2.beta0',
            '1.2-beta0',

            '1rc',
            '1.rc',
            '1-rc',
            '1rc0',
            '1.rc0',
            '1-rc0',
            '1.2rc',
            '1.2.rc',
            '1.2-rc',
            '1.2rc0',
            '1.2.rc0',
            '1.2-rc0',

            '1.2.3.4alpha5',
        ]
        for test in tests:
            self.assertEqual(test, str(FlexibleVersion(test)))
        return

    def test_repr(self):
        v = FlexibleVersion('1,2,3rc4', ',', ['lol', 'rc'])
        expected = "FlexibleVersion ('1,2,3rc4', ',', ('lol', 'rc'))"
        self.assertEqual(expected, repr(v))

    def test_order(self):
        test0 = ["1.7.0", "1.7.0rc0", "1.11.0"]
        expected0 = ['1.7.0rc0', '1.7.0', '1.11.0']
        self.assertEqual(expected0, list(map(str, sorted([FlexibleVersion(v) for v in test0]))))

        test1 = [
            '2.0.2rc2',
            '2.2.0beta3',
            '2.0.10',
            '2.1.0alpha42',
            '2.0.2beta4',
            '2.1.1',
            '2.0.1',
            '2.0.2rc3',
            '2.2.0',
            '2.0.0',
            '3.0.1',
            '2.1.0rc1'
        ]
        expected1 = [
            '2.0.0',
            '2.0.1',
            '2.0.2beta4',
            '2.0.2rc2',
            '2.0.2rc3',
            '2.0.10',
            '2.1.0alpha42',
            '2.1.0rc1',
            '2.1.1',
            '2.2.0beta3',
            '2.2.0',
            '3.0.1'
        ]
        self.assertEqual(expected1, list(map(str, sorted([FlexibleVersion(v) for v in test1]))))

        self.assertEqual(FlexibleVersion("1.0.0.0.0.0.0.0"), FlexibleVersion("1"))

        self.assertFalse(FlexibleVersion("1.0") > FlexibleVersion("1.0"))
        self.assertFalse(FlexibleVersion("1.0") < FlexibleVersion("1.0"))
        
        self.assertTrue(FlexibleVersion("1.0") < FlexibleVersion("1.1"))
        self.assertTrue(FlexibleVersion("1.9") < FlexibleVersion("1.10"))
        self.assertTrue(FlexibleVersion("1.9.9") < FlexibleVersion("1.10.0"))
        self.assertTrue(FlexibleVersion("1.0.0.0") < FlexibleVersion("1.2.0.0"))

        self.assertTrue(FlexibleVersion("1.1") > FlexibleVersion("1.0"))
        self.assertTrue(FlexibleVersion("1.10") > FlexibleVersion("1.9"))
        self.assertTrue(FlexibleVersion("1.10.0") > FlexibleVersion("1.9.9"))
        self.assertTrue(FlexibleVersion("1.2.0.0") > FlexibleVersion("1.0.0.0"))

        self.assertTrue(FlexibleVersion("1.0") <= FlexibleVersion("1.1"))
        self.assertTrue(FlexibleVersion("1.1") > FlexibleVersion("1.0"))
        self.assertTrue(FlexibleVersion("1.1") >= FlexibleVersion("1.0"))

        self.assertTrue(FlexibleVersion("1.0") == FlexibleVersion("1.0"))
        self.assertTrue(FlexibleVersion("1.0") >= FlexibleVersion("1.0"))
        self.assertTrue(FlexibleVersion("1.0") <= FlexibleVersion("1.0"))

        self.assertFalse(FlexibleVersion("1.0") != FlexibleVersion("1.0"))
        self.assertTrue(FlexibleVersion("1.1") != FlexibleVersion("1.0"))
        return
 def setUp(self):
     self.v = FlexibleVersion()