Repository: Azure/WALinuxAgent
Pull request #1690 (2019-10-31 22:35:26)

Merge release 2.2.44 to develop


<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/azure/walinuxagent/1690)
<!-- Reviewable:end -->



Patch:
diff --git a/README.md b/README.md
index 7533c59c..99b7b628 100644
--- a/README.md
+++ b/README.md
@@ -183,7 +183,8 @@ A sample configuration file is shown below:
 
 ```yml
 Extensions.Enabled=y
-Provisioning.Agent=auto
+Provisioning.Enabled=y
+Provisioning.UseCloudInit=n
 Provisioning.DeleteRootPassword=n
 Provisioning.RegenerateSshHostKeyPair=y
 Provisioning.SshHostKeyPairType=rsa
@@ -236,18 +237,9 @@ without the agent. In order to do that, the `provisionVMAgent` flag must be set
 provisioning time, via whichever API is being used. We will provide more details on
 this on our wiki when it is generally available. 
 
-#### __Provisioning.Agent__
+#### __Provisioning.Enabled__
 
-_Type: String_
-_Default: auto_
-
-Choose which provisioning agent to use (or allow waagent to figure it out by
-specifying "auto"). Possible options are "auto" (default), "waagent", "cloud-init",
-or "disabled".
-
-#### __Provisioning.Enabled__ (*removed in VERSION*)
-
-_Type: Boolean_ 
+_Type: Boolean_  
 _Default: y_
 
 This allows the user to enable or disable the provisioning functionality in the
@@ -255,13 +247,9 @@ agent. Valid values are "y" or "n". If provisioning is disabled, SSH host and
 user keys in the image are preserved and any configuration specified in the
 Azure provisioning API is ignored.
 
-_Note_: This configuration option has been removed and has no effect. waagent
-now auto-detects cloud-init as a provisioning agent (with an option to override
-with `Provisioning.Agent`).
-
-#### __Provisioning.UseCloudInit__ (*removed in VERSION*)
-
-_Type: Boolean_ 
+#### __Provisioning.UseCloudInit__
+  
+_Type: Boolean_  
 _Default: n_
 
 This options enables / disables support for provisioning by means of cloud-init.
@@ -270,10 +258,6 @@ extensions and processing the latest goal state. _Provisioning.Enabled_ must be
 disabled ("n") for this option to have an effect. Setting _Provisioning.Enabled_ to
 true ("y") overrides this option and runs the built-in agent provisioning code.
 
-_Note_: This configuration option has been removed and has no effect. waagent
-now auto-detects cloud-init as a provisioning agent (with an option to override
-with `Provisioning.Agent`).
-
 #### __Provisioning.DeleteRootPassword__  
 
 _Type: Boolean_  
@@ -417,10 +401,11 @@ leverages the system logrotate functionality to rotate logs.
 _Type: Boolean_  
 _Default: n_
 
-If SSL support is not compiled into Python, the agent will fail all HTTPS requests.
-You can set this option to 'y' to make the agent fall-back to HTTP, instead of failing the requests.
+If set to `y` and SSL support is not compiled into Python, the agent will fall-back to
+use HTTP. Otherwise, if SSL support is not compiled into Python, the agent will fail
+all HTTPS requests.
 
-NOTE: Allowing HTTP may unintentionally expose secure data.
+Note: Allowing HTTP may unintentionally expose secure data.
 
 #### __OS.EnableRDMA__
 
diff --git a/azurelinuxagent/common/cgroupapi.py b/azurelinuxagent/common/cgroupapi.py
index b72a2b31..d497c68c 100644
--- a/azurelinuxagent/common/cgroupapi.py
+++ b/azurelinuxagent/common/cgroupapi.py
@@ -88,10 +88,45 @@ class CGroupsApi(object):
     @staticmethod
     def _is_systemd():
         """
-        Determine if systemd is managing system services; the implementation follows the same strategy as, for example,
-        sd_booted() in libsystemd, or /usr/sbin/service
+        Determine if systemd is managing system services. If this process (presumed to be the agent) is in a CPU cgroup
+        that looks like one created by systemd, we can assume systemd is in use.
+
+        TODO: We need to re-evaluate whether this the right logic to determine if Systemd is managing cgroups.
+
+        :return: True if systemd is managing system services
+        :rtype: Bool
+        """
+        controller_id = CGroupsApi._get_controller_id('cpu')
+        current_process_cgroup_path = CGroupsApi._get_current_process_cgroup_relative_path(controller_id)
+        is_systemd = current_process_cgroup_path == 'system.slice/walinuxagent.service'
+
+        return is_systemd
+
+    @staticmethod
+    def _get_current_process_cgroup_relative_path(controller_id):
+        """
+        Get the cgroup path "suffix" for this process for the given controller. The leading "/" is always stripped,
+        so the suffix is suitable for passing to os.path.join(). (If the process is in the root cgroup, an empty
+        string is returned, and os.path.join() will still do the right thing.)
+        """
+        cgroup_paths = fileutil.read_file("/proc/self/cgroup")
+        for entry in cgroup_paths.splitlines():
+            fields = entry.split(':')
+            if fields[0] == controller_id:
+                return fields[2].lstrip(os.path.sep)
+        raise CGroupsException("This process belongs to no cgroup for controller ID {0}".format(controller_id))
+
+    @staticmethod
+    def _get_controller_id(controller):
+        """
+        Get the ID for a given cgroup controller
         """
-        return os.path.exists('/run/systemd/system/')
+        cgroup_states = fileutil.read_file("/proc/cgroups")
+        for entry in cgroup_states.splitlines():
+            fields = entry.split('\t')
+            if fields[0] == controller:
+                return fields[1]
+        raise CGroupsException("Cgroup controller {0} not found in /proc/cgroups".format(controller))
 
     @staticmethod
     def _foreach_controller(operation, message):
@@ -359,8 +394,8 @@ class SystemdCgroupsApi(CGroupsApi):
         try:
             unit_path = os.path.join(UNIT_FILES_FILE_SYSTEM_PATH, unit_filename)
             fileutil.write_file(unit_path, unit_contents)
-            shellutil.run_command(["systemctl", "daemon-reload"])
-            shellutil.run_command(["systemctl", "start", unit_filename])
+            shellutil.run_get_output("systemctl daemon-reload")
+            shellutil.run_get_output("systemctl start {0}".format(unit_filename))
         except Exception as e:
             raise CGroupsException("Failed to create and start {0}. Error: {1}".format(unit_filename, ustr(e)))
 
@@ -428,9 +463,9 @@ After=system-{1}.slice""".format(extension_name, EXTENSIONS_ROOT_CGROUP_NAME)
         unit_filename = self._get_extension_slice_name(extension_name)
         try:
             unit_path = os.path.join(UNIT_FILES_FILE_SYSTEM_PATH, unit_filename)
-            shellutil.run_command(["systemctl", "stop", unit_filename])
+            shellutil.run_get_output("systemctl stop {0}".format(unit_filename))
             fileutil.rm_files(unit_path)
-            shellutil.run_command(["systemctl", "daemon-reload"])
+            shellutil.run_get_output("systemctl daemon-reload")
         except Exception as e:
             raise CGroupsException("Failed to remove {0}. Error: {1}".format(unit_filename, ustr(e)))
 
@@ -510,8 +545,6 @@ After=system-{1}.slice""".format(extension_name, EXTENSIONS_ROOT_CGROUP_NAME)
                 stderr.truncate(0)
 
                 # Try invoking the process again, this time without systemd-run
-                logger.info('Extension invocation using systemd failed, falling back to regular invocation '
-                            'without cgroups tracking.')
                 process = subprocess.Popen(command,
                                            shell=shell,
                                            cwd=cwd,
diff --git a/azurelinuxagent/common/conf.py b/azurelinuxagent/common/conf.py
index fb26468e..17351199 100644
--- a/azurelinuxagent/common/conf.py
+++ b/azurelinuxagent/common/conf.py
@@ -98,6 +98,8 @@ __SWITCH_OPTIONS__ = {
     "Logs.Verbose": False,
     "Logs.Console": True,
     "Extensions.Enabled": True,
+    "Provisioning.Enabled": True,
+    "Provisioning.UseCloudInit": False,
     "Provisioning.AllowResetSysUser": False,
     "Provisioning.RegenerateSshHostKeyPair": False,
     "Provisioning.DeleteRootPassword": False,
@@ -125,7 +127,6 @@ __STRING_OPTIONS__ = {
     "OS.PasswordPath": "/etc/shadow",
     "OS.SudoersDir": "/etc/sudoers.d",
     "OS.RootDeviceScsiTimeout": None,
-    "Provisioning.Agent": "auto",
     "Provisioning.SshHostKeyPairType": "rsa",
     "Provisioning.PasswordCryptId": "6",
     "HttpProxy.Host": None,
@@ -267,10 +268,18 @@ def get_ssh_host_keypair_mode(conf=__conf__):
     return conf.get("Provisioning.SshHostKeyPairType", "rsa")
 
 
+def get_provision_enabled(conf=__conf__):
+    return conf.get_switch("Provisioning.Enabled", True)
+
+
 def get_extensions_enabled(conf=__conf__):
     return conf.get_switch("Extensions.Enabled", True)
 
 
+def get_provision_cloudinit(conf=__conf__):
+    return conf.get_switch("Provisioning.UseCloudInit", False)
+
+
 def get_allow_reset_sys_user(conf=__conf__):
     return conf.get_switch("Provisioning.AllowResetSysUser", False)
 
@@ -295,21 +304,6 @@ def get_password_cryptid(conf=__conf__):
     return conf.get("Provisioning.PasswordCryptId", "6")
 
 
-def get_provisioning_agent(conf=__conf__):
-    return conf.get("Provisioning.Agent", "auto")
-
-
-def get_provision_enabled(conf=__conf__):
-    """
-    Provisioning (as far as waagent is concerned) is enabled if either the
-    agent is set to 'auto' or 'waagent'. This wraps logic that was introduced
-    for flexible provisioning agent configuration and detection. The replaces
-    the older bool setting to turn provisioning on or off.
-    """
-
-    return get_provisioning_agent(conf) in ("auto", "waagent")
-
-
 def get_password_crypt_salt_len(conf=__conf__):
     return conf.get_int("Provisioning.PasswordCryptSaltLength", 10)
 
diff --git a/azurelinuxagent/common/dhcp.py b/azurelinuxagent/common/dhcp.py
index fc2cb649..108d996e 100644
--- a/azurelinuxagent/common/dhcp.py
+++ b/azurelinuxagent/common/dhcp.py
@@ -86,8 +86,9 @@ class DhcpHandler(object):
         route_exists = False
         logger.info("Test for route to {0}".format(KNOWN_WIRESERVER_IP))
         try:
-            route_table = self.osutil.read_route_table()
-            if any([(KNOWN_WIRESERVER_IP_ENTRY in route) for route in route_table]):
+            route_file = '/proc/net/route'
+            if os.path.exists(route_file) and \
+                    KNOWN_WIRESERVER_IP_ENTRY in open(route_file).read():
                 # reset self.gateway and self.routes
                 # we do not need to alter the routing table
                 self.endpoint = KNOWN_WIRESERVER_IP
@@ -101,7 +102,7 @@ class DhcpHandler(object):
             logger.error(
                 "Could not determine whether route exists to {0}: {1}".format(
                     KNOWN_WIRESERVER_IP, e))
-                    
+
         return route_exists
 
     @property
diff --git a/azurelinuxagent/common/osutil/debian.py b/azurelinuxagent/common/osutil/debian.py
index 6e573ef3..527831f0 100644
--- a/azurelinuxagent/common/osutil/debian.py
+++ b/azurelinuxagent/common/osutil/debian.py
@@ -33,10 +33,10 @@ import azurelinuxagent.common.utils.textutil as textutil
 from azurelinuxagent.common.osutil.default import DefaultOSUtil
 
 
-class DebianOSBaseUtil(DefaultOSUtil):
+class DebianOSUtil(DefaultOSUtil):
 
     def __init__(self):
-        super(DebianOSBaseUtil, self).__init__()
+        super(DebianOSUtil, self).__init__()
         self.jit_enabled = True
 
     def restart_ssh_service(self):
@@ -61,10 +61,10 @@ class DebianOSBaseUtil(DefaultOSUtil):
         return self.get_endpoint_from_leases_path('/var/lib/dhcp/dhclient.*.leases')
 
 
-class DebianOSModernUtil(DebianOSBaseUtil):
+class DebianOS8Util(DebianOSUtil):
 
     def __init__(self):
-        super(DebianOSModernUtil, self).__init__()
+        super(DebianOS8Util, self).__init__()
         self.jit_enabled = True
         self.service_name = self.get_service_name()
 
diff --git a/azurelinuxagent/common/osutil/default.py b/azurelinuxagent/common/osutil/default.py
index 7ccc5344..36326c4e 100644
--- a/azurelinuxagent/common/osutil/default.py
+++ b/azurelinuxagent/common/osutil/default.py
@@ -97,8 +97,6 @@ IP_COMMAND_OUTPUT = re.compile('^\d+:\s+(\w+):\s+(.*)$')
 
 BASE_CGROUPS = '/sys/fs/cgroup'
 
-STORAGE_DEVICE_PATH = '/sys/bus/vmbus/devices/'
-GEN2_DEVICE_ID = 'f8b3781a-1e82-4818-a1c3-63d806ec15bb'
 
 class DefaultOSUtil(object):
     def __init__(self):
@@ -1193,67 +1191,6 @@ class DefaultOSUtil(object):
                     return tokens[2] if len(tokens) > 2 else None
         return None
 
-    @staticmethod
-    def _enumerate_device_id():
-        """
-        Enumerate all storage device IDs.
-
-        Args:
-            None
-
-        Returns:
-            Iterator[Tuple[str, str]]: VmBus and storage devices.
-        """
-
-        if os.path.exists(STORAGE_DEVICE_PATH):
-            for vmbus in os.listdir(STORAGE_DEVICE_PATH):
-                deviceid = fileutil.read_file(os.path.join(STORAGE_DEVICE_PATH, vmbus, "device_id"))
-                guid = deviceid.strip('{}\n')
-                yield vmbus, guid
-
-    @staticmethod
-    def search_for_resource_disk(gen1_device_prefix, gen2_device_id):
-        """
-        Search the filesystem for a device by ID or prefix.
-
-        Args:
-            gen1_device_prefix (str): Gen1 resource disk prefix.
-            gen2_device_id (str): Gen2 resource device ID.
-
-        Returns:
-            str: The found device.
-        """
-
-        device = None
-        # We have to try device IDs for both Gen1 and Gen2 VMs.
-        logger.info('Searching gen1 prefix {0} or gen2 {1}'.format(gen1_device_prefix, gen2_device_id))
-        try:
-            for vmbus, guid in DefaultOSUtil._enumerate_device_id():
-                if guid.startswith(gen1_device_prefix) or guid == gen2_device_id:
-                    for root, dirs, files in os.walk(STORAGE_DEVICE_PATH + vmbus):
-                        root_path_parts = root.split('/')
-                        # For Gen1 VMs we only have to check for the block dir in the
-                        # current device. But for Gen2 VMs all of the disks (sda, sdb,
-                        # sr0) are presented in this device on the same SCSI controller.
-                        # Because of that we need to also read the LUN. It will be:
-                        #   0 - OS disk
-                        #   1 - Resource disk
-                        #   2 - CDROM
-                        if root_path_parts[-1] == 'block' and (
-                                guid != gen2_device_id or
-                                root_path_parts[-2].split(':')[-1] == '1'):
-                            device = dirs[0]
-                            return device
-                        else:
-                            # older distros
-                            for d in dirs:
-                                if ':' in d and "block" == d.split(':')[0]:
-                                    device = d.split(':')[1]
-                                    return device
-        except (OSError, IOError) as exc:
-            logger.warn('Error getting device for {0} or {1}: {2}', gen1_device_prefix, gen2_device_id, ustr(exc))
-        return None
-
     def device_for_ide_port(self, port_id):
         """
         Return device name attached to ide port 'n'.
@@ -1264,13 +1201,27 @@ class DefaultOSUtil(object):
         if port_id > 1:
             g0 = "00000001"
             port_id = port_id - 2
-
-        gen1_device_prefix = '{0}-000{1}'.format(g0, port_id)
-        device = DefaultOSUtil.search_for_resource_disk(
-            gen1_device_prefix=gen1_device_prefix,
-            gen2_device_id=GEN2_DEVICE_ID
-        )
-        logger.info('Found device: {0}'.format(device))
+        device = None
+        path = "/sys/bus/vmbus/devices/"
+        if os.path.exists(path):
+            try:
+                for vmbus in os.listdir(path):
+                    deviceid = fileutil.read_file(os.path.join(path, vmbus, "device_id"))
+                    guid = deviceid.lstrip('{').split('-')
+                    if guid[0] == g0 and guid[1] == "000" + ustr(port_id):
+                        for root, dirs, files in os.walk(path + vmbus):
+                            if root.endswith("/block"):
+                                device = dirs[0]
+                                break
+                            else:
+                                # older distros
+                                for d in dirs:
+                                    if ':' in d and "block" == d.split(':')[0]:
+                                        device = d.split(':')[1]
+                                        break
+                        break
+            except OSError as oe:
+                logger.warn('Could not obtain device for IDE port {0}: {1}', port_id, ustr(oe))
         return device
 
     def set_hostname_record(self, hostname):
diff --git a/azurelinuxagent/common/osutil/factory.py b/azurelinuxagent/common/osutil/factory.py
index 56515ede..3d91f10c 100644
--- a/azurelinuxagent/common/osutil/factory.py
+++ b/azurelinuxagent/common/osutil/factory.py
@@ -22,7 +22,7 @@ from .default import DefaultOSUtil
 from .arch import ArchUtil
 from .clearlinux import ClearLinuxUtil
 from .coreos import CoreOSUtil
-from .debian import DebianOSBaseUtil, DebianOSModernUtil
+from .debian import DebianOSUtil, DebianOS8Util
 from .freebsd import FreeBSDOSUtil
 from .openbsd import OpenBSDOSUtil
 from .redhat import RedhatOSUtil, Redhat6xOSUtil
@@ -76,7 +76,7 @@ def _get_osutil(distro_name, distro_code_name, distro_version, distro_full_name)
         return AlpineOSUtil()
 
     if distro_name == "kali":
-        return DebianOSBaseUtil()
+        return DebianOSUtil()
 
     if distro_name == "coreos" or distro_code_name == "coreos":
         return CoreOSUtil()
@@ -90,10 +90,10 @@ def _get_osutil(distro_name, distro_code_name, distro_version, distro_full_name)
             return SUSEOSUtil()
 
     if distro_name == "debian":
-        if "sid" in distro_version or Version(distro_version) > Version("7"):
-            return DebianOSModernUtil()
+        if Version(distro_version) > Version("7"):
+            return DebianOS8Util()
         else:
-            return DebianOSBaseUtil()
+            return DebianOSUtil()
 
     if distro_name == "redhat" \
             or distro_name == "centos" \
diff --git a/azurelinuxagent/common/osutil/freebsd.py b/azurelinuxagent/common/osutil/freebsd.py
index 2e298ca5..ae7fed45 100644
--- a/azurelinuxagent/common/osutil/freebsd.py
+++ b/azurelinuxagent/common/osutil/freebsd.py
@@ -16,13 +16,9 @@
 #
 # Requires Python 2.6+ and Openssl 1.0+
 
-import socket
-import struct
-import binascii
 import azurelinuxagent.common.utils.fileutil as fileutil
 import azurelinuxagent.common.utils.shellutil as shellutil
 import azurelinuxagent.common.utils.textutil as textutil
-from azurelinuxagent.common.utils.networkutil import RouteEntry
 import azurelinuxagent.common.logger as logger
 from azurelinuxagent.common.exception import OSUtilError
 from azurelinuxagent.common.osutil.default import DefaultOSUtil
@@ -97,304 +93,6 @@ class FreeBSDOSUtil(DefaultOSUtil):
     def get_first_if(self):
         return self._get_net_info()[:2]
 
-    @staticmethod
-    def read_route_table():
-        """
-        Return a list of strings comprising the route table as in the Linux /proc/net/route format. The input taken is from FreeBSDs
-        `netstat -rn -f inet` command. Here is what the function does in detail:
-
-        1. Runs `netstat -rn -f inet` which outputs a column formatted list of ipv4 routes in priority order like so:
-
-            > Routing tables
-            > 
-            > Internet:
-            > Destination        Gateway            Flags    Refs      Use  Netif Expire
-            > default            61.221.xx.yy       UGS         0      247    em1
-            > 10                 10.10.110.5        UGS         0       50    em0
-            > 10.10.110/26       link#1             UC          0        0    em0
-            > 10.10.110.5        00:1b:0d:e6:58:40  UHLW        2        0    em0   1145
-            > 61.221.xx.yy/29    link#2             UC          0        0    em1
-            > 61.221.xx.yy       00:1b:0d:e6:57:c0  UHLW        2        0    em1   1055
-            > 61.221.xx/24       link#2             UC          0        0    em1
-            > 127.0.0.1          127.0.0.1          UH          0        0    lo0
-        
-        2. Convert it to an array of lines that resemble an equivalent /proc/net/route content on a Linux system like so:
-
-            > Iface   Destination Gateway     Flags   RefCnt  Use Metric  Mask        MTU Window  IRTT
-            > gre828  00000000    00000000    0001    0   0   0   000000F8    0   0   0
-            > ens160  00000000    FE04700A    0003    0   0   100 00000000    0   0   0
-            > gre828  00000008    00000000    0001    0   0   0   000000FE    0   0   0
-            > ens160  0004700A    00000000    0001    0   0   100 00FFFFFF    0   0   0
-            > gre828  2504700A    00000000    0005    0   0   0   FFFFFFFF    0   0   0
-            > gre828  3704700A    00000000    0005    0   0   0   FFFFFFFF    0   0   0
-            > gre828  4104700A    00000000    0005    0   0   0   FFFFFFFF    0   0   0
-
-        :return: Entries in the ipv4 route priority list from `netstat -rn -f inet` in the linux `/proc/net/route` style
-        :rtype: list(str)
-        """
-            
-        def _get_netstat_rn_ipv4_routes():
-            """
-            Runs `netstat -rn -f inet` and parses its output and returns a list of routes where the key is the column name
-            and the value is the value in the column, stripped of leading and trailing whitespace.
-
-            :return: List of dictionaries representing routes in the ipv4 route priority list from `netstat -rn -f inet`
-            :rtype: list(dict)
-            """
-            cmd = [ "netstat", "-rn", "-f", "inet" ]
-            output = shellutil.run_command(cmd, log_error=True)
-            output_lines = output.split("\n")
-            if len(output_lines) < 3:
-                raise OSUtilError("`netstat -rn -f inet` output seems to be empty")
-            output_lines = [ line.strip() for line in output_lines if line ]
-            if "Internet:" not in output_lines:
-                raise OSUtilError("`netstat -rn -f inet` output seems to contain no ipv4 routes")
-            route_header_line = output_lines.index("Internet:") + 1
-            # Parse the file structure and left justify the routes
-            route_start_line = route_header_line + 1
-            route_line_length = max([len(line) for line in output_lines[route_header_line:]])
-            netstat_route_list = [line.ljust(route_line_length) for line in output_lines[route_start_line:]]
-            # Parse the headers
-            _route_headers = output_lines[route_header_line].split()
-            n_route_headers = len(_route_headers)
-            route_columns = {}
-            for i in range(0, n_route_headers - 1):
-                route_columns[_route_headers[i]] = (
-                    output_lines[route_header_line].index(_route_headers[i]),
-                    (output_lines[route_header_line].index(_route_headers[i+1]) - 1)
-                )
-            route_columns[_route_headers[n_route_headers - 1]] = (
-                output_lines[route_header_line].index(_route_headers[n_route_headers - 1]),
-                None
-            )
-            # Parse the routes
-            netstat_routes = []
-            n_netstat_routes = len(netstat_route_list)
-            for i in range(0, n_netstat_routes):
-                netstat_route = {}
-                for column in route_columns:
-                    netstat_route[column] = netstat_route_list[i][route_columns[column][0]:route_columns[column][1]].strip()
-                netstat_route["Metric"] = n_netstat_routes - i
-                netstat_routes.append(netstat_route)
-            # Return the Sections
-            return netstat_routes
-
-        def _ipv4_ascii_address_to_hex(ipv4_ascii_address):
-            """
-            Converts an IPv4 32bit address from its ASCII notation (ie. 127.0.0.1) to an 8 digit padded hex notation
-            (ie. "0100007F") string.
-
-            :return: 8 character long hex string representation of the IP
-            :rtype: string
-            """
-            # Raises socket.error if the IP is not a valid IPv4
-            return "%08X" % int(binascii.hexlify(struct.pack("!I", struct.unpack("=I", socket.inet_pton(socket.AF_INET, ipv4_ascii_address))[0])), 16)
-
-        def _ipv4_cidr_mask_to_hex(ipv4_cidr_mask):
-            """
-            Converts an subnet mask from its CIDR integer notation (ie. 32) to an 8 digit padded hex notation
-            (ie. "FFFFFFFF") string representing its bitmask form.
-
-            :return: 8 character long hex string representation of the IP
-            :rtype: string
-            """
-            return "{0:08x}".format(struct.unpack("=I", struct.pack("!I", (0xffffffff << (32 - ipv4_cidr_mask)) & 0xffffffff))[0]).upper()
-
-        def _ipv4_cidr_destination_to_hex(destination):
-            """
-            Converts an destination address from its CIDR notation (ie. 127.0.0.1/32 or default or localhost) to an 8
-            digit padded hex notation (ie. "0100007F" or "00000000" or "0100007F") string and its subnet bitmask
-            also in hex (FFFFFFFF).
-
-            :return: tuple of 8 character long hex string representation of the IP and 8 character long hex string representation of the subnet mask
-            :rtype: tuple(string, int)
-            """
-            destination_ip = "0.0.0.0"
-            destination_subnetmask = 32
-            if destination != "default":
-                if destination == "localhost":
-                    destination_ip = "127.0.0.1"
-                else:
-                    destination_ip = destination.split("/")
-                    if len(destination_ip) > 1:
-                        destination_subnetmask = int(destination_ip[1])
-                    destination_ip = destination_ip[0]
-            hex_destination_ip = _ipv4_ascii_address_to_hex(destination_ip)
-            hex_destination_subnetmask = _ipv4_cidr_mask_to_hex(destination_subnetmask)
-            return hex_destination_ip, hex_destination_subnetmask
-        
-        def _try_ipv4_gateway_to_hex(gateway):
-            """
-            If the gateway is an IPv4 address, return its IP in hex, else, return "00000000"
-
-            :return: 8 character long hex string representation of the IP of the gateway
-            :rtype: string
-            """
-            try:
-                return _ipv4_ascii_address_to_hex(gateway)
-            except socket.error:
-                return "00000000"
-
-        def _ascii_route_flags_to_bitmask(ascii_route_flags):
-            """
-            Converts route flags to a bitmask of their equivalent linux/route.h values.
-
-            :return: integer representation of a 16 bit mask
-            :rtype: int
-            """
-            bitmask_flags = 0
-            RTF_UP = 0x0001
-            RTF_GATEWAY = 0x0002
-            RTF_HOST = 0x0004
-            RTF_DYNAMIC = 0x0010
-            if "U" in ascii_route_flags:
-                bitmask_flags |= RTF_UP
-            if "G" in ascii_route_flags:
-                bitmask_flags |= RTF_GATEWAY
-            if "H" in ascii_route_flags:
-                bitmask_flags |= RTF_HOST
-            if "S" not in ascii_route_flags:
-                bitmask_flags |= RTF_DYNAMIC
-            return bitmask_flags
-
-        def _freebsd_netstat_rn_route_to_linux_proc_net_route(netstat_route):
-            """
-            Converts a single FreeBSD `netstat -rn -f inet` route to its equivalent /proc/net/route line. ie:
-            > default            0.0.0.0       UGS         0      247    em1
-            to
-            > em1  00000000    00000000    0003    0   0   0   FFFFFFFF    0   0   0
-
-            :return: string representation of the equivalent /proc/net/route line
-            :rtype: string
-            """
-            network_interface = netstat_route["Netif"]
-            hex_destination_ip, hex_destination_subnetmask = _ipv4_cidr_destination_to_hex(netstat_route["Destination"])
-            hex_gateway = _try_ipv4_gateway_to_hex(netstat_route["Gateway"])
-            bitmask_flags = _ascii_route_flags_to_bitmask(netstat_route["Flags"])
-            dummy_refcount = 0
-            dummy_use = 0
-            route_metric = netstat_route["Metric"]
-            dummy_mtu = 0
-            dummy_window = 0
-            dummy_irtt = 0
-            return "{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}".format(
-                network_interface,
-                hex_destination_ip,
-                hex_gateway,
-                bitmask_flags,
-                dummy_refcount,
-                dummy_use,
-                route_metric,
-                hex_destination_subnetmask,
-                dummy_mtu,
-                dummy_window,
-                dummy_irtt
-            )
-
-        linux_style_route_file = [ "Iface\tDestination\tGateway\tFlags\tRefCnt\tUse\tMetric\tMask\tMTU\tWindow\tIRTT" ]
-
-        try:
-            netstat_routes = _get_netstat_rn_ipv4_routes()
-            # Make sure the `netstat -rn -f inet` contains columns for Netif, Destination, Gateway and Flags which are needed to convert
-            # to the Linux Format
-            if len(netstat_routes) > 0:
-                missing_headers = []
-                if "Netif" not in netstat_routes[0]:
-                    missing_headers.append("Netif")
-                if "Destination" not in netstat_routes[0]:
-                    missing_headers.append("Destination")
-                if "Gateway" not in netstat_routes[0]:
-                    missing_headers.append("Gateway")
-                if "Flags" not in netstat_routes[0]:
-                    missing_headers.append("Flags")
-                if missing_headers:
-                    raise KeyError("`netstat -rn -f inet` output is missing columns required to convert to the Linux /proc/net/route format; columns are [{0}]".format(missing_headers))
-                # Parse the Netstat IPv4 Routes
-                for netstat_route in netstat_routes:
-                    try:
-                        linux_style_route = _freebsd_netstat_rn_route_to_linux_proc_net_route(netstat_route)
-                        linux_style_route_file.append(linux_style_route)
-                    except Exception:
-                        # Skip the route
-                        continue
-        except Exception as e:
-            logger.error("Cannot read route table [{0}]", ustr(e))
-        return linux_style_route_file
-
-    @staticmethod
-    def get_list_of_routes(route_table):
-        """
-        Construct a list of all network routes known to this system.
-
-        :param list(str) route_table: List of text entries from route table, including headers
-        :return: a list of network routes
-        :rtype: list(RouteEntry)
-        """
-        route_list = []
-        count = len(route_table)
-
-        if count < 1:
-            logger.error("netstat -rn -f inet is missing headers")
-        elif count == 1:
-            logger.error("netstat -rn -f inet contains no routes")
-        else:
-            route_list = DefaultOSUtil._build_route_list(route_table)
-        return route_list
-
-    def get_primary_interface(self):
-        """
-        Get the name of the primary interface, which is the one with the
-        default route attached to it; if there are multiple default routes,
-        the primary has the lowest Metric.
-        :return: the interface which has the default route
-        """
-        RTF_GATEWAY = 0x0002
-        DEFAULT_DEST = "00000000"
-        
-        primary_interface = None
-
-        if not self.disable_route_warning:
-            logger.info("Examine `netstat -rn -f inet` for primary interface")
-
-        route_table = self.read_route_table()
-
-        def is_default(route):
-            return (route.destination == DEFAULT_DEST) and (RTF_GATEWAY & route.flags)
-
-        candidates = list(filter(is_default, self.get_list_of_routes(route_table)))
-
-        if len(candidates) > 0:
-            def get_metric(route):
-                return int(route.metric)
-            primary_route = min(candidates, key=get_metric)
-            primary_interface = primary_route.interface
-
-        if primary_interface is None:
-            primary_interface = ''
-            if not self.disable_route_warning:
-                logger.warn('Could not determine primary interface, '
-                            'please ensure routes are correct')
-                logger.warn('Primary interface examination will retry silently')
-                self.disable_route_warning = True
-        else:
-            logger.info('Primary interface is [{0}]'.format(primary_interface))
-            self.disable_route_warning = False
-        return primary_interface
-
-    def is_primary_interface(self, ifname):
-        """
-        Indicate whether the specified interface is the primary.
-        :param ifname: the name of the interface - eth0, lo, etc.
-        :return: True if this interface binds the default route
-        """
-        return self.get_primary_interface() == ifname
-
-    def is_loopback(self, ifname):
-        """
-        Determine if a named interface is loopback.
-        """
-        return ifname.startswith("lo")
-
     def route_add(self, net, mask, gateway):
         cmd = 'route add {0} {1} {2}'.format(net, gateway, mask)
         return shellutil.run(cmd, chk_err=False)
@@ -405,14 +103,6 @@ class FreeBSDOSUtil(DefaultOSUtil):
         specify the route manually to get it work in a VNET environment.
         SEE ALSO: man ip(4) IP_ONESBCAST,
         """
-        RTF_GATEWAY = 0x0002
-        DEFAULT_DEST = "00000000"
-
-        route_table = self.read_route_table()
-        routes = self.get_list_of_routes(route_table)
-        for route in routes:
-            if (route.destination == DEFAULT_DEST) and (RTF_GATEWAY & route.flags):
-               return False
         return True
 
     def is_dhcp_enabled(self):
diff --git a/azurelinuxagent/common/utils/shellutil.py b/azurelinuxagent/common/utils/shellutil.py
index 1260f9d9..96897635 100644
--- a/azurelinuxagent/common/utils/shellutil.py
+++ b/azurelinuxagent/common/utils/shellutil.py
@@ -89,10 +89,13 @@ def run_get_output(cmd, chk_err=True, log_cmd=True, expected_errors=[]):
         output = subprocess.check_output(cmd,
                                          stderr=subprocess.STDOUT,
                                          shell=True)
-        output = _encode_command_output(output)
+        output = ustr(output,
+                      encoding='utf-8',
+                      errors="backslashreplace")
     except subprocess.CalledProcessError as e:
-        output = _encode_command_output(e.output)
-
+        output = ustr(e.output,
+                      encoding='utf-8',
+                      errors="backslashreplace")
         if chk_err:
             msg = u"Command: [{0}], " \
                   u"return code: [{1}], " \
diff --git a/azurelinuxagent/daemon/main.py b/azurelinuxagent/daemon/main.py
index 0f5296a4..723324df 100644
--- a/azurelinuxagent/daemon/main.py
+++ b/azurelinuxagent/daemon/main.py
@@ -61,7 +61,6 @@ class DaemonHandler(object):
 
     def run(self, child_args=None):
         logger.info("{0} Version:{1}", AGENT_LONG_NAME, AGENT_VERSION)
-        logger.info("OS: {0} {1}", DISTRO_NAME, DISTRO_VERSION)
         logger.info("Python: {0}.{1}.{2}", PY_VERSION_MAJOR, PY_VERSION_MINOR,
                     PY_VERSION_MICRO)
 
diff --git a/azurelinuxagent/daemon/resourcedisk/default.py b/azurelinuxagent/daemon/resourcedisk/default.py
index 5ed14b01..cfb76d2b 100644
--- a/azurelinuxagent/daemon/resourcedisk/default.py
+++ b/azurelinuxagent/daemon/resourcedisk/default.py
@@ -195,7 +195,7 @@ class ResourceDiskHandler(object):
 
             self.reread_partition_table(device)
 
-            ret, output = shellutil.run_get_output(mount_string, chk_err=False)
+            ret, output = shellutil.run_get_output(mount_string)
             if ret:
                 logger.warn("Failed to mount resource disk. "
                             "Attempting to format and retry mount. [{0}]",
diff --git a/azurelinuxagent/pa/provision/cloudinit.py b/azurelinuxagent/pa/provision/cloudinit.py
index e4455685..3f3cdb04 100644
--- a/azurelinuxagent/pa/provision/cloudinit.py
+++ b/azurelinuxagent/pa/provision/cloudinit.py
@@ -19,7 +19,6 @@
 
 import os
 import os.path
-import subprocess
 import time
 
 from datetime import datetime
@@ -42,6 +41,13 @@ class CloudInitProvisionHandler(ProvisionHandler):
         super(CloudInitProvisionHandler, self).__init__()
 
     def run(self):
+        # If provision is enabled, run default provision handler
+        if conf.get_provision_enabled():
+            logger.warn("Provisioning flag is enabled, which overrides using "
+                        "cloud-init; running the default provisioning code")
+            super(CloudInitProvisionHandler, self).run()
+            return
+
         try:
             if super(CloudInitProvisionHandler, self).is_provisioned():
                 logger.info("Provisioning already completed, skipping.")
@@ -126,69 +132,3 @@ class CloudInitProvisionHandler(ProvisionHandler):
         raise ProvisionError("Giving up, ssh host key was not found at {0} "
                              "after {1}s".format(path,
                                                  max_retry * sleep_time))
-
-def _cloud_init_is_enabled_systemd():
-    """
-    Determine whether or not cloud-init is enabled on a systemd machine.
-
-    Args:
-        None
-
-    Returns:
-        bool: True if cloud-init is enabled, False if otherwise.
-    """
-
-    try:
-        systemctl_output = subprocess.check_output([
-            'systemctl',
-            'is-enabled',
-            'cloud-init-local.service'
-        ], stderr=subprocess.STDOUT).decode('utf-8').replace('\n', '')
-
-        unit_is_enabled = systemctl_output == 'enabled'
-    except Exception as exc:
-        logger.info('Error getting cloud-init enabled status from systemctl: {0}'.format(exc))
-        unit_is_enabled = False
-
-    return unit_is_enabled
-
-def _cloud_init_is_enabled_service():
-    """
-    Determine whether or not cloud-init is enabled on a non-systemd machine.
-
-    Args:
-        None
-
-    Returns:
-        bool: True if cloud-init is enabled, False if otherwise.
-    """
-
-    try:
-        subprocess.check_output([
-            'service',
-            'cloud-init',
-            'status'
-        ], stderr=subprocess.STDOUT)
-
-        unit_is_enabled = True
-    except Exception as exc:
-        logger.info('Error getting cloud-init enabled status from service: {0}'.format(exc))
-        unit_is_enabled = False
-
-    return unit_is_enabled
-
-def cloud_init_is_enabled():
-    """
-    Determine whether or not cloud-init is enabled.
-
-    Args:
-        None
-
-    Returns:
-        bool: True if cloud-init is enabled, False if otherwise.
-    """
-
-    unit_is_enabled = _cloud_init_is_enabled_systemd() or _cloud_init_is_enabled_service()
-    logger.info('cloud-init is enabled: {0}'.format(unit_is_enabled))
-
-    return unit_is_enabled
diff --git a/azurelinuxagent/pa/provision/factory.py b/azurelinuxagent/pa/provision/factory.py
index 8134d194..5f90319b 100644
--- a/azurelinuxagent/pa/provision/factory.py
+++ b/azurelinuxagent/pa/provision/factory.py
@@ -16,24 +16,19 @@
 #
 
 import azurelinuxagent.common.conf as conf
-from azurelinuxagent.common import logger
+
 from azurelinuxagent.common.version import DISTRO_NAME, DISTRO_VERSION, \
                                      DISTRO_FULL_NAME
 
 from .default import ProvisionHandler
-from .cloudinit import CloudInitProvisionHandler, cloud_init_is_enabled
+from .cloudinit import CloudInitProvisionHandler
 
-def get_provision_handler(distro_name=DISTRO_NAME,
+def get_provision_handler(distro_name=DISTRO_NAME, 
                             distro_version=DISTRO_VERSION,
                             distro_full_name=DISTRO_FULL_NAME):
 
-    provisioning_agent = conf.get_provisioning_agent()
-
-    if provisioning_agent == 'cloud-init' or (
-            provisioning_agent == 'auto' and
-            cloud_init_is_enabled()):
-        logger.info('Using cloud-init for provisioning')
+    if conf.get_provision_cloudinit():
         return CloudInitProvisionHandler()
 
-    logger.info('Using waagent for provisioning')
     return ProvisionHandler()
+


Test patch:
diff --git a/tests/common/osutil/test_default.py b/tests/common/osutil/test_default.py
index 968499b7..965550e6 100644
--- a/tests/common/osutil/test_default.py
+++ b/tests/common/osutil/test_default.py
@@ -926,41 +926,6 @@ Chain OUTPUT (policy ACCEPT 104 packets, 43628 bytes)
 
         self.assertTrue(len(pid_list) == 0, "the return value is not an empty list: {0}".format(pid_list))
 
-    @patch('os.walk', return_value=[('host3/target3:0:1/3:0:1:0/block', ['sdb'], [])])
-    @patch('azurelinuxagent.common.utils.fileutil.read_file', return_value='{00000000-0001-8899-0000-000000000000}')
-    @patch('os.listdir', return_value=['00000000-0001-8899-0000-000000000000'])
-    @patch('os.path.exists', return_value=True)
-    def test_device_for_ide_port_gen1_success(
-            self,
-            os_path_exists,
-            os_listdir,
-            fileutil_read_file,
-            os_walk):
-        dev = osutil.DefaultOSUtil().device_for_ide_port(1)
-        self.assertEqual(dev, 'sdb', 'The returned device should be the resource disk')
-
-    @patch('os.walk', return_value=[('host0/target0:0:0/0:0:0:1/block', ['sdb'], [])])
-    @patch('azurelinuxagent.common.utils.fileutil.read_file', return_value='{f8b3781a-1e82-4818-a1c3-63d806ec15bb}')
-    @patch('os.listdir', return_value=['f8b3781a-1e82-4818-a1c3-63d806ec15bb'])
-    @patch('os.path.exists', return_value=True)
-    def test_device_for_ide_port_gen2_success(
-            self,
-            os_path_exists,
-            os_listdir,
-            fileutil_read_file,
-            os_walk):
-        dev = osutil.DefaultOSUtil().device_for_ide_port(1)
-        self.assertEqual(dev, 'sdb', 'The returned device should be the resource disk')
-
-    @patch('os.listdir', return_value=['00000000-0000-0000-0000-000000000000'])
-    @patch('os.path.exists', return_value=True)
-    def test_device_for_ide_port_none(
-            self,
-            os_path_exists,
-            os_listdir):
-        dev = osutil.DefaultOSUtil().device_for_ide_port(1)
-        self.assertIsNone(dev, 'None should be returned if no resource disk found')
-
 def osutil_get_dhcp_pid_should_return_a_list_of_pids(test_instance, osutil_instance):
     """
     This is a very basic test for osutil.get_dhcp_pid. It is simply meant to exercise the implementation of that method
diff --git a/tests/common/osutil/test_factory.py b/tests/common/osutil/test_factory.py
index 92aa7d6e..6b639137 100644
--- a/tests/common/osutil/test_factory.py
+++ b/tests/common/osutil/test_factory.py
@@ -20,7 +20,7 @@ from azurelinuxagent.common.osutil.default import DefaultOSUtil
 from azurelinuxagent.common.osutil.arch import ArchUtil
 from azurelinuxagent.common.osutil.clearlinux import ClearLinuxUtil
 from azurelinuxagent.common.osutil.coreos import CoreOSUtil
-from azurelinuxagent.common.osutil.debian import DebianOSBaseUtil, DebianOSModernUtil
+from azurelinuxagent.common.osutil.debian import DebianOSUtil, DebianOS8Util
 from azurelinuxagent.common.osutil.freebsd import FreeBSDOSUtil
 from azurelinuxagent.common.osutil.openbsd import OpenBSDOSUtil
 from azurelinuxagent.common.osutil.redhat import RedhatOSUtil, Redhat6xOSUtil
@@ -125,7 +125,7 @@ class TestOsUtilFactory(AgentTestCase):
                           distro_code_name="",
                           distro_version="",
                           distro_full_name="")
-        self.assertTrue(type(ret) == DebianOSBaseUtil)
+        self.assertTrue(type(ret) == DebianOSUtil)
         self.assertEquals(ret.get_service_name(), "waagent")
 
     def test_get_osutil_it_should_return_coreos(self):
@@ -163,14 +163,14 @@ class TestOsUtilFactory(AgentTestCase):
                           distro_code_name="",
                           distro_full_name="",
                           distro_version="7")
-        self.assertTrue(type(ret) == DebianOSBaseUtil)
+        self.assertTrue(type(ret) == DebianOSUtil)
         self.assertEquals(ret.get_service_name(), "waagent")
 
         ret = _get_osutil(distro_name="debian",
                           distro_code_name="",
                           distro_full_name="",
                           distro_version="8")
-        self.assertTrue(type(ret) == DebianOSModernUtil)
+        self.assertTrue(type(ret) == DebianOS8Util)
         self.assertEquals(ret.get_service_name(), "walinuxagent")
 
     def test_get_osutil_it_should_return_redhat(self):
diff --git a/tests/common/osutil/test_freebsd.py b/tests/common/osutil/test_freebsd.py
index 1b1f687b..14b87719 100644
--- a/tests/common/osutil/test_freebsd.py
+++ b/tests/common/osutil/test_freebsd.py
@@ -14,14 +14,12 @@
 #
 # Requires Python 2.6+ and Openssl 1.0+
 #
-import mock
-
 from azurelinuxagent.common.osutil.freebsd import FreeBSDOSUtil
-import azurelinuxagent.common.utils.shellutil as shellutil
 from .test_default import osutil_get_dhcp_pid_should_return_a_list_of_pids
 from tests.tools import *
 
-class TestFreeBSDOSUtil(AgentTestCase):
+
+class TestAlpineOSUtil(AgentTestCase):
     def setUp(self):
         AgentTestCase.setUp(self)
 
@@ -31,94 +29,6 @@ class TestFreeBSDOSUtil(AgentTestCase):
     def test_get_dhcp_pid_should_return_a_list_of_pids(self):
         osutil_get_dhcp_pid_should_return_a_list_of_pids(self, FreeBSDOSUtil())
 
-    def test_empty_proc_net_route(self):
-        route_table = ""
-
-        with patch.object(shellutil, 'run_command', return_value=route_table):
-            # Header line only
-            self.assertEqual(len(FreeBSDOSUtil().read_route_table()), 1)
-
-    def test_no_routes(self):
-        route_table = """Routing tables
-
-Internet:
-Destination        Gateway            Flags     Netif Expire
-"""
-
-        with patch.object(shellutil, 'run_command', return_value=route_table):
-            raw_route_list = FreeBSDOSUtil().read_route_table()
-
-        self.assertEqual(len(FreeBSDOSUtil().get_list_of_routes(raw_route_list)), 0)
-
-    def test_bogus_proc_net_route(self):
-        route_table = """Routing tables
-
-Internet:
-Destination        Gateway            Flags     Netif Expire
-1.1.1              0.0.0
-"""
-
-        with patch.object(shellutil, 'run_command', return_value=route_table):
-            raw_route_list = FreeBSDOSUtil().read_route_table()
-    
-        self.assertEqual(len(FreeBSDOSUtil().get_list_of_routes(raw_route_list)), 0)
-
-    def test_valid_routes(self):
-        route_table = """Routing tables
-
-Internet:
-Destination        Gateway            Flags     Netif Expire
-0.0.0.0            10.145.187.193     UGS         em0       
-10.145.187.192/26  0.0.0.0            US          em0       
-168.63.129.16      10.145.187.193     UH          em0       
-169.254.169.254    10.145.187.193     UHS         em0       
-192.168.43.0       0.0.0.0            US        vtbd0     
-"""
-
-        with patch.object(shellutil, 'run_command', return_value=route_table):
-            raw_route_list = FreeBSDOSUtil().read_route_table()
-
-        self.assertEqual(len(raw_route_list), 6)
-
-        route_list = FreeBSDOSUtil().get_list_of_routes(raw_route_list)
-
-        self.assertEqual(len(route_list), 5)
-        self.assertEqual(route_list[0].gateway_quad(), '10.145.187.193')
-        self.assertEqual(route_list[1].gateway_quad(), '0.0.0.0')
-        self.assertEqual(route_list[1].mask_quad(), '255.255.255.192')
-        self.assertEqual(route_list[2].destination_quad(), '168.63.129.16')
-        self.assertEqual(route_list[1].flags, 1)
-        self.assertEqual(route_list[2].flags, 33)
-        self.assertEqual(route_list[3].flags, 5)
-        self.assertEqual((route_list[3].metric - route_list[4].metric), 1)
-        self.assertEqual(route_list[0].interface, 'em0')
-        self.assertEqual(route_list[4].interface, 'vtbd0')
-
-    def test_get_first_if(self):
-        """
-        Validate that the agent can find the first active non-loopback
-        interface.
-        This test case used to run live, but not all developers have an eth*
-        interface. It is perfectly valid to have a br*, but this test does not
-        account for that.
-        """
-        freebsdosutil = FreeBSDOSUtil()
-
-        with patch.object(freebsdosutil, '_get_net_info', return_value=('em0', '10.0.0.1', 'e5:f0:38:aa:da:52')):
-            ifname, ipaddr = freebsdosutil.get_first_if()
-        
-        self.assertEqual(ifname, 'em0')
-        self.assertEqual(ipaddr, '10.0.0.1')
-
-    def test_no_primary_does_not_throw(self):
-        freebsdosutil = FreeBSDOSUtil()
-
-        with patch.object(freebsdosutil, '_get_net_info', return_value=('em0', '10.0.0.1', 'e5:f0:38:aa:da:52')):
-            try:
-                freebsdosutil.get_first_if()[0]
-            except Exception as e:
-                print(traceback.format_exc())
-                exception = True
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/common/test_cgroupapi.py b/tests/common/test_cgroupapi.py
index 12575860..324104b5 100644
--- a/tests/common/test_cgroupapi.py
+++ b/tests/common/test_cgroupapi.py
@@ -55,41 +55,83 @@ class CGroupsApiTestCase(AgentTestCase):
         self.assertTrue(type(api) == FileSystemCgroupsApi)
 
     def test_is_systemd_should_return_true_when_systemd_manages_current_process(self):
-        path_exists = os.path.exists
-
-        def mock_path_exists(path):
-            if path == "/run/systemd/system/":
-                mock_path_exists.path_tested = True
-                return True
-            return path_exists(path)
-
-        mock_path_exists.path_tested = False
+        fileutil_read_file = fileutil.read_file
+
+        def mock_read_file(filepath, asbin=False, remove_bom=False, encoding='utf-8'):
+            if filepath == "/proc/cgroups":
+                return """
+#subsys_name	hierarchy	num_cgroups	enabled
+cpuset	11	1	1
+cpu	3	77	1
+cpuacct	3	77	1
+blkio	10	70	1
+memory	12	124	1
+devices	9	70	1
+freezer	4	1	1
+net_cls	2	1	1
+perf_event	7	1	1
+net_prio	2	1	1
+hugetlb	8	1	1
+pids	5	76	1
+rdma	6	1	1
+"""
+            if filepath == "/proc/self/cgroup":
+                return """
+12:memory:/system.slice/walinuxagent.service
+11:cpuset:/
+10:blkio:/system.slice/walinuxagent.service
+9:devices:/system.slice/walinuxagent.service
+8:hugetlb:/
+7:perf_event:/
+6:rdma:/
+5:pids:/system.slice/walinuxagent.service
+4:freezer:/
+3:cpu,cpuacct:/system.slice/walinuxagent.service
+2:net_cls,net_prio:/
+1:name=systemd:/system.slice/walinuxagent.service
+0::/system.slice/walinuxagent.service
+"""
+            return fileutil_read_file(filepath, asbin=asbin, remove_bom=remove_bom, encoding=encoding)
 
-        with patch("azurelinuxagent.common.cgroupapi.os.path.exists", mock_path_exists):
+        with patch("azurelinuxagent.common.cgroupapi.fileutil.read_file", mock_read_file):
             is_systemd = CGroupsApi._is_systemd()
 
         self.assertTrue(is_systemd)
 
-        self.assertTrue(mock_path_exists.path_tested, 'The expected path was not tested; the implementation of CGroupsApi._is_systemd() may have changed.')
-
     def test_is_systemd_should_return_false_when_systemd_does_not_manage_current_process(self):
-        path_exists = os.path.exists
-
-        def mock_path_exists(path):
-            if path == "/run/systemd/system/":
-                mock_path_exists.path_tested = True
-                return False
-            return path_exists(path)
-
-        mock_path_exists.path_tested = False
-
-        with patch("azurelinuxagent.common.cgroupapi.os.path.exists", mock_path_exists):
+        fileutil_read_file = fileutil.read_file
+
+        def mock_read_file(filepath, asbin=False, remove_bom=False, encoding='utf-8'):
+            if filepath == "/proc/cgroups":
+                return """
+#subsys_name	hierarchy	num_cgroups	enabled
+cpuset	11	1	1
+cpu	3	77	1
+cpuacct	3	77	1
+blkio	10	70	1
+memory	12	124	1
+devices	9	70	1
+freezer	4	1	1
+net_cls	2	1	1
+perf_event	7	1	1
+net_prio	2	1	1
+hugetlb	8	1	1
+pids	5	76	1
+rdma	6	1	1
+"""
+            if filepath == "/proc/self/cgroup":
+                return """
+3:name=systemd:/
+2:memory:/walinuxagent.service
+1:cpu,cpuacct:/walinuxagent.service
+"""
+            return fileutil_read_file(filepath, asbin=asbin, remove_bom=remove_bom, encoding=encoding)
+
+        with patch("azurelinuxagent.common.cgroupapi.fileutil.read_file", mock_read_file):
             is_systemd = CGroupsApi._is_systemd()
 
         self.assertFalse(is_systemd)
 
-        self.assertTrue(mock_path_exists.path_tested, 'The expected path was not tested; the implementation of CGroupsApi._is_systemd() may have changed.')
-
     def test_foreach_controller_should_execute_operation_on_all_mounted_controllers(self):
         executed_controllers = []
 
@@ -507,18 +549,16 @@ class SystemdCgroupsApiTestCase(AgentTestCase):
 
     @patch('time.sleep', side_effect=lambda _: mock_sleep(0.001))
     def test_start_extension_command_should_use_fallback_option_if_systemd_times_out(self, _):
-        # Systemd has its own internal timeout which is shorter than what we define for extension operation timeout.
-        # When systemd times out, it will write a message to stderr and exit with exit code 1.
-        # In that case, we will internally recognize the failure due to the non-zero exit code, not as a timeout.
+        # Mock systemd timeout and make sure the failure is only attributed to the extension if the command fails
+        # using the fallback option
         original_popen = subprocess.Popen
-        systemd_timeout_command = "echo 'Failed to start transient scope unit: Connection timed out' >&2 && exit 1"
+        success_cmd = "echo 'success'"
 
         def mock_popen(*args, **kwargs):
-            # If trying to invoke systemd, mock what would happen if systemd timed out internally:
-            # write failure to stderr and exit with exit code 1.
+            # Inject a syntax error to the call
             new_args = args
             if "systemd-run" in args[0]:
-                new_args = (systemd_timeout_command,)
+                new_args = (args[0].replace(success_cmd, "sleep 1s"),)    # Inject sleep for timeout
 
             return original_popen(new_args, **kwargs)
 
@@ -526,28 +566,21 @@ class SystemdCgroupsApiTestCase(AgentTestCase):
 
         with tempfile.TemporaryFile(dir=self.tmp_dir, mode="w+b") as stdout:
             with tempfile.TemporaryFile(dir=self.tmp_dir, mode="w+b") as stderr:
-                with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen", side_effect=mock_popen) \
-                        as patch_mock_popen:
-                    extension_cgroups, process_output = SystemdCgroupsApi().start_extension_command(
-                        extension_name="Microsoft.Compute.TestExtension-1.2.3",
-                        command="echo 'success'",
-                        timeout=300,
-                        shell=True,
-                        cwd=self.tmp_dir,
-                        env={},
-                        stdout=stdout,
-                        stderr=stderr)
-
-                    # We expect two calls to Popen, first for the systemd-run call, second for the fallback option
-                    self.assertEquals(2, patch_mock_popen.call_count)
-
-                    first_call_args = patch_mock_popen.mock_calls[0][1][0]
-                    second_call_args = patch_mock_popen.mock_calls[1][1][0]
-                    self.assertIn("systemd-run --unit", first_call_args)
-                    self.assertNotIn("systemd-run --unit", second_call_args)
+                with patch("azurelinuxagent.common.cgroupapi.subprocess.Popen", side_effect=mock_popen):
+                    with patch("azurelinuxagent.common.cgroupapi.SystemdCgroupsApi._is_systemd_failure",
+                               return_value=True):
+                        extension_cgroups, process_output = SystemdCgroupsApi().start_extension_command(
+                            extension_name="Microsoft.Compute.TestExtension-1.2.3",
+                            command="echo 'success'",
+                            timeout=300,
+                            shell=True,
+                            cwd=self.tmp_dir,
+                            env={},
+                            stdout=stdout,
+                            stderr=stderr)
 
-                    self.assertEquals(extension_cgroups, [])
-                    self.assertEquals(expected_output.format("success"), process_output)
+                        self.assertEquals(extension_cgroups, [])
+                        self.assertEquals(expected_output.format("success"), process_output)
 
     @attr('requires_sudo')
     @patch("azurelinuxagent.common.cgroupapi.add_event")
diff --git a/tests/common/test_cgroupstelemetry.py b/tests/common/test_cgroupstelemetry.py
index 34abfb08..7fb6ba82 100644
--- a/tests/common/test_cgroupstelemetry.py
+++ b/tests/common/test_cgroupstelemetry.py
@@ -579,28 +579,21 @@ class TestCGroupsTelemetry(AgentTestCase):
     def test_telemetry_with_tracked_cgroup(self):
         self.assertTrue(i_am_root(), "Test does not run when non-root")
 
-        # This test has some timing issues when systemd is managing cgroups, so we force the file system API
-        # by creating a new instance of the CGroupConfigurator
-        with patch("azurelinuxagent.common.cgroupapi.CGroupsApi._is_systemd", return_value=False):
-            cgroup_configurator_instance = CGroupConfigurator._instance
-            CGroupConfigurator._instance = None
-
-            try:
-                max_num_polls = 30
-                time_to_wait = 3
-                extn_name = "foobar-1.0.0"
-                num_summarization_values = 7
-
-                cgs = make_new_cgroup(extn_name)
-                self.assertEqual(len(cgs), 2)
-
-                ext_handler_properties = ExtHandlerProperties()
-                ext_handler_properties.version = "1.0.0"
-                self.ext_handler = ExtHandler(name='foobar')
-                self.ext_handler.properties = ext_handler_properties
-                self.ext_handler_instance = ExtHandlerInstance(ext_handler=self.ext_handler, protocol=None)
-
-                command = self.create_script("keep_cpu_busy_and_consume_memory_for_5_seconds", '''
+        max_num_polls = 30
+        time_to_wait = 3
+        extn_name = "foobar-1.0.0"
+        num_summarization_values = 7
+
+        cgs = make_new_cgroup(extn_name)
+        self.assertEqual(len(cgs), 2)
+
+        ext_handler_properties = ExtHandlerProperties()
+        ext_handler_properties.version = "1.0.0"
+        self.ext_handler = ExtHandler(name='foobar')
+        self.ext_handler.properties = ext_handler_properties
+        self.ext_handler_instance = ExtHandlerInstance(ext_handler=self.ext_handler, protocol=None)
+
+        command = self.create_script("keep_cpu_busy_and_consume_memory_for_5_seconds", '''
 nohup python -c "import time
 
 for i in range(5):
@@ -610,59 +603,48 @@ for i in range(5):
     print('Test loop')" &
 '''.format(time_to_wait))
 
-                self.log_dir = os.path.join(self.tmp_dir, "log")
-
-                with patch("azurelinuxagent.ga.exthandlers.ExtHandlerInstance.get_base_dir", lambda *_: self.tmp_dir) as \
-                        patch_get_base_dir:
-                    with patch("azurelinuxagent.ga.exthandlers.ExtHandlerInstance.get_log_dir", lambda *_: self.log_dir) as \
-                            patch_get_log_dir:
-                        self.ext_handler_instance.launch_command(command)
-
-                #
-                # If the test is made to run using the systemd API, then the paths of the cgroups need to be checked differently:
-                #
-                #     self.assertEquals(len(CGroupsTelemetry._tracked), 2)
-                #     cpu = os.path.join(BASE_CGROUPS, "cpu", "system.slice", r"foobar_1.0.0_.*\.scope")
-                #     self.assertTrue(any(re.match(cpu, tracked.path) for tracked in CGroupsTelemetry._tracked))
-                #     memory = os.path.join(BASE_CGROUPS, "memory", "system.slice", r"foobar_1.0.0_.*\.scope")
-                #     self.assertTrue(any(re.match(memory, tracked.path) for tracked in CGroupsTelemetry._tracked))
-                #
-                self.assertTrue(CGroupsTelemetry.is_tracked(os.path.join(
-                    BASE_CGROUPS, "cpu", "walinuxagent.extensions", "foobar_1.0.0")))
-                self.assertTrue(CGroupsTelemetry.is_tracked(os.path.join(
-                    BASE_CGROUPS, "memory", "walinuxagent.extensions", "foobar_1.0.0")))
-
-                for i in range(max_num_polls):
-                    CGroupsTelemetry.poll_all_tracked()
-                    time.sleep(0.5)
+        self.log_dir = os.path.join(self.tmp_dir, "log")
 
-                collected_metrics = CGroupsTelemetry.report_all_tracked()
+        with patch("azurelinuxagent.ga.exthandlers.ExtHandlerInstance.get_base_dir", lambda *_: self.tmp_dir) as \
+                patch_get_base_dir:
+            with patch("azurelinuxagent.ga.exthandlers.ExtHandlerInstance.get_log_dir", lambda *_: self.log_dir) as \
+                    patch_get_log_dir:
+                self.ext_handler_instance.launch_command(command)
+
+        self.assertTrue(CGroupsTelemetry.is_tracked(os.path.join(
+            BASE_CGROUPS, "cpu", "walinuxagent.extensions", "foobar_1.0.0")))
+        self.assertTrue(CGroupsTelemetry.is_tracked(os.path.join(
+            BASE_CGROUPS, "memory", "walinuxagent.extensions", "foobar_1.0.0")))
+
+        for i in range(max_num_polls):
+            CGroupsTelemetry.poll_all_tracked()
+            time.sleep(0.5)
+
+        collected_metrics = CGroupsTelemetry.report_all_tracked()
 
-                self.assertIn("memory", collected_metrics[extn_name])
-                self.assertIn("cur_mem", collected_metrics[extn_name]["memory"])
-                self.assertIn("max_mem", collected_metrics[extn_name]["memory"])
-                self.assertEqual(len(collected_metrics[extn_name]["memory"]["cur_mem"]), num_summarization_values)
-                self.assertEqual(len(collected_metrics[extn_name]["memory"]["max_mem"]), num_summarization_values)
-
-                self.assertIsInstance(collected_metrics[extn_name]["memory"]["cur_mem"][5], str)
-                self.assertIsInstance(collected_metrics[extn_name]["memory"]["cur_mem"][6], str)
-                self.assertIsInstance(collected_metrics[extn_name]["memory"]["max_mem"][5], str)
-                self.assertIsInstance(collected_metrics[extn_name]["memory"]["max_mem"][6], str)
-
-                self.assertIn("cpu", collected_metrics[extn_name])
-                self.assertIn("cur_cpu", collected_metrics[extn_name]["cpu"])
-                self.assertEqual(len(collected_metrics[extn_name]["cpu"]["cur_cpu"]), num_summarization_values)
-
-                self.assertIsInstance(collected_metrics[extn_name]["cpu"]["cur_cpu"][5], str)
-                self.assertIsInstance(collected_metrics[extn_name]["cpu"]["cur_cpu"][6], str)
-
-                for i in range(5):
-                    self.assertGreater(collected_metrics[extn_name]["memory"]["cur_mem"][i], 0)
-                    self.assertGreater(collected_metrics[extn_name]["memory"]["max_mem"][i], 0)
-                    self.assertGreaterEqual(collected_metrics[extn_name]["cpu"]["cur_cpu"][i], 0)
-                    # Equal because CPU could be zero for minimum value.
-            finally:
-                CGroupConfigurator._instance = cgroup_configurator_instance
+        self.assertIn("memory", collected_metrics[extn_name])
+        self.assertIn("cur_mem", collected_metrics[extn_name]["memory"])
+        self.assertIn("max_mem", collected_metrics[extn_name]["memory"])
+        self.assertEqual(len(collected_metrics[extn_name]["memory"]["cur_mem"]), num_summarization_values)
+        self.assertEqual(len(collected_metrics[extn_name]["memory"]["max_mem"]), num_summarization_values)
+
+        self.assertIsInstance(collected_metrics[extn_name]["memory"]["cur_mem"][5], str)
+        self.assertIsInstance(collected_metrics[extn_name]["memory"]["cur_mem"][6], str)
+        self.assertIsInstance(collected_metrics[extn_name]["memory"]["max_mem"][5], str)
+        self.assertIsInstance(collected_metrics[extn_name]["memory"]["max_mem"][6], str)
+
+        self.assertIn("cpu", collected_metrics[extn_name])
+        self.assertIn("cur_cpu", collected_metrics[extn_name]["cpu"])
+        self.assertEqual(len(collected_metrics[extn_name]["cpu"]["cur_cpu"]), num_summarization_values)
+
+        self.assertIsInstance(collected_metrics[extn_name]["cpu"]["cur_cpu"][5], str)
+        self.assertIsInstance(collected_metrics[extn_name]["cpu"]["cur_cpu"][6], str)
+
+        for i in range(5):
+            self.assertGreater(collected_metrics[extn_name]["memory"]["cur_mem"][i], 0)
+            self.assertGreater(collected_metrics[extn_name]["memory"]["max_mem"][i], 0)
+            self.assertGreaterEqual(collected_metrics[extn_name]["cpu"]["cur_cpu"][i], 0)
+            # Equal because CPU could be zero for minimum value.
 
 
 class TestMetric(AgentTestCase):
diff --git a/tests/common/test_conf.py b/tests/common/test_conf.py
index b4805d34..55fd5aec 100644
--- a/tests/common/test_conf.py
+++ b/tests/common/test_conf.py
@@ -28,7 +28,8 @@ class TestConf(AgentTestCase):
     # -- These values *MUST* match those from data/test_waagent.conf
     EXPECTED_CONFIGURATION = {
         "Extensions.Enabled": True,
-        "Provisioning.Agent": "auto",
+        "Provisioning.Enabled": True,
+        "Provisioning.UseCloudInit": True,
         "Provisioning.DeleteRootPassword": True,
         "Provisioning.RegenerateSshHostKeyPair": True,
         "Provisioning.SshHostKeyPairType": "rsa",
@@ -105,8 +106,8 @@ class TestConf(AgentTestCase):
     def test_get_fips_enabled(self):
         self.assertTrue(get_fips_enabled(self.conf))
 
-    def test_get_provision_agent(self):
-        self.assertTrue(get_provisioning_agent(self.conf) == 'auto')
+    def test_get_provision_cloudinit(self):
+        self.assertTrue(get_provision_cloudinit(self.conf))
 
     def test_get_configuration(self):
         configuration = conf.get_configuration(self.conf)
diff --git a/tests/daemon/test_daemon.py b/tests/daemon/test_daemon.py
index 4e87e5a0..bce70fe3 100644
--- a/tests/daemon/test_daemon.py
+++ b/tests/daemon/test_daemon.py
@@ -85,10 +85,9 @@ class TestDaemon(AgentTestCase):
             daemon_handler.run()
             self.assertFalse(OPENSSL_FIPS_ENVIRONMENT in os.environ)
 
-    @patch('azurelinuxagent.common.conf.get_provisioning_agent', return_value='waagent')
     @patch('azurelinuxagent.ga.update.UpdateHandler.run_latest')
     @patch('azurelinuxagent.pa.provision.default.ProvisionHandler.run')
-    def test_daemon_agent_enabled(self, patch_run_provision, patch_run_latest, gpa):
+    def test_daemon_agent_enabled(self, patch_run_provision, patch_run_latest):
         """
         Agent should run normally when no disable_agent is found
         """
@@ -105,10 +104,9 @@ class TestDaemon(AgentTestCase):
             self.assertEqual(1, patch_run_provision.call_count)
             self.assertEqual(1, patch_run_latest.call_count)
 
-    @patch('azurelinuxagent.common.conf.get_provisioning_agent', return_value='waagent')
     @patch('azurelinuxagent.ga.update.UpdateHandler.run_latest', side_effect=AgentTestCase.fail)
     @patch('azurelinuxagent.pa.provision.default.ProvisionHandler.run', side_effect=ProvisionHandler.write_agent_disabled)
-    def test_daemon_agent_disabled(self, _, patch_run_latest, gpa):
+    def test_daemon_agent_disabled(self, _, patch_run_latest):
         """
         Agent should provision, then sleep forever when disable_agent is found
         """
diff --git a/tests/data/test_waagent.conf b/tests/data/test_waagent.conf
index 3e16c45a..049c8e2b 100644
--- a/tests/data/test_waagent.conf
+++ b/tests/data/test_waagent.conf
@@ -8,11 +8,14 @@ FauxKey1= Value1
 FauxKey2=Value2 Value2
 FauxKey3=delalloc,rw,noatime,nobarrier,users,mode=777
 
+# Enable instance creation
+Provisioning.Enabled=y
+
 # Enable extension handling
 Extensions.Enabled=y
 
-# Specify provisioning agent.
-Provisioning.Agent=auto
+# Rely on cloud-init to provision
+Provisioning.UseCloudInit=y
 
 # Password authentication for root account will be unavailable.
 Provisioning.DeleteRootPassword=y
diff --git a/tests/pa/test_provision.py b/tests/pa/test_provision.py
index 54c2f8c8..27f75266 100644
--- a/tests/pa/test_provision.py
+++ b/tests/pa/test_provision.py
@@ -19,7 +19,6 @@ from azurelinuxagent.common.exception import ProvisionError
 from azurelinuxagent.common.osutil.default import DefaultOSUtil
 from azurelinuxagent.common.protocol import OVF_FILE_NAME
 from azurelinuxagent.pa.provision import get_provision_handler
-from azurelinuxagent.pa.provision.cloudinit import CloudInitProvisionHandler
 from azurelinuxagent.pa.provision.default import ProvisionHandler
 from tests.tools import *
 
@@ -114,11 +113,10 @@ class TestProvision(AgentTestCase):
         self.assertEqual(1, deprovision_handler.run_changed_unique_id.call_count)
 
     @distros()
-    @patch('azurelinuxagent.common.conf.get_provisioning_agent', return_value='waagent')
     def test_provision_telemetry_pga_false(self,
                                            distro_name,
                                            distro_version,
-                                           distro_full_name, _):
+                                           distro_full_name):
         """
         ProvisionGuestAgent flag is 'false'
         """
@@ -130,11 +128,10 @@ class TestProvision(AgentTestCase):
                              True)
 
     @distros()
-    @patch('azurelinuxagent.common.conf.get_provisioning_agent', return_value='waagent')
     def test_provision_telemetry_pga_true(self,
                                           distro_name,
                                           distro_version,
-                                          distro_full_name, _):
+                                          distro_full_name):
         """
         ProvisionGuestAgent flag is 'true'
         """
@@ -146,11 +143,10 @@ class TestProvision(AgentTestCase):
                              True)
 
     @distros()
-    @patch('azurelinuxagent.common.conf.get_provisioning_agent', return_value='waagent')
     def test_provision_telemetry_pga_empty(self,
                                            distro_name,
                                            distro_version,
-                                           distro_full_name, _):
+                                           distro_full_name):
         """
         ProvisionGuestAgent flag is ''
         """
@@ -162,11 +158,10 @@ class TestProvision(AgentTestCase):
                              False)
 
     @distros()
-    @patch('azurelinuxagent.common.conf.get_provisioning_agent', return_value='waagent')
     def test_provision_telemetry_pga_bad(self,
                                          distro_name,
                                          distro_version,
-                                         distro_full_name, _):
+                                         distro_full_name):
         """
         ProvisionGuestAgent flag is 'bad data'
         """
@@ -243,12 +238,11 @@ class TestProvision(AgentTestCase):
     @patch(
         'azurelinuxagent.common.osutil.default.DefaultOSUtil.get_instance_id',
         return_value='B9F3C233-9913-9F42-8EB3-BA656DF32502')
-    @patch('azurelinuxagent.common.conf.get_provisioning_agent', return_value='waagent')
     def test_provision_telemetry_fail(self,
                                       mock_util,
                                       distro_name,
                                       distro_version,
-                                      distro_full_name, _):
+                                      distro_full_name):
         """
         Assert that the agent issues one telemetry message as part of a
         failed provisioning.
@@ -317,60 +311,6 @@ class TestProvision(AgentTestCase):
         ph.handle_provision_guest_agent(provision_guest_agent='TRUE')
         self.assertEqual(3, patch_write_agent_disabled.call_count)
 
-    @patch(
-        'azurelinuxagent.common.conf.get_provisioning_agent',
-        return_value='auto'
-    )
-    @patch(
-        'azurelinuxagent.pa.provision.factory.cloud_init_is_enabled',
-        return_value=False
-    )
-    def test_get_provision_handler_config_auto_no_cloudinit(
-            self,
-            patch_cloud_init_is_enabled,
-            patch_get_provisioning_agent):
-        provisioning_handler = get_provision_handler()
-        self.assertIsInstance(provisioning_handler, ProvisionHandler, 'Auto provisioning handler should be waagent if cloud-init is not enabled')
-
-    @patch(
-        'azurelinuxagent.common.conf.get_provisioning_agent',
-        return_value='waagent'
-    )
-    @patch(
-        'azurelinuxagent.pa.provision.factory.cloud_init_is_enabled',
-        return_value=True
-    )
-    def test_get_provision_handler_config_waagent(
-            self,
-            patch_cloud_init_is_enabled,
-            patch_get_provisioning_agent):
-        provisioning_handler = get_provision_handler()
-        self.assertIsInstance(provisioning_handler, ProvisionHandler, 'Provisioning handler should be waagent if agent is set to waagent')
-
-    @patch(
-        'azurelinuxagent.common.conf.get_provisioning_agent',
-        return_value='auto'
-    )
-    @patch(
-        'azurelinuxagent.pa.provision.factory.cloud_init_is_enabled',
-        return_value=True
-    )
-    def test_get_provision_handler_config_auto_cloudinit(
-            self,
-            patch_cloud_init_is_enabled,
-            patch_get_provisioning_agent):
-        provisioning_handler = get_provision_handler()
-        self.assertIsInstance(provisioning_handler, CloudInitProvisionHandler, 'Auto provisioning handler should be cloud-init if cloud-init is enabled')
-
-    @patch(
-        'azurelinuxagent.common.conf.get_provisioning_agent',
-        return_value='cloud-init'
-    )
-    def test_get_provision_handler_config_cloudinit(
-            self,
-            patch_get_provisioning_agent):
-        provisioning_handler = get_provision_handler()
-        self.assertIsInstance(provisioning_handler, CloudInitProvisionHandler, 'Provisioning handler should be cloud-init if agent is set to cloud-init')
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/test_agent.py b/tests/test_agent.py
index d0122641..7d8eee2d 100644
--- a/tests/test_agent.py
+++ b/tests/test_agent.py
@@ -52,16 +52,17 @@ OS.SshDir = /notareal/path
 OS.SudoersDir = /etc/sudoers.d
 OS.UpdateRdmaDriver = False
 Pid.File = /var/run/waagent.pid
-Provisioning.Agent = auto
 Provisioning.AllowResetSysUser = False
 Provisioning.DecodeCustomData = False
 Provisioning.DeleteRootPassword = True
+Provisioning.Enabled = True
 Provisioning.ExecuteCustomData = False
 Provisioning.MonitorHostName = True
 Provisioning.PasswordCryptId = 6
 Provisioning.PasswordCryptSaltLength = 10
 Provisioning.RegenerateSshHostKeyPair = True
 Provisioning.SshHostKeyPairType = rsa
+Provisioning.UseCloudInit = True
 ResourceDisk.EnableSwap = False
 ResourceDisk.EnableSwapEncryption = False
 ResourceDisk.Filesystem = ext4