Esempio n. 1
0
 def test_get_data_vmware_customization_disabled(self):
     """When cloud-init workflow for vmware is enabled via sys_cfg log a
     message.
     """
     paths = Paths({'cloud_dir': self.tdir})
     ds = self.datasource(
         sys_cfg={'disable_vmware_customization': False}, distro={},
         paths=paths)
     conf_file = self.tmp_path('test-cust', self.tdir)
     conf_content = dedent("""\
         [CUSTOM-SCRIPT]
         SCRIPT-NAME = test-script
         [MISC]
         MARKER-ID = 12345345
         """)
     util.write_file(conf_file, conf_content)
     with self.assertRaises(CustomScriptNotFound) as context:
         wrap_and_call(
             'cloudinit.sources.DataSourceOVF',
             {'util.read_dmi_data': 'vmware',
              'util.del_dir': True,
              'search_file': self.tdir,
              'wait_for_imc_cfg_file': conf_file,
              'get_nics_to_enable': ''},
             ds.get_data)
     customscript = self.tmp_path('test-script', self.tdir)
     self.assertIn('Script %s not found!!' % customscript,
                   str(context.exception))
Esempio n. 2
0
 def test_add_assertions_adds_assertions_as_dict(self, m_subp):
     """When provided with a dict, add_assertions adds all assertions."""
     self.assertEqual(
         ASSERTIONS_FILE, '/var/lib/cloud/instance/snapd.assertions')
     assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
     assertions = {'00': SYSTEM_USER_ASSERTION, '01': ACCOUNT_ASSERTION}
     wrap_and_call(
         'cloudinit.config.cc_snap',
         {'ASSERTIONS_FILE': {'new': assert_file}},
         add_assertions, assertions)
     self.assertIn(
         'Importing user-provided snap assertions', self.logs.getvalue())
     self.assertIn(
         "DEBUG: Snap acking: ['type: system-user', 'authority-id: Lqv",
         self.logs.getvalue())
     self.assertIn(
         "DEBUG: Snap acking: ['type: account-key', 'authority-id: canonic",
         self.logs.getvalue())
     self.assertEqual(
         [mock.call(['snap', 'ack', assert_file], capture=True)],
         m_subp.call_args_list)
     compare_file = self.tmp_path('comparison', dir=self.tmp)
     combined = '\n'.join(assertions.values())
     util.write_file(compare_file, combined.encode('utf-8'))
     self.assertEqual(
         util.load_file(compare_file), util.load_file(assert_file))
Esempio n. 3
0
 def test_get_data_vmware_customization_disabled(self):
     """When cloud-init workflow for vmware is enabled via sys_cfg log a
     message.
     """
     paths = Paths({'cloud_dir': self.tdir})
     ds = self.datasource(sys_cfg={'disable_vmware_customization': False},
                          distro={},
                          paths=paths)
     conf_file = self.tmp_path('test-cust', self.tdir)
     conf_content = dedent("""\
         [CUSTOM-SCRIPT]
         SCRIPT-NAME = test-script
         [MISC]
         MARKER-ID = 12345345
         """)
     util.write_file(conf_file, conf_content)
     with mock.patch(MPATH + 'get_tools_config', return_value='true'):
         with self.assertRaises(CustomScriptNotFound) as context:
             wrap_and_call(
                 'cloudinit.sources.DataSourceOVF', {
                     'dmi.read_dmi_data': 'vmware',
                     'util.del_dir': True,
                     'search_file': self.tdir,
                     'wait_for_imc_cfg_file': conf_file,
                     'get_nics_to_enable': ''
                 }, ds.get_data)
     customscript = self.tmp_path('test-script', self.tdir)
     self.assertIn('Script %s not found!!' % customscript,
                   str(context.exception))
Esempio n. 4
0
    def test_get_data_cloudinit_metadata_not_found(self):
        """Test metadata file can't be found.
        """
        paths = Paths({'cloud_dir': self.tdir})
        ds = self.datasource(sys_cfg={'disable_vmware_customization': True},
                             distro={},
                             paths=paths)
        # Prepare the conf file
        conf_file = self.tmp_path('test-cust', self.tdir)
        conf_content = dedent("""\
            [CLOUDINIT]
            METADATA = test-meta
            """)
        util.write_file(conf_file, conf_content)
        # Don't prepare the meta data file

        with mock.patch(MPATH + 'set_customization_status',
                        return_value=('msg', b'')):
            with self.assertRaises(FileNotFoundError) as context:
                wrap_and_call(
                    'cloudinit.sources.DataSourceOVF', {
                        'dmi.read_dmi_data': 'vmware',
                        'util.del_dir': True,
                        'search_file': self.tdir,
                        'wait_for_imc_cfg_file': conf_file,
                        'get_nics_to_enable': ''
                    }, ds.get_data)

        self.assertIn('is not found', str(context.exception))
Esempio n. 5
0
    def test_get_data_cust_script_disabled(self):
        """If custom script is disabled by VMware tools configuration,
        raise a RuntimeError.
        """
        paths = Paths({'cloud_dir': self.tdir})
        ds = self.datasource(sys_cfg={'disable_vmware_customization': False},
                             distro={},
                             paths=paths)
        # Prepare the conf file
        conf_file = self.tmp_path('test-cust', self.tdir)
        conf_content = dedent("""\
            [CUSTOM-SCRIPT]
            SCRIPT-NAME = test-script
            [MISC]
            MARKER-ID = 12345346
            """)
        util.write_file(conf_file, conf_content)
        # Prepare the custom sript
        customscript = self.tmp_path('test-script', self.tdir)
        util.write_file(customscript, "This is the post cust script")

        with mock.patch(MPATH + 'get_tools_config', return_value='invalid'):
            with mock.patch(MPATH + 'set_customization_status',
                            return_value=('msg', b'')):
                with self.assertRaises(RuntimeError) as context:
                    wrap_and_call(
                        'cloudinit.sources.DataSourceOVF', {
                            'dmi.read_dmi_data': 'vmware',
                            'util.del_dir': True,
                            'search_file': self.tdir,
                            'wait_for_imc_cfg_file': conf_file,
                            'get_nics_to_enable': ''
                        }, ds.get_data)
        self.assertIn('Custom script is disabled by VM Administrator',
                      str(context.exception))
Esempio n. 6
0
 def test_handler_installs_client_and_creates_config_file(self):
     """Write landscape client.conf and install landscape-client."""
     mycloud = get_cloud('ubuntu')
     cfg = {'landscape': {'client': {}}}
     expected = {
         'client': {
             'log_level': 'info',
             'url': 'https://landscape.canonical.com/message-system',
             'ping_url': 'http://landscape.canonical.com/ping',
             'data_path': '/var/lib/landscape/client'
         }
     }
     mycloud.distro = mock.MagicMock()
     wrap_and_call(
         'cloudinit.config.cc_landscape', {
             'LSC_CLIENT_CFG_FILE': {
                 'new': self.conf
             },
             'LS_DEFAULT_FILE': {
                 'new': self.default_file
             }
         }, cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
     self.assertEqual([mock.call('landscape-client')],
                      mycloud.distro.install_packages.call_args)
     self.assertEqual(expected, dict(ConfigObj(self.conf)))
     self.assertIn('Wrote landscape config file to {0}'.format(self.conf),
                   self.logs.getvalue())
     default_content = util.load_file(self.default_file)
     self.assertEqual('RUN=1\n', default_content)
Esempio n. 7
0
 def test_add_assertions_adds_assertions_as_dict(self, m_subp):
     """When provided with a dict, add_assertions adds all assertions."""
     self.assertEqual(
         ASSERTIONS_FILE, '/var/lib/cloud/instance/snapd.assertions')
     assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
     assertions = {'00': SYSTEM_USER_ASSERTION, '01': ACCOUNT_ASSERTION}
     wrap_and_call(
         'cloudinit.config.cc_snap',
         {'ASSERTIONS_FILE': {'new': assert_file}},
         add_assertions, assertions)
     self.assertIn(
         'Importing user-provided snap assertions', self.logs.getvalue())
     self.assertIn(
         "DEBUG: Snap acking: ['type: system-user', 'authority-id: Lqv",
         self.logs.getvalue())
     self.assertIn(
         "DEBUG: Snap acking: ['type: account-key', 'authority-id: canonic",
         self.logs.getvalue())
     self.assertEqual(
         [mock.call(['snap', 'ack', assert_file], capture=True)],
         m_subp.call_args_list)
     compare_file = self.tmp_path('comparison', dir=self.tmp)
     combined = '\n'.join(assertions.values())
     util.write_file(compare_file, combined.encode('utf-8'))
     self.assertEqual(
         util.load_file(compare_file), util.load_file(assert_file))
Esempio n. 8
0
 def test_status_main(self):
     '''status.main can be run as a standalone script.'''
     write_json(self.status_file,
                {'v1': {
                    'init': {
                        'start': 1,
                        'finished': None
                    }
                }})
     with self.assertRaises(SystemExit) as context_manager:
         with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
             wrap_and_call(
                 'cloudinit.cmd.status', {
                     'sys.argv': {
                         'new': ['status']
                     },
                     'sys.exit': {
                         'side_effect': self.sys_exit
                     },
                     '_is_cloudinit_disabled': (False, ''),
                     'Init': {
                         'side_effect': self.init_class
                     }
                 }, status.main)
     self.assertEqual(0, context_manager.exception.code)
     self.assertEqual('status: running\n', m_stdout.getvalue())
Esempio n. 9
0
    def test_handle_warns_on_undiscoverable_root_path_in_commandline(self):
        """handle noops when the root path is not found on the commandline."""
        cfg = {'resize_rootfs': True}
        exists_mock_path = 'cloudinit.config.cc_resizefs.os.path.exists'

        def fake_mount_info(path, log):
            self.assertEqual('/', path)
            self.assertEqual(LOG, log)
            return ('/dev/root', 'ext4', '/')

        with mock.patch(exists_mock_path) as m_exists:
            m_exists.return_value = False
            wrap_and_call('cloudinit.config.cc_resizefs.util', {
                'is_container': {
                    'return_value': False
                },
                'get_mount_info': {
                    'side_effect': fake_mount_info
                },
                'get_cmdline': {
                    'return_value': 'BOOT_IMAGE=/vmlinuz.efi'
                }
            },
                          handle,
                          'cc_resizefs',
                          cfg,
                          _cloud=None,
                          log=LOG,
                          args=[])
        logs = self.logs.getvalue()
        self.assertIn("WARNING: Unable to find device '/dev/root'", logs)
Esempio n. 10
0
    def test_collect_logs_includes_optional_userdata(self, m_getuid):
        """collect-logs include userdata when --include-userdata is set."""
        m_getuid.return_value = 0
        log1 = self.tmp_path('cloud-init.log', self.new_root)
        write_file(log1, 'cloud-init-log')
        log2 = self.tmp_path('cloud-init-output.log', self.new_root)
        write_file(log2, 'cloud-init-output-log')
        userdata = self.tmp_path('user-data.txt', self.new_root)
        write_file(userdata, 'user-data')
        ensure_dir(self.run_dir)
        write_file(self.tmp_path('results.json', self.run_dir), 'results')
        write_file(self.tmp_path(INSTANCE_JSON_SENSITIVE_FILE, self.run_dir),
                   'sensitive')
        output_tarfile = self.tmp_path('logs.tgz')

        date = datetime.utcnow().date().strftime('%Y-%m-%d')
        date_logdir = 'cloud-init-logs-{0}'.format(date)

        version_out = '/usr/bin/cloud-init 18.2fake\n'
        expected_subp = {
            ('dpkg-query', '--show', "-f=${Version}\n", 'cloud-init'):
                '0.7fake',
            ('cloud-init', '--version'): version_out,
            ('dmesg',): 'dmesg-out\n',
            ('journalctl', '--boot=0', '-o', 'short-precise'): 'journal-out\n',
            ('tar', 'czvf', output_tarfile, date_logdir): ''
        }

        def fake_subp(cmd):
            cmd_tuple = tuple(cmd)
            if cmd_tuple not in expected_subp:
                raise AssertionError(
                    'Unexpected command provided to subp: {0}'.format(cmd))
            if cmd == ['tar', 'czvf', output_tarfile, date_logdir]:
                subp(cmd)  # Pass through tar cmd so we can check output
            return expected_subp[cmd_tuple], ''

        fake_stderr = mock.MagicMock()

        wrap_and_call(
            'cloudinit.cmd.devel.logs',
            {'subp': {'side_effect': fake_subp},
             'sys.stderr': {'new': fake_stderr},
             'CLOUDINIT_LOGS': {'new': [log1, log2]},
             'CLOUDINIT_RUN_DIR': {'new': self.run_dir},
             'USER_DATA_FILE': {'new': userdata}},
            logs.collect_logs, output_tarfile, include_userdata=True)
        # unpack the tarfile and check file contents
        subp(['tar', 'zxvf', output_tarfile, '-C', self.new_root])
        out_logdir = self.tmp_path(date_logdir, self.new_root)
        self.assertEqual(
            'user-data',
            load_file(os.path.join(out_logdir, 'user-data.txt')))
        self.assertEqual(
            'sensitive',
            load_file(os.path.join(out_logdir, 'run', 'cloud-init',
                                   INSTANCE_JSON_SENSITIVE_FILE)))
        fake_stderr.write.assert_any_call('Wrote %s\n' % output_tarfile)
Esempio n. 11
0
 def test_handler_restarts_landscape_client(self, m_util):
     """handler restarts lansdscape-client after install."""
     mycloud = self._get_cloud('ubuntu')
     cfg = {'landscape': {'client': {}}}
     wrap_and_call(
         'cloudinit.config.cc_landscape',
         {'LSC_CLIENT_CFG_FILE': {'new': self.conf}},
         cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
     self.assertEqual(
         [mock.call(['service', 'landscape-client', 'restart'])],
         m_util.subp.call_args_list)
 def test_maybe_get_writable_device_path_raises_oserror(self):
     """When unexpected OSError is raises by os.stat it is reraised."""
     info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
     with self.assertRaises(OSError) as context_manager:
         wrap_and_call(
             'cloudinit.config.cc_resizefs',
             {'util.is_container': {'return_value': True},
              'os.stat': {'side_effect': OSError('Something unexpected')}},
             maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
     self.assertEqual(
         'Something unexpected', str(context_manager.exception))
 def test_maybe_get_writable_device_path_raises_oserror(self):
     """When unexpected OSError is raises by os.stat it is reraised."""
     info = 'dev=/I/dont/exist mnt_point=/ path=/dev/none'
     with self.assertRaises(OSError) as context_manager:
         wrap_and_call(
             'cloudinit.config.cc_resizefs',
             {'util.is_container': {'return_value': True},
              'os.stat': {'side_effect': OSError('Something unexpected')}},
             maybe_get_writable_device_path, '/I/dont/exist', info, LOG)
     self.assertEqual(
         'Something unexpected', str(context_manager.exception))
Esempio n. 14
0
    def test_collect_logs_includes_optional_userdata(self):
        """collect-logs include userdata when --include-userdata is set."""
        log1 = self.tmp_path('cloud-init.log', self.new_root)
        write_file(log1, 'cloud-init-log')
        log2 = self.tmp_path('cloud-init-output.log', self.new_root)
        write_file(log2, 'cloud-init-output-log')
        userdata = self.tmp_path('user-data.txt', self.new_root)
        write_file(userdata, 'user-data')
        ensure_dir(self.run_dir)
        write_file(self.tmp_path('results.json', self.run_dir), 'results')
        output_tarfile = self.tmp_path('logs.tgz')

        date = datetime.utcnow().date().strftime('%Y-%m-%d')
        date_logdir = 'cloud-init-logs-{0}'.format(date)

        expected_subp = {
            ('dpkg-query', '--show', "-f=${Version}\n", 'cloud-init'):
            '0.7fake',
            ('dmesg', ): 'dmesg-out\n',
            ('journalctl', '-o', 'short-precise'): 'journal-out\n',
            ('tar', 'czvf', output_tarfile, date_logdir): ''
        }

        def fake_subp(cmd):
            cmd_tuple = tuple(cmd)
            if cmd_tuple not in expected_subp:
                raise AssertionError(
                    'Unexpected command provided to subp: {0}'.format(cmd))
            if cmd == ['tar', 'czvf', output_tarfile, date_logdir]:
                subp(cmd)  # Pass through tar cmd so we can check output
            return expected_subp[cmd_tuple], ''

        wrap_and_call('cloudinit.cmd.devel.logs', {
            'subp': {
                'side_effect': fake_subp
            },
            'CLOUDINIT_LOGS': {
                'new': [log1, log2]
            },
            'CLOUDINIT_RUN_DIR': {
                'new': self.run_dir
            },
            'USER_DATA_FILE': {
                'new': userdata
            }
        },
                      logs.collect_logs,
                      output_tarfile,
                      include_userdata=True)
        # unpack the tarfile and check file contents
        subp(['tar', 'zxvf', output_tarfile, '-C', self.new_root])
        out_logdir = self.tmp_path(date_logdir, self.new_root)
        self.assertEqual('user-data',
                         load_file(os.path.join(out_logdir, 'user-data.txt')))
Esempio n. 15
0
 def test_handle_validates_schema(self, m_subp):
     """Any provided configuration is runs validate_cloudconfig_schema."""
     assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
     cfg = {'snap': {'invalid': ''}}  # Generates schema warning
     wrap_and_call(
         'cloudinit.config.cc_snap',
         {'ASSERTIONS_FILE': {'new': assert_file}},
         handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None)
     self.assertEqual(
         "WARNING: Invalid config:\nsnap: Additional properties are not"
         " allowed ('invalid' was unexpected)\n",
         self.logs.getvalue())
Esempio n. 16
0
 def test_handle_validates_schema(self, m_subp):
     """Any provided configuration is runs validate_cloudconfig_schema."""
     assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
     cfg = {'snap': {'invalid': ''}}  # Generates schema warning
     wrap_and_call(
         'cloudinit.config.cc_snap',
         {'ASSERTIONS_FILE': {'new': assert_file}},
         handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None)
     self.assertEqual(
         "WARNING: Invalid config:\nsnap: Additional properties are not"
         " allowed ('invalid' was unexpected)\n",
         self.logs.getvalue())
Esempio n. 17
0
    def test_status_main(self):
        '''clean.main can be run as a standalone script.'''
        write_file(self.log1, 'cloud-init-log')
        with self.assertRaises(SystemExit) as context_manager:
            wrap_and_call(
                'cloudinit.cmd.clean',
                {'Init': {'side_effect': self.init_class},
                 'sys.argv': {'new': ['clean', '--logs']}},
                clean.main)

        self.assertEqual(0, context_manager.exception.code)
        self.assertFalse(
            os.path.exists(self.log1), 'Unexpected log {0}'.format(self.log1))
Esempio n. 18
0
    def test_status_main(self):
        '''clean.main can be run as a standalone script.'''
        write_file(self.log1, 'cloud-init-log')
        with self.assertRaises(SystemExit) as context_manager:
            wrap_and_call(
                'cloudinit.cmd.clean',
                {'Init': {'side_effect': self.init_class},
                 'sys.exit': {'side_effect': self.sys_exit},
                 'sys.argv': {'new': ['clean', '--logs']}},
                clean.main)

        self.assertEqual(0, context_manager.exception.code)
        self.assertFalse(
            os.path.exists(self.log1), 'Unexpected log {0}'.format(self.log1))
Esempio n. 19
0
 def test_handle_adds_assertions(self, m_subp):
     """Any configured snap assertions are provided to add_assertions."""
     assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
     compare_file = self.tmp_path('comparison', dir=self.tmp)
     cfg = {
         'snap': {'assertions': [SYSTEM_USER_ASSERTION, ACCOUNT_ASSERTION]}}
     wrap_and_call(
         'cloudinit.config.cc_snap',
         {'ASSERTIONS_FILE': {'new': assert_file}},
         handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None)
     content = '\n'.join(cfg['snap']['assertions'])
     util.write_file(compare_file, content.encode('utf-8'))
     self.assertEqual(
         util.load_file(compare_file), util.load_file(assert_file))
Esempio n. 20
0
 def test_handle_adds_assertions(self, m_subp):
     """Any configured snap assertions are provided to add_assertions."""
     assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
     compare_file = self.tmp_path('comparison', dir=self.tmp)
     cfg = {
         'snap': {'assertions': [SYSTEM_USER_ASSERTION, ACCOUNT_ASSERTION]}}
     wrap_and_call(
         'cloudinit.config.cc_snap',
         {'ASSERTIONS_FILE': {'new': assert_file}},
         handle, 'snap', cfg=cfg, cloud=None, log=self.logger, args=None)
     content = '\n'.join(cfg['snap']['assertions'])
     util.write_file(compare_file, content.encode('utf-8'))
     self.assertEqual(
         util.load_file(compare_file), util.load_file(assert_file))
Esempio n. 21
0
 def test_get_data_no_vmware_customization_disabled(self):
     """When cloud-init workflow for vmware is disabled via sys_cfg and
     no meta data provided, log a message.
     """
     paths = Paths({'cloud_dir': self.tdir})
     ds = self.datasource(sys_cfg={'disable_vmware_customization': True},
                          distro={},
                          paths=paths)
     conf_file = self.tmp_path('test-cust', self.tdir)
     conf_content = dedent("""\
         [CUSTOM-SCRIPT]
         SCRIPT-NAME = test-script
         [MISC]
         MARKER-ID = 12345345
         """)
     util.write_file(conf_file, conf_content)
     retcode = wrap_and_call(
         'cloudinit.sources.DataSourceOVF', {
             'dmi.read_dmi_data': 'vmware',
             'transport_iso9660': NOT_FOUND,
             'transport_vmware_guestinfo': NOT_FOUND,
             'util.del_dir': True,
             'search_file': self.tdir,
             'wait_for_imc_cfg_file': conf_file
         }, ds.get_data)
     self.assertFalse(retcode, 'Expected False return from ds.get_data')
     self.assertIn('DEBUG: Customization for VMware platform is disabled.',
                   self.logs.getvalue())
Esempio n. 22
0
    def test_status_returns_disabled_long_on_presence_of_disable_file(self):
        '''When cloudinit is disabled, return disabled reason.'''

        checked_files = []

        def fakeexists(filepath):
            checked_files.append(filepath)
            status_file = os.path.join(self.paths.run_dir, 'status.json')
            return bool(not filepath == status_file)

        cmdargs = myargs(long=True, wait=False)
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
            retcode = wrap_and_call(
                'cloudinit.cmd.status',
                {'os.path.exists': {'side_effect': fakeexists},
                 '_is_cloudinit_disabled': (True, 'disabled for some reason'),
                 'Init': {'side_effect': self.init_class}},
                status.handle_status_args, 'ignored', cmdargs)
        self.assertEqual(0, retcode)
        self.assertEqual(
            [os.path.join(self.paths.run_dir, 'status.json')],
            checked_files)
        expected = dedent('''\
            status: disabled
            detail:
            disabled for some reason
        ''')
        self.assertEqual(expected, m_stdout.getvalue())
Esempio n. 23
0
 def test_cmdline_overrides_confd_runtime_and_defaults(self):
     builtin = {'key1': 'value0', 'key3': 'other2'}
     conf_d = {'key1': 'value1', 'key2': 'other1'}
     cmdline = {'key3': 'other3', 'key2': 'other2'}
     runtime = {'key3': 'runtime3'}
     ret = helpers.wrap_and_call(
         'cloudinit.stages', {
             'util.read_conf_with_confd': {
                 'return_value': conf_d
             },
             'util.get_builtin_cfg': {
                 'return_value': builtin
             },
             'read_runtime_config': {
                 'return_value': runtime
             },
             'util.read_conf_from_cmdline': {
                 'return_value': cmdline
             }
         }, stages.fetch_base_config)
     self.assertEqual(ret, {
         'key1': 'value1',
         'key2': 'other2',
         'key3': 'other3'
     })
Esempio n. 24
0
 def test_main_init_run_net_stops_on_file_no_net(self):
     """When no-net file is present, main_init does not process modules."""
     stop_file = os.path.join(self.cloud_dir, 'data', 'no-net')  # stop file
     write_file(stop_file, '')
     cmdargs = myargs(
         debug=False, files=None, force=False, local=False, reporter=None,
         subcommand='init')
     (_item1, item2) = wrap_and_call(
         'cloudinit.cmd.main',
         {'util.close_stdin': True,
          'netinfo.debug_info': 'my net debug info',
          'util.fixup_output': ('outfmt', 'errfmt')},
         main.main_init, 'init', cmdargs)
     # We should not run write_files module
     self.assertFalse(
         os.path.exists(os.path.join(self.new_root, 'etc/blah.ini')),
         'Unexpected run of write_files module produced blah.ini')
     self.assertEqual([], item2)
     # Instancify is called
     instance_id_path = 'var/lib/cloud/data/instance-id'
     self.assertFalse(
         os.path.exists(os.path.join(self.new_root, instance_id_path)),
         'Unexpected call to datasource.instancify produced instance-id')
     expected_logs = [
         "Exiting. stop file ['{stop_file}'] existed\n".format(
             stop_file=stop_file),
         'my net debug info'  # netinfo.debug_info
     ]
     for log in expected_logs:
         self.assertIn(log, self.stderr.getvalue())
Esempio n. 25
0
 def test_main_init_run_net_runs_modules(self):
     """Modules like write_files are run in 'net' mode."""
     cmdargs = myargs(
         debug=False, files=None, force=False, local=False, reporter=None,
         subcommand='init')
     (_item1, item2) = wrap_and_call(
         'cloudinit.cmd.main',
         {'util.close_stdin': True,
          'netinfo.debug_info': 'my net debug info',
          'util.fixup_output': ('outfmt', 'errfmt')},
         main.main_init, 'init', cmdargs)
     self.assertEqual([], item2)
     # Instancify is called
     instance_id_path = 'var/lib/cloud/data/instance-id'
     self.assertEqual(
         'iid-datasource-none\n',
         os.path.join(load_file(
             os.path.join(self.new_root, instance_id_path))))
     # modules are run (including write_files)
     self.assertEqual(
         'blah', load_file(os.path.join(self.new_root, 'etc/blah.ini')))
     expected_logs = [
         'network config is disabled by fallback',  # apply_network_config
         'my net debug info',  # netinfo.debug_info
         'no previous run detected'
     ]
     for log in expected_logs:
         self.assertIn(log, self.stderr.getvalue())
Esempio n. 26
0
 def test_main_init_run_net_stops_on_file_no_net(self):
     """When no-net file is present, main_init does not process modules."""
     stop_file = os.path.join(self.cloud_dir, 'data', 'no-net')  # stop file
     write_file(stop_file, '')
     cmdargs = myargs(debug=False,
                      files=None,
                      force=False,
                      local=False,
                      reporter=None,
                      subcommand='init')
     (_item1, item2) = wrap_and_call(
         'cloudinit.cmd.main', {
             'util.close_stdin': True,
             'netinfo.debug_info': 'my net debug info',
             'util.fixup_output': ('outfmt', 'errfmt')
         }, main.main_init, 'init', cmdargs)
     # We should not run write_files module
     self.assertFalse(
         os.path.exists(os.path.join(self.new_root, 'etc/blah.ini')),
         'Unexpected run of write_files module produced blah.ini')
     self.assertEqual([], item2)
     # Instancify is called
     instance_id_path = 'var/lib/cloud/data/instance-id'
     self.assertFalse(
         os.path.exists(os.path.join(self.new_root, instance_id_path)),
         'Unexpected call to datasource.instancify produced instance-id')
     expected_logs = [
         "Exiting. stop file ['{stop_file}'] existed\n".format(
             stop_file=stop_file),
         'my net debug info'  # netinfo.debug_info
     ]
     for log in expected_logs:
         self.assertIn(log, self.stderr.getvalue())
Esempio n. 27
0
 def test_maybe_get_writable_device_path_returns_cmdline_root(self):
     """When root device is UUID in kernel commandline, update devpath."""
     # XXX Long-term we want to use FilesystemMocking test to avoid
     # touching os.stat.
     FakeStat = namedtuple(
         'FakeStat', ['st_mode', 'st_size', 'st_mtime'])  # minimal def.
     info = 'dev=/dev/root mnt_point=/ path=/does/not/matter'
     devpath = wrap_and_call(
         'cloudinit.config.cc_resizefs',
         {
             'util.get_cmdline': {
                 'return_value': 'asdf root=UUID=my-uuid'
             },
             'util.is_container': False,
             'os.path.exists': False,  # /dev/root doesn't exist
             'os.stat': {
                 'return_value': FakeStat(25008, 0, 1)
             }  # char block device
         },
         maybe_get_writable_device_path,
         '/dev/root',
         info,
         LOG)
     self.assertEqual('/dev/disk/by-uuid/my-uuid', devpath)
     self.assertIn(
         "DEBUG: Converted /dev/root to '/dev/disk/by-uuid/my-uuid'"
         " per kernel cmdline", self.logs.getvalue())
Esempio n. 28
0
 def test_status_on_errors(self):
     '''Reports error when any stage has errors.'''
     write_json(
         self.status_file, {
             'v1': {
                 'stage': None,
                 'blah': {
                     'errors': [],
                     'finished': 123.456
                 },
                 'init': {
                     'errors': ['error1'],
                     'start': 124.567,
                     'finished': 125.678
                 },
                 'init-local': {
                     'start': 123.45,
                     'finished': 123.46
                 }
             }
         })
     cmdargs = myargs(long=False, wait=False)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         retcode = wrap_and_call(
             'cloudinit.cmd.status', {
                 '_is_cloudinit_disabled': (False, ''),
                 'Init': {
                     'side_effect': self.init_class
                 }
             }, status.handle_status_args, 'ignored', cmdargs)
     self.assertEqual(1, retcode)
     self.assertEqual('status: error\n', m_stdout.getvalue())
Esempio n. 29
0
 def test_order_precedence_is_builtin_system_runtime_cmdline(self):
     builtin = {'key1': 'builtin0', 'key3': 'builtin3'}
     conf_d = {'key1': 'confd1', 'key2': 'confd2', 'keyconfd1': 'kconfd1'}
     runtime = {'key1': 'runtime1', 'key2': 'runtime2'}
     cmdline = {'key1': 'cmdline1'}
     ret = helpers.wrap_and_call(
         'cloudinit.stages', {
             'util.read_conf_with_confd': {
                 'return_value': conf_d
             },
             'util.get_builtin_cfg': {
                 'return_value': builtin
             },
             'util.read_conf_from_cmdline': {
                 'return_value': cmdline
             },
             'read_runtime_config': {
                 'return_value': runtime
             },
         }, stages.fetch_base_config)
     self.assertEqual(
         ret, {
             'key1': 'cmdline1',
             'key2': 'runtime2',
             'key3': 'builtin3',
             'keyconfd1': 'kconfd1'
         })
Esempio n. 30
0
    def test_maybe_get_writable_device_path_warns_missing_cmdline_root(self):
        """When root does not exist isn't in the cmdline, log warning."""
        info = 'does not matter'

        def fake_mount_info(path, log):
            self.assertEqual('/', path)
            self.assertEqual(LOG, log)
            return ('/dev/root', 'ext4', '/')

        exists_mock_path = 'cloudinit.config.cc_resizefs.os.path.exists'
        with mock.patch(exists_mock_path) as m_exists:
            m_exists.return_value = False
            devpath = wrap_and_call(
                'cloudinit.config.cc_resizefs.util', {
                    'is_container': {
                        'return_value': False
                    },
                    'get_mount_info': {
                        'side_effect': fake_mount_info
                    },
                    'get_cmdline': {
                        'return_value': 'BOOT_IMAGE=/vmlinuz.efi'
                    }
                }, maybe_get_writable_device_path, '/dev/root', info, LOG)
        self.assertIsNone(devpath)
        logs = self.logs.getvalue()
        self.assertIn("WARNING: Unable to find device '/dev/root'", logs)
Esempio n. 31
0
 def test_status_returns_done_long(self):
     '''Long format of done status includes datasource info.'''
     ensure_file(self.tmp_path('result.json', self.new_root))
     write_json(
         self.status_file,
         {'v1': {'stage': None,
                 'datasource': (
                     'DataSourceNoCloud [seed=/var/.../seed/nocloud-net]'
                     '[dsmode=net]'),
                 'init': {'start': 124.567, 'finished': 125.678},
                 'init-local': {'start': 123.45, 'finished': 123.46}}})
     cmdargs = myargs(long=True, wait=False)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         retcode = wrap_and_call(
             'cloudinit.cmd.status',
             {'_is_cloudinit_disabled': (False, ''),
              'Init': {'side_effect': self.init_class}},
             status.handle_status_args, 'ignored', cmdargs)
     self.assertEqual(0, retcode)
     expected = dedent('''\
         status: done
         time: Thu, 01 Jan 1970 00:02:05 +0000
         detail:
         DataSourceNoCloud [seed=/var/.../seed/nocloud-net][dsmode=net]
     ''')
     self.assertEqual(expected, m_stdout.getvalue())
Esempio n. 32
0
 def test_status_returns_done(self):
     '''Reports done when stage is None and all stages are finished.'''
     write_json(
         self.status_file, {
             'v1': {
                 'stage':
                 None,
                 'datasource':
                 ('DataSourceNoCloud [seed=/var/.../seed/nocloud-net]'
                  '[dsmode=net]'),
                 'blah': {
                     'finished': 123.456
                 },
                 'init': {
                     'errors': [],
                     'start': 124.567,
                     'finished': 125.678
                 },
                 'init-local': {
                     'start': 123.45,
                     'finished': 123.46
                 }
             }
         })
     cmdargs = myargs(long=False, wait=False)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         retcode = wrap_and_call(
             'cloudinit.cmd.status', {
                 '_is_cloudinit_disabled': (False, ''),
                 'Init': {
                     'side_effect': self.init_class
                 }
             }, status.handle_status_args, 'ignored', cmdargs)
     self.assertEqual(0, retcode)
     self.assertEqual('status: done\n', m_stdout.getvalue())
Esempio n. 33
0
    def test_status_wait_blocks_until_error(self):
        '''Specifying wait will poll every 1/4 second until error state.'''
        running_json = {
            'v1': {'stage': 'init',
                   'init': {'start': 124.456, 'finished': None},
                   'init-local': {'start': 123.45, 'finished': 123.46}}}
        error_json = {
            'v1': {'stage': None,
                   'init': {'errors': ['error1'], 'start': 124.456,
                            'finished': 125.678},
                   'init-local': {'start': 123.45, 'finished': 123.46}}}

        self.sleep_calls = 0

        def fake_sleep(interval):
            self.assertEqual(0.25, interval)
            self.sleep_calls += 1
            if self.sleep_calls == 2:
                write_json(self.status_file, running_json)
            elif self.sleep_calls == 3:
                write_json(self.status_file, error_json)

        cmdargs = myargs(long=False, wait=True)
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
            retcode = wrap_and_call(
                'cloudinit.cmd.status',
                {'sleep': {'side_effect': fake_sleep},
                 '_is_cloudinit_disabled': (False, ''),
                 'Init': {'side_effect': self.init_class}},
                status.handle_status_args, 'ignored', cmdargs)
        self.assertEqual(1, retcode)
        self.assertEqual(4, self.sleep_calls)
        self.assertEqual('....\nstatus: error\n', m_stdout.getvalue())
Esempio n. 34
0
 def test_get_data_vmware_customization_sys_cfg_disabled(self):
     """When vmware customization is disabled via sys_cfg and
     no meta data is found, log a message.
     """
     paths = Paths({'cloud_dir': self.tdir})
     ds = self.datasource(sys_cfg={
         'disable_vmware_customization': True,
         'datasource': {
             'OVF': {
                 'allow_raw_data': True
             }
         }
     },
                          distro={},
                          paths=paths)
     conf_file = self.tmp_path('test-cust', self.tdir)
     conf_content = dedent("""\
         [MISC]
         MARKER-ID = 12345345
         """)
     util.write_file(conf_file, conf_content)
     retcode = wrap_and_call(
         'cloudinit.sources.DataSourceOVF', {
             'dmi.read_dmi_data': 'vmware',
             'transport_iso9660': NOT_FOUND,
             'transport_vmware_guestinfo': NOT_FOUND,
             'util.del_dir': True,
             'search_file': self.tdir,
             'wait_for_imc_cfg_file': conf_file
         }, ds.get_data)
     self.assertFalse(retcode, 'Expected False return from ds.get_data')
     self.assertIn('DEBUG: Customization using VMware config is disabled.',
                   self.logs.getvalue())
Esempio n. 35
0
 def test_status_on_errors_long(self):
     '''Long format of error status includes all error messages.'''
     write_json(
         self.status_file,
         {'v1': {'stage': None,
                 'datasource': (
                     'DataSourceNoCloud [seed=/var/.../seed/nocloud-net]'
                     '[dsmode=net]'),
                 'init': {'errors': ['error1'], 'start': 124.567,
                          'finished': 125.678},
                 'init-local': {'errors': ['error2', 'error3'],
                                'start': 123.45, 'finished': 123.46}}})
     cmdargs = myargs(long=True, wait=False)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         retcode = wrap_and_call(
             'cloudinit.cmd.status',
             {'_is_cloudinit_disabled': (False, ''),
              'Init': {'side_effect': self.init_class}},
             status.handle_status_args, 'ignored', cmdargs)
     self.assertEqual(1, retcode)
     expected = dedent('''\
         status: error
         time: Thu, 01 Jan 1970 00:02:05 +0000
         detail:
         error1
         error2
         error3
     ''')
     self.assertEqual(expected, m_stdout.getvalue())
Esempio n. 36
0
 def test_main_init_run_net_runs_modules(self):
     """Modules like write_files are run in 'net' mode."""
     cmdargs = myargs(debug=False,
                      files=None,
                      force=False,
                      local=False,
                      reporter=None,
                      subcommand='init')
     (_item1, item2) = wrap_and_call(
         'cloudinit.cmd.main', {
             'util.close_stdin': True,
             'netinfo.debug_info': 'my net debug info',
             'util.fixup_output': ('outfmt', 'errfmt')
         }, main.main_init, 'init', cmdargs)
     self.assertEqual([], item2)
     # Instancify is called
     instance_id_path = 'var/lib/cloud/data/instance-id'
     self.assertEqual(
         'iid-datasource-none\n',
         os.path.join(
             load_file(os.path.join(self.new_root, instance_id_path))))
     # modules are run (including write_files)
     self.assertEqual(
         'blah', load_file(os.path.join(self.new_root, 'etc/blah.ini')))
     expected_logs = [
         'network config is disabled by fallback',  # apply_network_config
         'my net debug info',  # netinfo.debug_info
         'no previous run detected'
     ]
     for log in expected_logs:
         self.assertIn(log, self.stderr.getvalue())
Esempio n. 37
0
 def test_status_returns_running_long_format(self):
     '''Long format reports the stage in which we are running.'''
     write_json(
         self.status_file, {
             'v1': {
                 'stage': 'init',
                 'init': {
                     'start': 124.456,
                     'finished': None
                 },
                 'init-local': {
                     'start': 123.45,
                     'finished': 123.46
                 }
             }
         })
     cmdargs = myargs(long=True, wait=False)
     with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
         retcode = wrap_and_call(
             'cloudinit.cmd.status', {
                 '_is_cloudinit_disabled': (False, ''),
                 'Init': {
                     'side_effect': self.init_class
                 }
             }, status.handle_status_args, 'ignored', cmdargs)
     self.assertEqual(0, retcode)
     expected = dedent('''\
         status: running
         time: Thu, 01 Jan 1970 00:02:04 +0000
         detail:
         Running in stage: init
     ''')
     self.assertEqual(expected, m_stdout.getvalue())
Esempio n. 38
0
 def test_only_builtin_gets_builtin(self):
     ret = helpers.wrap_and_call(
         'cloudinit.stages',
         {'util.read_conf_with_confd': None,
          'util.read_conf_from_cmdline': None,
          'read_runtime_config': {'return_value': {}}},
         stages.fetch_base_config)
     self.assertEqual(util.get_builtin_cfg(), ret)
Esempio n. 39
0
    def test_get_data_cloudinit_userdata(self):
        """Test user data can be loaded to cloud-init user data.
        """
        paths = Paths({'cloud_dir': self.tdir})
        ds = self.datasource(sys_cfg={'disable_vmware_customization': False},
                             distro={},
                             paths=paths)

        # Prepare the conf file
        conf_file = self.tmp_path('test-cust', self.tdir)
        conf_content = dedent("""\
            [CLOUDINIT]
            METADATA = test-meta
            USERDATA = test-user
            """)
        util.write_file(conf_file, conf_content)

        # Prepare the meta data file
        metadata_file = self.tmp_path('test-meta', self.tdir)
        metadata_content = dedent("""\
            instance-id: cloud-vm
            local-hostname: my-host.domain.com
            network:
                version: 2
                ethernets:
                    nics:
                        match:
                            name: ens*
                        dhcp4: yes
            """)
        util.write_file(metadata_file, metadata_content)

        # Prepare the user data file
        userdata_file = self.tmp_path('test-user', self.tdir)
        userdata_content = "This is the user data"
        util.write_file(userdata_file, userdata_content)

        with mock.patch(MPATH + 'set_customization_status',
                        return_value=('msg', b'')):
            result = wrap_and_call(
                'cloudinit.sources.DataSourceOVF', {
                    'dmi.read_dmi_data':
                    'vmware',
                    'util.del_dir':
                    True,
                    'search_file':
                    self.tdir,
                    'wait_for_imc_cfg_file':
                    conf_file,
                    'collect_imc_file_paths':
                    [self.tdir + '/test-meta', self.tdir + '/test-user', ''],
                    'get_nics_to_enable':
                    ''
                }, ds._get_data)

        self.assertTrue(result)
        self.assertEqual("cloud-vm", ds.metadata['instance-id'])
        self.assertEqual(userdata_content, ds.userdata_raw)
 def test_handler_writes_merged_client_config_file_with_defaults(self):
     """Merge and write options from LSC_CLIENT_CFG_FILE with defaults."""
     # Write existing sparse client.conf file
     util.write_file(self.conf, '[client]\ncomputer_title = My PC\n')
     mycloud = self._get_cloud('ubuntu')
     cfg = {'landscape': {'client': {}}}
     expected = {'client': {
         'log_level': 'info',
         'url': 'https://landscape.canonical.com/message-system',
         'ping_url': 'http://landscape.canonical.com/ping',
         'data_path': '/var/lib/landscape/client',
         'computer_title': 'My PC'}}
     wrap_and_call(
         'cloudinit.config.cc_landscape',
         {'LSC_CLIENT_CFG_FILE': {'new': self.conf}},
         cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
     self.assertEqual(expected, dict(ConfigObj(self.conf)))
     self.assertIn(
         'Wrote landscape config file to {0}'.format(self.conf),
         self.logs.getvalue())
 def test_maybe_get_writable_device_path_none_on_overlayroot(self):
     """When devpath is overlayroot (on MAAS), is_dev_writable is False."""
     info = 'does not matter'
     devpath = wrap_and_call(
         'cloudinit.config.cc_resizefs.util',
         {'is_container': {'return_value': False}},
         maybe_get_writable_device_path, 'overlayroot', info, LOG)
     self.assertIsNone(devpath)
     self.assertIn(
         "Not attempting to resize devpath 'overlayroot'",
         self.logs.getvalue())
 def test_maybe_get_writable_device_path_does_not_exist_in_container(self):
     """When devpath does not exist in a container, log a debug message."""
     info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
     devpath = wrap_and_call(
         'cloudinit.config.cc_resizefs.util',
         {'is_container': {'return_value': True}},
         maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
     self.assertIsNone(devpath)
     self.assertIn(
         "DEBUG: Device '/dev/I/dont/exist' did not exist in container."
         ' cannot resize: %s' % info,
         self.logs.getvalue())
 def test_maybe_get_writable_device_path_does_not_exist(self):
     """When devpath does not exist, a warning is logged."""
     info = 'dev=/dev/I/dont/exist mnt_point=/ path=/dev/none'
     devpath = wrap_and_call(
         'cloudinit.config.cc_resizefs.util',
         {'is_container': {'return_value': False}},
         maybe_get_writable_device_path, '/dev/I/dont/exist', info, LOG)
     self.assertIsNone(devpath)
     self.assertIn(
         "WARNING: Device '/dev/I/dont/exist' did not exist."
         ' cannot resize: %s' % info,
         self.logs.getvalue())
    def test_handle_warns_on_undiscoverable_root_path_in_commandline(self):
        """handle noops when the root path is not found on the commandline."""
        cfg = {'resize_rootfs': True}
        exists_mock_path = 'cloudinit.config.cc_resizefs.os.path.exists'

        def fake_mount_info(path, log):
            self.assertEqual('/', path)
            self.assertEqual(LOG, log)
            return ('/dev/root', 'ext4', '/')

        with mock.patch(exists_mock_path) as m_exists:
            m_exists.return_value = False
            wrap_and_call(
                'cloudinit.config.cc_resizefs.util',
                {'is_container': {'return_value': False},
                 'get_mount_info': {'side_effect': fake_mount_info},
                 'get_cmdline': {'return_value': 'BOOT_IMAGE=/vmlinuz.efi'}},
                handle, 'cc_resizefs', cfg, _cloud=None, log=LOG,
                args=[])
        logs = self.logs.getvalue()
        self.assertIn("WARNING: Unable to find device '/dev/root'", logs)
Esempio n. 45
0
    def test_remove_artifacts_preserves_logs(self):
        """remove_artifacts leaves logs when remove_logs is False."""
        write_file(self.log1, 'cloud-init-log')
        write_file(self.log2, 'cloud-init-output-log')

        retcode = wrap_and_call(
            'cloudinit.cmd.clean',
            {'Init': {'side_effect': self.init_class}},
            clean.remove_artifacts, remove_logs=False)
        self.assertTrue(os.path.exists(self.log1), 'Missing expected file')
        self.assertTrue(os.path.exists(self.log2), 'Missing expected file')
        self.assertEqual(0, retcode)
Esempio n. 46
0
 def test_add_assertions_adds_assertions_as_list(self, m_subp):
     """When provided with a list, add_assertions adds all assertions."""
     self.assertEqual(
         ASSERTIONS_FILE, '/var/lib/cloud/instance/snapd.assertions')
     assert_file = self.tmp_path('snapd.assertions', dir=self.tmp)
     assertions = [SYSTEM_USER_ASSERTION, ACCOUNT_ASSERTION]
     wrap_and_call(
         'cloudinit.config.cc_snap',
         {'ASSERTIONS_FILE': {'new': assert_file}},
         add_assertions, assertions)
     self.assertIn(
         'Importing user-provided snap assertions', self.logs.getvalue())
     self.assertIn(
         'sertions', self.logs.getvalue())
     self.assertEqual(
         [mock.call(['snap', 'ack', assert_file], capture=True)],
         m_subp.call_args_list)
     compare_file = self.tmp_path('comparison', dir=self.tmp)
     util.write_file(compare_file, '\n'.join(assertions).encode('utf-8'))
     self.assertEqual(
         util.load_file(compare_file), util.load_file(assert_file))
Esempio n. 47
0
 def test_get_data_false_on_none_dmi_data(self):
     """When dmi for system-product-name is None, get_data returns False."""
     paths = Paths({'cloud_dir': self.tdir})
     ds = self.datasource(sys_cfg={}, distro={}, paths=paths)
     retcode = wrap_and_call(
         'cloudinit.sources.DataSourceOVF',
         {'util.read_dmi_data': None,
          'transport_iso9660': NOT_FOUND,
          'transport_vmware_guestinfo': NOT_FOUND},
         ds.get_data)
     self.assertFalse(retcode, 'Expected False return from ds.get_data')
     self.assertIn(
         'DEBUG: No system-product-name found', self.logs.getvalue())
Esempio n. 48
0
    def test_main_init_run_net_calls_set_hostname_when_metadata_present(self):
        """When local-hostname metadata is present, call cc_set_hostname."""
        self.cfg['datasource'] = {
            'None': {'metadata': {'local-hostname': 'md-hostname'}}}
        cloud_cfg = yaml_dumps(self.cfg)
        write_file(self.cloud_cfg_file, cloud_cfg)
        cmdargs = myargs(
            debug=False, files=None, force=False, local=False, reporter=None,
            subcommand='init')

        def set_hostname(name, cfg, cloud, log, args):
            self.assertEqual('set-hostname', name)
            updated_cfg = copy.deepcopy(self.cfg)
            updated_cfg.update(
                {'def_log_file': '/var/log/cloud-init.log',
                 'log_cfgs': [],
                 'syslog_fix_perms': [
                     'syslog:adm', 'root:adm', 'root:wheel', 'root:root'
                 ],
                 'vendor_data': {'enabled': True, 'prefix': []}})
            updated_cfg.pop('system_info')

            self.assertEqual(updated_cfg, cfg)
            self.assertEqual(main.LOG, log)
            self.assertIsNone(args)

        (_item1, item2) = wrap_and_call(
            'cloudinit.cmd.main',
            {'util.close_stdin': True,
             'netinfo.debug_info': 'my net debug info',
             'cc_set_hostname.handle': {'side_effect': set_hostname},
             'util.fixup_output': ('outfmt', 'errfmt')},
            main.main_init, 'init', cmdargs)
        self.assertEqual([], item2)
        # Instancify is called
        instance_id_path = 'var/lib/cloud/data/instance-id'
        self.assertEqual(
            'iid-datasource-none\n',
            os.path.join(load_file(
                os.path.join(self.new_root, instance_id_path))))
        # modules are run (including write_files)
        self.assertEqual(
            'blah', load_file(os.path.join(self.new_root, 'etc/blah.ini')))
        expected_logs = [
            'network config is disabled by fallback',  # apply_network_config
            'my net debug info',  # netinfo.debug_info
            'no previous run detected'
        ]
        for log in expected_logs:
            self.assertIn(log, self.stderr.getvalue())
Esempio n. 49
0
 def test_cmdline_overrides_defaults(self):
     builtin = util.get_builtin_cfg()
     test_key = sorted(builtin)[0]
     test_value = 'test'
     cmdline = {test_key: test_value}
     ret = helpers.wrap_and_call(
         'cloudinit.stages',
         {'util.read_conf_from_cmdline': {'return_value': cmdline},
          'util.read_conf_with_confd': None,
          'read_runtime_config': None},
         stages.fetch_base_config)
     self.assertEqual(ret.get(test_key), test_value)
     builtin[test_key] = test_value
     self.assertEqual(ret, builtin)
Esempio n. 50
0
 def test_cmdline_overrides_confd_runtime_and_defaults(self):
     builtin = {'key1': 'value0', 'key3': 'other2'}
     conf_d = {'key1': 'value1', 'key2': 'other1'}
     cmdline = {'key3': 'other3', 'key2': 'other2'}
     runtime = {'key3': 'runtime3'}
     ret = helpers.wrap_and_call(
         'cloudinit.stages',
         {'util.read_conf_with_confd': {'return_value': conf_d},
          'util.get_builtin_cfg': {'return_value': builtin},
          'read_runtime_config': {'return_value': runtime},
          'util.read_conf_from_cmdline': {'return_value': cmdline}},
         stages.fetch_base_config)
     self.assertEqual(ret, {'key1': 'value1', 'key2': 'other2',
                            'key3': 'other3'})
    def test_maybe_get_writable_device_path_non_block_on_container(self):
        """When device is non-block device in container, emit debug log."""
        fake_devpath = self.tmp_path('dev/readwrite')
        util.write_file(fake_devpath, '', mode=0o600)  # read-write
        info = 'dev=/dev/root mnt_point=/ path={0}'.format(fake_devpath)

        devpath = wrap_and_call(
            'cloudinit.config.cc_resizefs.util',
            {'is_container': {'return_value': True}},
            maybe_get_writable_device_path, fake_devpath, info, LOG)
        self.assertIsNone(devpath)
        self.assertIn(
            "DEBUG: device '{0}' not a block device in container."
            ' cannot resize'.format(fake_devpath),
            self.logs.getvalue())
 def test_handler_installs_client_and_creates_config_file(self):
     """Write landscape client.conf and install landscape-client."""
     mycloud = self._get_cloud('ubuntu')
     cfg = {'landscape': {'client': {}}}
     expected = {'client': {
         'log_level': 'info',
         'url': 'https://landscape.canonical.com/message-system',
         'ping_url': 'http://landscape.canonical.com/ping',
         'data_path': '/var/lib/landscape/client'}}
     mycloud.distro = mock.MagicMock()
     wrap_and_call(
         'cloudinit.config.cc_landscape',
         {'LSC_CLIENT_CFG_FILE': {'new': self.conf},
          'LS_DEFAULT_FILE': {'new': self.default_file}},
         cc_landscape.handle, 'notimportant', cfg, mycloud, LOG, None)
     self.assertEqual(
         [mock.call('landscape-client')],
         mycloud.distro.install_packages.call_args)
     self.assertEqual(expected, dict(ConfigObj(self.conf)))
     self.assertIn(
         'Wrote landscape config file to {0}'.format(self.conf),
         self.logs.getvalue())
     default_content = util.load_file(self.default_file)
     self.assertEqual('RUN=1\n', default_content)
Esempio n. 53
0
    def test_remove_artifacts_returns_one_on_errors(self):
        """remove_artifacts returns non-zero on failure and prints an error."""
        ensure_dir(self.artifact_dir)
        ensure_dir(os.path.join(self.artifact_dir, 'dir1'))

        with mock.patch('sys.stderr', new_callable=StringIO) as m_stderr:
            retcode = wrap_and_call(
                'cloudinit.cmd.clean',
                {'del_dir': {'side_effect': OSError('oops')},
                 'Init': {'side_effect': self.init_class}},
                clean.remove_artifacts, remove_logs=False)
        self.assertEqual(1, retcode)
        self.assertEqual(
            'ERROR: Could not remove %s/dir1: oops\n' % self.artifact_dir,
            m_stderr.getvalue())
Esempio n. 54
0
 def test_order_precedence_is_builtin_system_runtime_cmdline(self):
     builtin = {'key1': 'builtin0', 'key3': 'builtin3'}
     conf_d = {'key1': 'confd1', 'key2': 'confd2', 'keyconfd1': 'kconfd1'}
     runtime = {'key1': 'runtime1', 'key2': 'runtime2'}
     cmdline = {'key1': 'cmdline1'}
     ret = helpers.wrap_and_call(
         'cloudinit.stages',
         {'util.read_conf_with_confd': {'return_value': conf_d},
          'util.get_builtin_cfg': {'return_value': builtin},
          'util.read_conf_from_cmdline': {'return_value': cmdline},
          'read_runtime_config': {'return_value': runtime},
          },
         stages.fetch_base_config)
     self.assertEqual(ret, {'key1': 'cmdline1', 'key2': 'runtime2',
                            'key3': 'builtin3', 'keyconfd1': 'kconfd1'})
Esempio n. 55
0
 def test_get_data_no_vmware_customization_disabled(self):
     """When vmware customization is disabled via sys_cfg log a message."""
     paths = Paths({'cloud_dir': self.tdir})
     ds = self.datasource(
         sys_cfg={'disable_vmware_customization': True}, distro={},
         paths=paths)
     retcode = wrap_and_call(
         'cloudinit.sources.DataSourceOVF',
         {'util.read_dmi_data': 'vmware',
          'transport_iso9660': NOT_FOUND,
          'transport_vmware_guestinfo': NOT_FOUND},
         ds.get_data)
     self.assertFalse(retcode, 'Expected False return from ds.get_data')
     self.assertIn(
         'DEBUG: Customization for VMware platform is disabled.',
         self.logs.getvalue())
Esempio n. 56
0
    def test_remove_artifacts_removes_unlinks_symlinks(self):
        """remove_artifacts cleans artifacts dir unlinking any symlinks."""
        dir1 = os.path.join(self.artifact_dir, 'dir1')
        ensure_dir(dir1)
        symlink = os.path.join(self.artifact_dir, 'mylink')
        sym_link(dir1, symlink)

        retcode = wrap_and_call(
            'cloudinit.cmd.clean',
            {'Init': {'side_effect': self.init_class}},
            clean.remove_artifacts, remove_logs=False)
        self.assertEqual(0, retcode)
        for path in (dir1, symlink):
            self.assertFalse(
                os.path.exists(path),
                'Unexpected {0} dir'.format(path))
Esempio n. 57
0
    def test_mkstemp_default_root(self):
        """mkstemp creates a secure tempfile in /run/cloud-init for root."""
        calls = []

        def fake_mkstemp(*args, **kwargs):
            calls.append(kwargs)
            return '/fake/return/path'

        retval = wrap_and_call(
            'cloudinit.temp_utils',
            {'os.getuid': 0,
             'tempfile.mkstemp': {'side_effect': fake_mkstemp},
             '_TMPDIR': {'new': None},
             'os.path.isdir': True},
            mkstemp)
        self.assertEqual('/fake/return/path', retval)
        self.assertEqual([{'dir': '/run/cloud-init/tmp'}], calls)
Esempio n. 58
0
    def test_mkdtemp_default_non_root_needs_exe(self):
        """mkdtemp creates a dir under /var/tmp/cloud-init when needs_exe."""
        calls = []

        def fake_mkdtemp(*args, **kwargs):
            calls.append(kwargs)
            return '/fake/return/path'

        retval = wrap_and_call(
            'cloudinit.temp_utils',
            {'os.getuid': 1000,
             'tempfile.mkdtemp': {'side_effect': fake_mkdtemp},
             '_TMPDIR': {'new': None},
             'os.path.isdir': True},
            mkdtemp, needs_exe=True)
        self.assertEqual('/fake/return/path', retval)
        self.assertEqual([{'dir': '/var/tmp/cloud-init'}], calls)