def setUp(self):
        super(TestAzureEndpointHttpClient, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.read_file_or_url = patches.enter_context(
            mock.patch.object(azure_helper.url_helper, 'read_file_or_url'))
Example #2
0
class TestIsDiskUsed(TestCase):
    def setUp(self):
        super(TestIsDiskUsed, self).setUp()
        self.patches = ExitStack()
        mod_name = 'cloudinit.config.cc_disk_setup'
        self.enumerate_disk = self.patches.enter_context(
            mock.patch('{0}.enumerate_disk'.format(mod_name)))
        self.check_fs = self.patches.enter_context(
            mock.patch('{0}.check_fs'.format(mod_name)))

    def tearDown(self):
        super(TestIsDiskUsed, self).tearDown()
        self.patches.close()

    def test_multiple_child_nodes_returns_true(self):
        self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(2))
        self.check_fs.return_value = (mock.MagicMock(), None, mock.MagicMock())
        self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))

    def test_valid_filesystem_returns_true(self):
        self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1))
        self.check_fs.return_value = (mock.MagicMock(), 'ext4',
                                      mock.MagicMock())
        self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))

    def test_one_child_nodes_and_no_fs_returns_false(self):
        self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1))
        self.check_fs.return_value = (mock.MagicMock(), None, mock.MagicMock())
        self.assertFalse(cc_disk_setup.is_disk_used(mock.MagicMock()))
Example #3
0
    def setUp(self):
        super(TestWalkerHandleHandler, self).setUp()
        tmpdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, tmpdir)

        self.data = {
            "handlercount": 0,
            "frequency": "",
            "handlerdir": tmpdir,
            "handlers": helpers.ContentHandlers(),
            "data": None}

        self.expected_module_name = "part-handler-%03d" % (
            self.data["handlercount"],)
        expected_file_name = "%s.py" % self.expected_module_name
        self.expected_file_fullname = os.path.join(
            self.data["handlerdir"], expected_file_name)
        self.module_fake = FakeModule()
        self.ctype = None
        self.filename = None
        self.payload = "dummy payload"

        # Mock the write_file() function.  We'll assert that it got called as
        # expected in each of the individual tests.
        resources = ExitStack()
        self.addCleanup(resources.close)
        self.write_file_mock = resources.enter_context(
            mock.patch('cloudinit.util.write_file'))
Example #4
0
    def setUp(self):
        super(TestWalkerHandleHandler, self).setUp()
        tmpdir = tempfile.mkdtemp()
        self.addCleanup(shutil.rmtree, tmpdir)

        self.data = {
            "handlercount": 0,
            "frequency": "",
            "handlerdir": tmpdir,
            "handlers": helpers.ContentHandlers(),
            "data": None
        }

        self.expected_module_name = "part-handler-%03d" % (
            self.data["handlercount"], )
        expected_file_name = "%s.py" % self.expected_module_name
        self.expected_file_fullname = os.path.join(self.data["handlerdir"],
                                                   expected_file_name)
        self.module_fake = FakeModule()
        self.ctype = None
        self.filename = None
        self.payload = "dummy payload"

        # Mock the write_file() function.  We'll assert that it got called as
        # expected in each of the individual tests.
        resources = ExitStack()
        self.addCleanup(resources.close)
        self.write_file_mock = resources.enter_context(
            mock.patch('cloudinit.util.write_file'))
class TestIsDiskUsed(TestCase):

    def setUp(self):
        super(TestIsDiskUsed, self).setUp()
        self.patches = ExitStack()
        mod_name = 'cloudinit.config.cc_disk_setup'
        self.enumerate_disk = self.patches.enter_context(
            mock.patch('{0}.enumerate_disk'.format(mod_name)))
        self.check_fs = self.patches.enter_context(
            mock.patch('{0}.check_fs'.format(mod_name)))

    def tearDown(self):
        super(TestIsDiskUsed, self).tearDown()
        self.patches.close()

    def test_multiple_child_nodes_returns_true(self):
        self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(2))
        self.check_fs.return_value = (mock.MagicMock(), None, mock.MagicMock())
        self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))

    def test_valid_filesystem_returns_true(self):
        self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1))
        self.check_fs.return_value = (
            mock.MagicMock(), 'ext4', mock.MagicMock())
        self.assertTrue(cc_disk_setup.is_disk_used(mock.MagicMock()))

    def test_one_child_nodes_and_no_fs_returns_false(self):
        self.enumerate_disk.return_value = (mock.MagicMock() for _ in range(1))
        self.check_fs.return_value = (mock.MagicMock(), None, mock.MagicMock())
        self.assertFalse(cc_disk_setup.is_disk_used(mock.MagicMock()))
Example #6
0
    def setUp(self):
        super(TestAzureEndpointHttpClient, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.read_file_or_url = patches.enter_context(
            mock.patch.object(azure_helper.util, 'read_file_or_url'))
Example #7
0
 def setUp(self):
     super(TestIsDiskUsed, self).setUp()
     self.patches = ExitStack()
     mod_name = 'cloudinit.config.cc_disk_setup'
     self.enumerate_disk = self.patches.enter_context(
         mock.patch('{0}.enumerate_disk'.format(mod_name)))
     self.check_fs = self.patches.enter_context(
         mock.patch('{0}.check_fs'.format(mod_name)))
    def setUp(self):
        super(TestAzureEndpointHttpClient, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.readurl = patches.enter_context(
            mock.patch.object(azure_helper.url_helper, 'readurl'))
        patches.enter_context(
            mock.patch.object(azure_helper.time, 'sleep', mock.MagicMock()))
Example #9
0
    def setUp(self):
        super().setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.load_file = patches.enter_context(
            mock.patch.object(bsd_utils.util, 'load_file'))

        self.write_file = patches.enter_context(
            mock.patch.object(bsd_utils.util, 'write_file'))
Example #10
0
    def setUp(self):
        super(TestOpenSSLManager, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.subp = patches.enter_context(
            mock.patch.object(azure_helper.util, 'subp'))
        try:
            self.open = patches.enter_context(mock.patch('__builtin__.open'))
        except ImportError:
            self.open = patches.enter_context(mock.patch('builtins.open'))
Example #11
0
    def setUp(self):
        super(TestFindEndpoint, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.load_file = patches.enter_context(
            mock.patch.object(azure_helper.util, 'load_file'))

        self.dhcp_options = patches.enter_context(
            mock.patch.object(azure_helper.WALinuxAgentShim,
                              '_load_dhclient_json'))
    def setUp(self):
        super(TestOpenSSLManager, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.subp = patches.enter_context(
            mock.patch.object(azure_helper.util, 'subp'))
        try:
            self.open = patches.enter_context(
                mock.patch('__builtin__.open'))
        except ImportError:
            self.open = patches.enter_context(
                mock.patch('builtins.open'))
Example #13
0
    def setUp(self):
        super(TestFindEndpoint, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.load_file = patches.enter_context(
            mock.patch.object(azure_helper.util, 'load_file'))

        self.dhcp_options = patches.enter_context(
            mock.patch.object(wa_shim, '_load_dhclient_json'))

        self.networkd_leases = patches.enter_context(
            mock.patch.object(wa_shim, '_networkd_get_value_from_leases'))
        self.networkd_leases.return_value = None
    def setUp(self):
        super(TestFindEndpoint, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.load_file = patches.enter_context(
            mock.patch.object(azure_helper.util, 'load_file'))

        self.dhcp_options = patches.enter_context(
            mock.patch.object(wa_shim, '_load_dhclient_json'))

        self.networkd_leases = patches.enter_context(
            mock.patch.object(wa_shim, '_networkd_get_value_from_leases'))
        self.networkd_leases.return_value = None
Example #15
0
 def setUp(self):
     super(TestAzureBounce, self).setUp()
     self.tmp = self.tmp_dir()
     self.waagent_d = os.path.join(self.tmp, 'var', 'lib', 'waagent')
     self.paths = helpers.Paths(
         {'cloud_dir': self.tmp, 'run_dir': self.tmp})
     dsaz.BUILTIN_DS_CONFIG['data_dir'] = self.waagent_d
     self.patches = ExitStack()
     self.mock_out_azure_moving_parts()
     self.get_hostname = self.patches.enter_context(
         mock.patch.object(dsaz, 'get_hostname'))
     self.set_hostname = self.patches.enter_context(
         mock.patch.object(dsaz, 'set_hostname'))
     self.subp = self.patches.enter_context(
         mock.patch('cloudinit.sources.DataSourceAzure.util.subp'))
Example #16
0
    def setUp(self):
        super(TestAzureDataSource, self).setUp()
        if PY26:
            raise SkipTest("Does not work on python 2.6")
        self.tmp = self.tmp_dir()

        # patch cloud_dir, so our 'seed_dir' is guaranteed empty
        self.paths = helpers.Paths(
            {'cloud_dir': self.tmp, 'run_dir': self.tmp})
        self.waagent_d = os.path.join(self.tmp, 'var', 'lib', 'waagent')

        self.patches = ExitStack()
        self.addCleanup(self.patches.close)

        super(TestAzureDataSource, self).setUp()
Example #17
0
    def setUp(self):
        super(TestNoCloudDataSource, self).setUp()
        self.tmp = self.tmp_dir()
        self.paths = helpers.Paths({
            'cloud_dir': self.tmp,
            'run_dir': self.tmp
        })

        self.cmdline = "root=TESTCMDLINE"

        self.mocks = ExitStack()
        self.addCleanup(self.mocks.close)

        self.mocks.enter_context(
            mock.patch.object(util, 'get_cmdline', return_value=self.cmdline))
Example #18
0
    def test_dev_os_remap(self):
        populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
        cfg_ds = ds.DataSourceConfigDrive(settings.CFG_BUILTIN,
                                          None,
                                          helpers.Paths({}))
        found = ds.read_config_drive(self.tmp)
        cfg_ds.metadata = found['metadata']
        name_tests = {
            'ami': '/dev/vda1',
            'root': '/dev/vda1',
            'ephemeral0': '/dev/vda2',
            'swap': '/dev/vda3',
        }
        for name, dev_name in name_tests.items():
            with ExitStack() as mocks:
                provided_name = dev_name[len('/dev/'):]
                provided_name = "s" + provided_name[1:]
                find_mock = mocks.enter_context(
                    mock.patch.object(util, 'find_devs_with',
                                      return_value=[provided_name]))
                # We want os.path.exists() to return False on its first call,
                # and True on its second call.  We use a handy generator as
                # the mock side effect for this.  The mocked function returns
                # what the side effect returns.

                def exists_side_effect():
                    yield False
                    yield True
                exists_mock = mocks.enter_context(
                    mock.patch.object(os.path, 'exists',
                                      side_effect=exists_side_effect()))
                self.assertEqual(dev_name, cfg_ds.device_name_to_device(name))

                find_mock.assert_called_once_with(mock.ANY)
                self.assertEqual(exists_mock.call_count, 2)
Example #19
0
    def test_dev_os_map(self):
        populate_dir(self.tmp, CFG_DRIVE_FILES_V2)
        cfg_ds = ds.DataSourceConfigDrive(settings.CFG_BUILTIN, None,
                                          helpers.Paths({}))
        found = ds.read_config_drive(self.tmp)
        os_md = found['metadata']
        cfg_ds.metadata = os_md
        name_tests = {
            'ami': '/dev/vda1',
            'root': '/dev/vda1',
            'ephemeral0': '/dev/vda2',
            'swap': '/dev/vda3',
        }
        for name, dev_name in name_tests.items():
            with ExitStack() as mocks:
                find_mock = mocks.enter_context(
                    mock.patch.object(util,
                                      'find_devs_with',
                                      return_value=[dev_name]))
                exists_mock = mocks.enter_context(
                    mock.patch.object(os.path, 'exists', return_value=True))
                self.assertEqual(dev_name, cfg_ds.device_name_to_device(name))

                find_mock.assert_called_once_with(mock.ANY)
                exists_mock.assert_called_once_with(mock.ANY)
 def setUp(self):
     super(TestIsDiskUsed, self).setUp()
     self.patches = ExitStack()
     mod_name = 'cloudinit.config.cc_disk_setup'
     self.enumerate_disk = self.patches.enter_context(
         mock.patch('{0}.enumerate_disk'.format(mod_name)))
     self.check_fs = self.patches.enter_context(
         mock.patch('{0}.check_fs'.format(mod_name)))
Example #21
0
    def setUp(self):
        super(TestCloudStackPasswordFetching, self).setUp()
        self.patches = ExitStack()
        self.addCleanup(self.patches.close)
        mod_name = 'cloudinit.sources.DataSourceCloudStack'
        self.patches.enter_context(mock.patch('{0}.ec2'.format(mod_name)))
        self.patches.enter_context(mock.patch('{0}.uhelp'.format(mod_name)))
        default_gw = "192.201.20.0"
        get_latest_lease = mock.MagicMock(return_value=None)
        self.patches.enter_context(mock.patch(
            mod_name + '.get_latest_lease', get_latest_lease))

        get_default_gw = mock.MagicMock(return_value=default_gw)
        self.patches.enter_context(mock.patch(
            mod_name + '.get_default_gateway', get_default_gw))

        get_networkd_server_address = mock.MagicMock(return_value=None)
        self.patches.enter_context(mock.patch(
            mod_name + '.dhcp.networkd_get_option_from_leases',
            get_networkd_server_address))
class TestGetMbrHddSize(TestCase):

    def setUp(self):
        super(TestGetMbrHddSize, self).setUp()
        self.patches = ExitStack()
        self.subp = self.patches.enter_context(
            mock.patch.object(cc_disk_setup.util, 'subp'))

    def tearDown(self):
        super(TestGetMbrHddSize, self).tearDown()
        self.patches.close()

    def _configure_subp_mock(self, hdd_size_in_bytes, sector_size_in_bytes):
        def _subp(cmd, *args, **kwargs):
            self.assertEqual(3, len(cmd))
            if '--getsize64' in cmd:
                return hdd_size_in_bytes, None
            elif '--getss' in cmd:
                return sector_size_in_bytes, None
            raise Exception('Unexpected blockdev command called')

        self.subp.side_effect = _subp

    def _test_for_sector_size(self, sector_size):
        size_in_bytes = random.randint(10000, 10000000) * 512
        size_in_sectors = size_in_bytes / sector_size
        self._configure_subp_mock(size_in_bytes, sector_size)
        self.assertEqual(size_in_sectors,
                         cc_disk_setup.get_hdd_size('/dev/sda1'))

    def test_size_for_512_byte_sectors(self):
        self._test_for_sector_size(512)

    def test_size_for_1024_byte_sectors(self):
        self._test_for_sector_size(1024)

    def test_size_for_2048_byte_sectors(self):
        self._test_for_sector_size(2048)

    def test_size_for_4096_byte_sectors(self):
        self._test_for_sector_size(4096)
Example #23
0
class TestGetMbrHddSize(TestCase):
    def setUp(self):
        super(TestGetMbrHddSize, self).setUp()
        self.patches = ExitStack()
        self.subp = self.patches.enter_context(
            mock.patch.object(cc_disk_setup.util, 'subp'))

    def tearDown(self):
        super(TestGetMbrHddSize, self).tearDown()
        self.patches.close()

    def _configure_subp_mock(self, hdd_size_in_bytes, sector_size_in_bytes):
        def _subp(cmd, *args, **kwargs):
            self.assertEqual(3, len(cmd))
            if '--getsize64' in cmd:
                return hdd_size_in_bytes, None
            elif '--getss' in cmd:
                return sector_size_in_bytes, None
            raise Exception('Unexpected blockdev command called')

        self.subp.side_effect = _subp

    def _test_for_sector_size(self, sector_size):
        size_in_bytes = random.randint(10000, 10000000) * 512
        size_in_sectors = size_in_bytes / sector_size
        self._configure_subp_mock(size_in_bytes, sector_size)
        self.assertEqual(size_in_sectors,
                         cc_disk_setup.get_hdd_size('/dev/sda1'))

    def test_size_for_512_byte_sectors(self):
        self._test_for_sector_size(512)

    def test_size_for_1024_byte_sectors(self):
        self._test_for_sector_size(1024)

    def test_size_for_2048_byte_sectors(self):
        self._test_for_sector_size(2048)

    def test_size_for_4096_byte_sectors(self):
        self._test_for_sector_size(4096)
Example #24
0
    def setUp(self):
        super(TestWALinuxAgentShim, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.AzureEndpointHttpClient = patches.enter_context(
            mock.patch.object(azure_helper, 'AzureEndpointHttpClient'))
        self.find_endpoint = patches.enter_context(
            mock.patch.object(azure_helper.WALinuxAgentShim, 'find_endpoint'))
        self.GoalState = patches.enter_context(
            mock.patch.object(azure_helper, 'GoalState'))
        self.OpenSSLManager = patches.enter_context(
            mock.patch.object(azure_helper, 'OpenSSLManager'))
        patches.enter_context(
            mock.patch.object(azure_helper.time, 'sleep', mock.MagicMock()))
Example #25
0
    def setUp(self):
        super(TestNoCloudDataSource, self).setUp()
        self.tmp = self.tmp_dir()
        self.paths = helpers.Paths(
            {'cloud_dir': self.tmp, 'run_dir': self.tmp})

        self.cmdline = "root=TESTCMDLINE"

        self.mocks = ExitStack()
        self.addCleanup(self.mocks.close)

        self.mocks.enter_context(
            mock.patch.object(util, 'get_cmdline', return_value=self.cmdline))
        self.mocks.enter_context(
            mock.patch.object(util, 'read_dmi_data', return_value=None))
    def setUp(self):
        super(TestWALinuxAgentShim, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.AzureEndpointHttpClient = patches.enter_context(
            mock.patch.object(azure_helper, 'AzureEndpointHttpClient'))
        self.find_endpoint = patches.enter_context(
            mock.patch.object(wa_shim, 'find_endpoint'))
        self.GoalState = patches.enter_context(
            mock.patch.object(azure_helper, 'GoalState'))
        self.OpenSSLManager = patches.enter_context(
            mock.patch.object(azure_helper, 'OpenSSLManager'))
        patches.enter_context(
            mock.patch.object(azure_helper.time, 'sleep', mock.MagicMock()))
Example #27
0
    def setUp(self):
        super(TestWALinuxAgentShim, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        self.AzureEndpointHttpClient = patches.enter_context(
            mock.patch.object(azure_helper, 'AzureEndpointHttpClient'))
        self.find_endpoint = patches.enter_context(
            mock.patch.object(wa_shim, 'find_endpoint'))
        self.GoalState = patches.enter_context(
            mock.patch.object(azure_helper, 'GoalState'))
        self.OpenSSLManager = patches.enter_context(
            mock.patch.object(azure_helper, 'OpenSSLManager'))
        patches.enter_context(
            mock.patch.object(azure_helper.time, 'sleep', mock.MagicMock()))

        self.test_incarnation = 'TestIncarnation'
        self.test_container_id = 'TestContainerId'
        self.test_instance_id = 'TestInstanceId'
        self.GoalState.return_value.incarnation = self.test_incarnation
        self.GoalState.return_value.container_id = self.test_container_id
        self.GoalState.return_value.instance_id = self.test_instance_id
Example #28
0
    def setUp(self):
        super(TestCloudStackPasswordFetching, self).setUp()
        self.patches = ExitStack()
        self.addCleanup(self.patches.close)
        mod_name = 'cloudinit.sources.DataSourceCloudStack'
        self.patches.enter_context(mock.patch('{0}.ec2'.format(mod_name)))
        self.patches.enter_context(mock.patch('{0}.uhelp'.format(mod_name)))
        default_gw = "192.201.20.0"
        get_latest_lease = mock.MagicMock(return_value=None)
        self.patches.enter_context(mock.patch(
            mod_name + '.get_latest_lease', get_latest_lease))

        get_default_gw = mock.MagicMock(return_value=default_gw)
        self.patches.enter_context(mock.patch(
            mod_name + '.get_default_gateway', get_default_gw))

        get_networkd_server_address = mock.MagicMock(return_value=None)
        self.patches.enter_context(mock.patch(
            mod_name + '.dhcp.networkd_get_option_from_leases',
            get_networkd_server_address))
        self.tmp = self.tmp_dir()
Example #29
0
    def setUp(self):
        super(TestGoalStateHealthReporter, self).setUp()
        patches = ExitStack()
        self.addCleanup(patches.close)

        patches.enter_context(
            mock.patch.object(azure_helper.time, 'sleep', mock.MagicMock()))
        self.read_file_or_url = patches.enter_context(
            mock.patch.object(azure_helper.url_helper, 'read_file_or_url'))

        self.post = patches.enter_context(
            mock.patch.object(azure_helper.AzureEndpointHttpClient, 'post'))

        self.GoalState = patches.enter_context(
            mock.patch.object(azure_helper, 'GoalState'))
        self.GoalState.return_value.container_id = \
            self.default_parameters['container_id']
        self.GoalState.return_value.instance_id = \
            self.default_parameters['instance_id']
        self.GoalState.return_value.incarnation = \
            self.default_parameters['incarnation']
Example #30
0
class TestCloudStackPasswordFetching(CiTestCase):
    def setUp(self):
        super(TestCloudStackPasswordFetching, self).setUp()
        self.patches = ExitStack()
        self.addCleanup(self.patches.close)
        mod_name = MOD_PATH
        self.patches.enter_context(mock.patch('{0}.ec2'.format(mod_name)))
        self.patches.enter_context(mock.patch('{0}.uhelp'.format(mod_name)))
        default_gw = "192.201.20.0"
        get_latest_lease = mock.MagicMock(return_value=None)
        self.patches.enter_context(
            mock.patch(mod_name + '.get_latest_lease', get_latest_lease))

        get_default_gw = mock.MagicMock(return_value=default_gw)
        self.patches.enter_context(
            mock.patch(mod_name + '.get_default_gateway', get_default_gw))

        get_networkd_server_address = mock.MagicMock(return_value=None)
        self.patches.enter_context(
            mock.patch(mod_name + '.dhcp.networkd_get_option_from_leases',
                       get_networkd_server_address))
        self.tmp = self.tmp_dir()

    def _set_password_server_response(self, response_string):
        subp = mock.MagicMock(return_value=(response_string, ''))
        self.patches.enter_context(
            mock.patch('cloudinit.sources.DataSourceCloudStack.subp.subp',
                       subp))
        return subp

    def test_empty_password_doesnt_create_config(self):
        self._set_password_server_response('')
        ds = DataSourceCloudStack({}, None,
                                  helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertEqual({}, ds.get_config_obj())

    def test_saved_password_doesnt_create_config(self):
        self._set_password_server_response('saved_password')
        ds = DataSourceCloudStack({}, None,
                                  helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertEqual({}, ds.get_config_obj())

    @mock.patch(DS_PATH + '.wait_for_metadata_service')
    def test_password_sets_password(self, m_wait):
        m_wait.return_value = True
        password = '******'
        self._set_password_server_response(password)
        ds = DataSourceCloudStack({}, None,
                                  helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertEqual(password, ds.get_config_obj()['password'])

    @mock.patch(DS_PATH + '.wait_for_metadata_service')
    def test_bad_request_doesnt_stop_ds_from_working(self, m_wait):
        m_wait.return_value = True
        self._set_password_server_response('bad_request')
        ds = DataSourceCloudStack({}, None,
                                  helpers.Paths({'run_dir': self.tmp}))
        self.assertTrue(ds.get_data())

    def assertRequestTypesSent(self, subp, expected_request_types):
        request_types = []
        for call in subp.call_args_list:
            args = call[0][0]
            for arg in args:
                if arg.startswith('DomU_Request'):
                    request_types.append(arg.split()[1])
        self.assertEqual(expected_request_types, request_types)

    @mock.patch(DS_PATH + '.wait_for_metadata_service')
    def test_valid_response_means_password_marked_as_saved(self, m_wait):
        m_wait.return_value = True
        password = '******'
        subp = self._set_password_server_response(password)
        ds = DataSourceCloudStack({}, None,
                                  helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertRequestTypesSent(subp,
                                    ['send_my_password', 'saved_password'])

    def _check_password_not_saved_for(self, response_string):
        subp = self._set_password_server_response(response_string)
        ds = DataSourceCloudStack({}, None,
                                  helpers.Paths({'run_dir': self.tmp}))
        with mock.patch(DS_PATH + '.wait_for_metadata_service') as m_wait:
            m_wait.return_value = True
            ds.get_data()
        self.assertRequestTypesSent(subp, ['send_my_password'])

    def test_password_not_saved_if_empty(self):
        self._check_password_not_saved_for('')

    def test_password_not_saved_if_already_saved(self):
        self._check_password_not_saved_for('saved_password')

    def test_password_not_saved_if_bad_request(self):
        self._check_password_not_saved_for('bad_request')
 def setUp(self):
     super(TestGetMbrHddSize, self).setUp()
     self.patches = ExitStack()
     self.subp = self.patches.enter_context(
         mock.patch.object(cc_disk_setup.util, 'subp'))
Example #32
0
class TestAzureBounce(CiTestCase):

    with_logs = True

    def mock_out_azure_moving_parts(self):
        self.patches.enter_context(
            mock.patch.object(dsaz, 'invoke_agent'))
        self.patches.enter_context(
            mock.patch.object(dsaz.util, 'wait_for_files'))
        self.patches.enter_context(
            mock.patch.object(dsaz, 'list_possible_azure_ds_devs',
                              mock.MagicMock(return_value=[])))
        self.patches.enter_context(
            mock.patch.object(dsaz, 'get_metadata_from_fabric',
                              mock.MagicMock(return_value={})))
        self.patches.enter_context(
            mock.patch.object(dsaz.util, 'which', lambda x: True))

        def _dmi_mocks(key):
            if key == 'system-uuid':
                return 'test-instance-id'
            elif key == 'chassis-asset-tag':
                return '7783-7084-3265-9085-8269-3286-77'
            raise RuntimeError('should not get here')

        self.patches.enter_context(
            mock.patch.object(dsaz.util, 'read_dmi_data',
                              mock.MagicMock(side_effect=_dmi_mocks)))

    def setUp(self):
        super(TestAzureBounce, self).setUp()
        self.tmp = self.tmp_dir()
        self.waagent_d = os.path.join(self.tmp, 'var', 'lib', 'waagent')
        self.paths = helpers.Paths(
            {'cloud_dir': self.tmp, 'run_dir': self.tmp})
        dsaz.BUILTIN_DS_CONFIG['data_dir'] = self.waagent_d
        self.patches = ExitStack()
        self.mock_out_azure_moving_parts()
        self.get_hostname = self.patches.enter_context(
            mock.patch.object(dsaz, 'get_hostname'))
        self.set_hostname = self.patches.enter_context(
            mock.patch.object(dsaz, 'set_hostname'))
        self.subp = self.patches.enter_context(
            mock.patch('cloudinit.sources.DataSourceAzure.util.subp'))

    def tearDown(self):
        self.patches.close()

    def _get_ds(self, ovfcontent=None, agent_command=None):
        if ovfcontent is not None:
            populate_dir(os.path.join(self.paths.seed_dir, "azure"),
                         {'ovf-env.xml': ovfcontent})
        dsrc = dsaz.DataSourceAzure(
            {}, distro=None, paths=self.paths)
        if agent_command is not None:
            dsrc.ds_cfg['agent_command'] = agent_command
        return dsrc

    def _get_and_setup(self, dsrc):
        ret = dsrc.get_data()
        if ret:
            dsrc.setup(True)
        return ret

    def get_ovf_env_with_dscfg(self, hostname, cfg):
        odata = {
            'HostName': hostname,
            'dscfg': {
                'text': b64e(yaml.dump(cfg)),
                'encoding': 'base64'
            }
        }
        return construct_valid_ovf_env(data=odata)

    def test_disabled_bounce_does_not_change_hostname(self):
        cfg = {'hostname_bounce': {'policy': 'off'}}
        ds = self._get_ds(self.get_ovf_env_with_dscfg('test-host', cfg))
        ds.get_data()
        self.assertEqual(0, self.set_hostname.call_count)

    @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
    def test_disabled_bounce_does_not_perform_bounce(
            self, perform_hostname_bounce):
        cfg = {'hostname_bounce': {'policy': 'off'}}
        ds = self._get_ds(self.get_ovf_env_with_dscfg('test-host', cfg))
        ds.get_data()
        self.assertEqual(0, perform_hostname_bounce.call_count)

    def test_same_hostname_does_not_change_hostname(self):
        host_name = 'unchanged-host-name'
        self.get_hostname.return_value = host_name
        cfg = {'hostname_bounce': {'policy': 'yes'}}
        ds = self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg))
        ds.get_data()
        self.assertEqual(0, self.set_hostname.call_count)

    @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
    def test_unchanged_hostname_does_not_perform_bounce(
            self, perform_hostname_bounce):
        host_name = 'unchanged-host-name'
        self.get_hostname.return_value = host_name
        cfg = {'hostname_bounce': {'policy': 'yes'}}
        ds = self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg))
        ds.get_data()
        self.assertEqual(0, perform_hostname_bounce.call_count)

    @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
    def test_force_performs_bounce_regardless(self, perform_hostname_bounce):
        host_name = 'unchanged-host-name'
        self.get_hostname.return_value = host_name
        cfg = {'hostname_bounce': {'policy': 'force'}}
        dsrc = self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg),
                            agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(1, perform_hostname_bounce.call_count)

    def test_bounce_skipped_on_ifupdown_absent(self):
        host_name = 'unchanged-host-name'
        self.get_hostname.return_value = host_name
        cfg = {'hostname_bounce': {'policy': 'force'}}
        dsrc = self._get_ds(self.get_ovf_env_with_dscfg(host_name, cfg),
                            agent_command=['not', '__builtin__'])
        patch_path = 'cloudinit.sources.DataSourceAzure.util.which'
        with mock.patch(patch_path) as m_which:
            m_which.return_value = None
            ret = self._get_and_setup(dsrc)
        self.assertEqual([mock.call('ifup')], m_which.call_args_list)
        self.assertTrue(ret)
        self.assertIn(
            "Skipping network bounce: ifupdown utils aren't present.",
            self.logs.getvalue())

    def test_different_hostnames_sets_hostname(self):
        expected_hostname = 'azure-expected-host-name'
        self.get_hostname.return_value = 'default-host-name'
        dsrc = self._get_ds(
            self.get_ovf_env_with_dscfg(expected_hostname, {}),
            agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(expected_hostname,
                         self.set_hostname.call_args_list[0][0][0])

    @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
    def test_different_hostnames_performs_bounce(
            self, perform_hostname_bounce):
        expected_hostname = 'azure-expected-host-name'
        self.get_hostname.return_value = 'default-host-name'
        dsrc = self._get_ds(
            self.get_ovf_env_with_dscfg(expected_hostname, {}),
            agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(1, perform_hostname_bounce.call_count)

    def test_different_hostnames_sets_hostname_back(self):
        initial_host_name = 'default-host-name'
        self.get_hostname.return_value = initial_host_name
        dsrc = self._get_ds(
            self.get_ovf_env_with_dscfg('some-host-name', {}),
            agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(initial_host_name,
                         self.set_hostname.call_args_list[-1][0][0])

    @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
    def test_failure_in_bounce_still_resets_host_name(
            self, perform_hostname_bounce):
        perform_hostname_bounce.side_effect = Exception
        initial_host_name = 'default-host-name'
        self.get_hostname.return_value = initial_host_name
        dsrc = self._get_ds(
            self.get_ovf_env_with_dscfg('some-host-name', {}),
            agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(initial_host_name,
                         self.set_hostname.call_args_list[-1][0][0])

    def test_environment_correct_for_bounce_command(self):
        interface = 'int0'
        hostname = 'my-new-host'
        old_hostname = 'my-old-host'
        self.get_hostname.return_value = old_hostname
        cfg = {'hostname_bounce': {'interface': interface, 'policy': 'force'}}
        data = self.get_ovf_env_with_dscfg(hostname, cfg)
        dsrc = self._get_ds(data, agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(1, self.subp.call_count)
        bounce_env = self.subp.call_args[1]['env']
        self.assertEqual(interface, bounce_env['interface'])
        self.assertEqual(hostname, bounce_env['hostname'])
        self.assertEqual(old_hostname, bounce_env['old_hostname'])

    def test_default_bounce_command_ifup_used_by_default(self):
        cfg = {'hostname_bounce': {'policy': 'force'}}
        data = self.get_ovf_env_with_dscfg('some-hostname', cfg)
        dsrc = self._get_ds(data, agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(1, self.subp.call_count)
        bounce_args = self.subp.call_args[1]['args']
        self.assertEqual(
            dsaz.BOUNCE_COMMAND_IFUP, bounce_args)

    @mock.patch('cloudinit.sources.DataSourceAzure.perform_hostname_bounce')
    def test_set_hostname_option_can_disable_bounce(
            self, perform_hostname_bounce):
        cfg = {'set_hostname': False, 'hostname_bounce': {'policy': 'force'}}
        data = self.get_ovf_env_with_dscfg('some-hostname', cfg)
        self._get_ds(data).get_data()

        self.assertEqual(0, perform_hostname_bounce.call_count)

    def test_set_hostname_option_can_disable_hostname_set(self):
        cfg = {'set_hostname': False, 'hostname_bounce': {'policy': 'force'}}
        data = self.get_ovf_env_with_dscfg('some-hostname', cfg)
        self._get_ds(data).get_data()

        self.assertEqual(0, self.set_hostname.call_count)
Example #33
0
class TestAzureDataSource(CiTestCase):

    with_logs = True

    def setUp(self):
        super(TestAzureDataSource, self).setUp()
        if PY26:
            raise SkipTest("Does not work on python 2.6")
        self.tmp = self.tmp_dir()

        # patch cloud_dir, so our 'seed_dir' is guaranteed empty
        self.paths = helpers.Paths(
            {'cloud_dir': self.tmp, 'run_dir': self.tmp})
        self.waagent_d = os.path.join(self.tmp, 'var', 'lib', 'waagent')

        self.patches = ExitStack()
        self.addCleanup(self.patches.close)

        super(TestAzureDataSource, self).setUp()

    def apply_patches(self, patches):
        for module, name, new in patches:
            self.patches.enter_context(mock.patch.object(module, name, new))

    def _get_mockds(self):
        sysctl_out = "dev.storvsc.3.%pnpinfo: "\
                     "classid=ba6163d9-04a1-4d29-b605-72e2ffb1dc7f "\
                     "deviceid=f8b3781b-1e82-4818-a1c3-63d806ec15bb\n"
        sysctl_out += "dev.storvsc.2.%pnpinfo: "\
                      "classid=ba6163d9-04a1-4d29-b605-72e2ffb1dc7f "\
                      "deviceid=f8b3781a-1e82-4818-a1c3-63d806ec15bb\n"
        sysctl_out += "dev.storvsc.1.%pnpinfo: "\
                      "classid=32412632-86cb-44a2-9b5c-50d1417354f5 "\
                      "deviceid=00000000-0001-8899-0000-000000000000\n"
        camctl_devbus = """
scbus0 on ata0 bus 0
scbus1 on ata1 bus 0
scbus2 on blkvsc0 bus 0
scbus3 on blkvsc1 bus 0
scbus4 on storvsc2 bus 0
scbus5 on storvsc3 bus 0
scbus-1 on xpt0 bus 0
        """
        camctl_dev = """
<Msft Virtual CD/ROM 1.0>          at scbus1 target 0 lun 0 (cd0,pass0)
<Msft Virtual Disk 1.0>            at scbus2 target 0 lun 0 (da0,pass1)
<Msft Virtual Disk 1.0>            at scbus3 target 1 lun 0 (da1,pass2)
        """
        self.apply_patches([
            (dsaz, 'get_dev_storvsc_sysctl', mock.MagicMock(
                return_value=sysctl_out)),
            (dsaz, 'get_camcontrol_dev_bus', mock.MagicMock(
                return_value=camctl_devbus)),
            (dsaz, 'get_camcontrol_dev', mock.MagicMock(
                return_value=camctl_dev))
        ])
        return dsaz

    def _get_ds(self, data, agent_command=None):

        def dsdevs():
            return data.get('dsdevs', [])

        def _invoke_agent(cmd):
            data['agent_invoked'] = cmd

        def _wait_for_files(flist, _maxwait=None, _naplen=None):
            data['waited'] = flist
            return []

        def _pubkeys_from_crt_files(flist):
            data['pubkey_files'] = flist
            return ["pubkey_from: %s" % f for f in flist]

        if data.get('ovfcontent') is not None:
            populate_dir(os.path.join(self.paths.seed_dir, "azure"),
                         {'ovf-env.xml': data['ovfcontent']})

        dsaz.BUILTIN_DS_CONFIG['data_dir'] = self.waagent_d

        self.get_metadata_from_fabric = mock.MagicMock(return_value={
            'public-keys': [],
        })

        self.instance_id = 'test-instance-id'

        def _dmi_mocks(key):
            if key == 'system-uuid':
                return self.instance_id
            elif key == 'chassis-asset-tag':
                return '7783-7084-3265-9085-8269-3286-77'

        self.apply_patches([
            (dsaz, 'list_possible_azure_ds_devs', dsdevs),
            (dsaz, 'invoke_agent', _invoke_agent),
            (dsaz, 'pubkeys_from_crt_files', _pubkeys_from_crt_files),
            (dsaz, 'perform_hostname_bounce', mock.MagicMock()),
            (dsaz, 'get_hostname', mock.MagicMock()),
            (dsaz, 'set_hostname', mock.MagicMock()),
            (dsaz, 'get_metadata_from_fabric', self.get_metadata_from_fabric),
            (dsaz.util, 'which', lambda x: True),
            (dsaz.util, 'read_dmi_data', mock.MagicMock(
                side_effect=_dmi_mocks)),
            (dsaz.util, 'wait_for_files', mock.MagicMock(
                side_effect=_wait_for_files)),
        ])

        dsrc = dsaz.DataSourceAzure(
            data.get('sys_cfg', {}), distro=None, paths=self.paths)
        if agent_command is not None:
            dsrc.ds_cfg['agent_command'] = agent_command

        return dsrc

    def _get_and_setup(self, dsrc):
        ret = dsrc.get_data()
        if ret:
            dsrc.setup(True)
        return ret

    def xml_equals(self, oxml, nxml):
        """Compare two sets of XML to make sure they are equal"""

        def create_tag_index(xml):
            et = ET.fromstring(xml)
            ret = {}
            for x in et.iter():
                ret[x.tag] = x
            return ret

        def tags_exists(x, y):
            for tag in x.keys():
                self.assertIn(tag, y)
            for tag in y.keys():
                self.assertIn(tag, x)

        def tags_equal(x, y):
            for x_tag, x_val in x.items():
                y_val = y.get(x_val.tag)
                self.assertEqual(x_val.text, y_val.text)

        old_cnt = create_tag_index(oxml)
        new_cnt = create_tag_index(nxml)
        tags_exists(old_cnt, new_cnt)
        tags_equal(old_cnt, new_cnt)

    def xml_notequals(self, oxml, nxml):
        try:
            self.xml_equals(oxml, nxml)
        except AssertionError:
            return
        raise AssertionError("XML is the same")

    def test_get_resource_disk(self):
        ds = self._get_mockds()
        dev = ds.get_resource_disk_on_freebsd(1)
        self.assertEqual("da1", dev)

    @mock.patch('cloudinit.util.subp')
    def test_find_freebsd_part_on_Azure(self, mock_subp):
        glabel_out = '''
gptid/fa52d426-c337-11e6-8911-00155d4c5e47  N/A  da0p1
                              label/rootfs  N/A  da0p2
                                label/swap  N/A  da0p3
'''
        mock_subp.return_value = (glabel_out, "")
        res = find_freebsd_part("/dev/label/rootfs")
        self.assertEqual("da0p2", res)

    def test_get_path_dev_freebsd_on_Azure(self):
        mnt_list = '''
/dev/label/rootfs  /                ufs     rw              1 1
devfs              /dev             devfs   rw,multilabel   0 0
fdescfs            /dev/fd          fdescfs rw              0 0
/dev/da1s1         /mnt/resource    ufs     rw              2 2
'''
        with mock.patch.object(os.path, 'exists',
                               return_value=True):
            res = get_path_dev_freebsd('/etc', mnt_list)
            self.assertIsNotNone(res)

    @mock.patch('cloudinit.sources.DataSourceAzure.util.read_dmi_data')
    def test_non_azure_dmi_chassis_asset_tag(self, m_read_dmi_data):
        """Report non-azure when DMI's chassis asset tag doesn't match.

        Return False when the asset tag doesn't match Azure's static
        AZURE_CHASSIS_ASSET_TAG.
        """
        # Return a non-matching asset tag value
        nonazure_tag = dsaz.AZURE_CHASSIS_ASSET_TAG + 'X'
        m_read_dmi_data.return_value = nonazure_tag
        dsrc = dsaz.DataSourceAzure(
            {}, distro=None, paths=self.paths)
        self.assertFalse(dsrc.get_data())
        self.assertEqual(
            "DEBUG: Non-Azure DMI asset tag '{0}' discovered.\n".format(
                nonazure_tag),
            self.logs.getvalue())

    def test_basic_seed_dir(self):
        odata = {'HostName': "myhost", 'UserName': "******"}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata),
                'sys_cfg': {}}

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(dsrc.userdata_raw, "")
        self.assertEqual(dsrc.metadata['local-hostname'], odata['HostName'])
        self.assertTrue(os.path.isfile(
            os.path.join(self.waagent_d, 'ovf-env.xml')))

    def test_waagent_d_has_0700_perms(self):
        # we expect /var/lib/waagent to be created 0700
        dsrc = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertTrue(os.path.isdir(self.waagent_d))
        self.assertEqual(stat.S_IMODE(os.stat(self.waagent_d).st_mode), 0o700)

    def test_user_cfg_set_agent_command_plain(self):
        # set dscfg in via plaintext
        # we must have friendly-to-xml formatted plaintext in yaml_cfg
        # not all plaintext is expected to work.
        yaml_cfg = "{agent_command: my_command}\n"
        cfg = yaml.safe_load(yaml_cfg)
        odata = {'HostName': "myhost", 'UserName': "******",
                 'dscfg': {'text': yaml_cfg, 'encoding': 'plain'}}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata)}

        dsrc = self._get_ds(data)
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(data['agent_invoked'], cfg['agent_command'])

    def test_user_cfg_set_agent_command(self):
        # set dscfg in via base64 encoded yaml
        cfg = {'agent_command': "my_command"}
        odata = {'HostName': "myhost", 'UserName': "******",
                 'dscfg': {'text': b64e(yaml.dump(cfg)),
                           'encoding': 'base64'}}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata)}

        dsrc = self._get_ds(data)
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(data['agent_invoked'], cfg['agent_command'])

    def test_sys_cfg_set_agent_command(self):
        sys_cfg = {'datasource': {'Azure': {'agent_command': '_COMMAND'}}}
        data = {'ovfcontent': construct_valid_ovf_env(data={}),
                'sys_cfg': sys_cfg}

        dsrc = self._get_ds(data)
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual(data['agent_invoked'], '_COMMAND')

    def test_username_used(self):
        odata = {'HostName': "myhost", 'UserName': "******"}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata)}

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(dsrc.cfg['system_info']['default_user']['name'],
                         "myuser")

    def test_password_given(self):
        odata = {'HostName': "myhost", 'UserName': "******",
                 'UserPassword': "******"}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata)}

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertTrue('default_user' in dsrc.cfg['system_info'])
        defuser = dsrc.cfg['system_info']['default_user']

        # default user should be updated username and should not be locked.
        self.assertEqual(defuser['name'], odata['UserName'])
        self.assertFalse(defuser['lock_passwd'])
        # passwd is crypt formated string $id$salt$encrypted
        # encrypting plaintext with salt value of everything up to final '$'
        # should equal that after the '$'
        pos = defuser['passwd'].rfind("$") + 1
        self.assertEqual(defuser['passwd'],
                         crypt.crypt(odata['UserPassword'],
                                     defuser['passwd'][0:pos]))

    def test_userdata_plain(self):
        mydata = "FOOBAR"
        odata = {'UserData': {'text': mydata, 'encoding': 'plain'}}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata)}

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(decode_binary(dsrc.userdata_raw), mydata)

    def test_userdata_found(self):
        mydata = "FOOBAR"
        odata = {'UserData': {'text': b64e(mydata), 'encoding': 'base64'}}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata)}

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(dsrc.userdata_raw, mydata.encode('utf-8'))

    def test_no_datasource_expected(self):
        # no source should be found if no seed_dir and no devs
        data = {}
        dsrc = self._get_ds({})
        ret = dsrc.get_data()
        self.assertFalse(ret)
        self.assertFalse('agent_invoked' in data)

    def test_cfg_has_pubkeys_fingerprint(self):
        odata = {'HostName': "myhost", 'UserName': "******"}
        mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': ''}]
        pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
        data = {'ovfcontent': construct_valid_ovf_env(data=odata,
                                                      pubkeys=pubkeys)}

        dsrc = self._get_ds(data, agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        for mypk in mypklist:
            self.assertIn(mypk, dsrc.cfg['_pubkeys'])
            self.assertIn('pubkey_from', dsrc.metadata['public-keys'][-1])

    def test_cfg_has_pubkeys_value(self):
        # make sure that provided key is used over fingerprint
        odata = {'HostName': "myhost", 'UserName': "******"}
        mypklist = [{'fingerprint': 'fp1', 'path': 'path1', 'value': 'value1'}]
        pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
        data = {'ovfcontent': construct_valid_ovf_env(data=odata,
                                                      pubkeys=pubkeys)}

        dsrc = self._get_ds(data, agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)

        for mypk in mypklist:
            self.assertIn(mypk, dsrc.cfg['_pubkeys'])
            self.assertIn(mypk['value'], dsrc.metadata['public-keys'])

    def test_cfg_has_no_fingerprint_has_value(self):
        # test value is used when fingerprint not provided
        odata = {'HostName': "myhost", 'UserName': "******"}
        mypklist = [{'fingerprint': None, 'path': 'path1', 'value': 'value1'}]
        pubkeys = [(x['fingerprint'], x['path'], x['value']) for x in mypklist]
        data = {'ovfcontent': construct_valid_ovf_env(data=odata,
                                                      pubkeys=pubkeys)}

        dsrc = self._get_ds(data, agent_command=['not', '__builtin__'])
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)

        for mypk in mypklist:
            self.assertIn(mypk['value'], dsrc.metadata['public-keys'])

    def test_default_ephemeral(self):
        # make sure the ephemeral device works
        odata = {}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata),
                'sys_cfg': {}}

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        cfg = dsrc.get_config_obj()

        self.assertEqual(dsrc.device_name_to_device("ephemeral0"),
                         dsaz.RESOURCE_DISK_PATH)
        assert 'disk_setup' in cfg
        assert 'fs_setup' in cfg
        self.assertIsInstance(cfg['disk_setup'], dict)
        self.assertIsInstance(cfg['fs_setup'], list)

    def test_provide_disk_aliases(self):
        # Make sure that user can affect disk aliases
        dscfg = {'disk_aliases': {'ephemeral0': '/dev/sdc'}}
        odata = {'HostName': "myhost", 'UserName': "******",
                 'dscfg': {'text': b64e(yaml.dump(dscfg)),
                           'encoding': 'base64'}}
        usercfg = {'disk_setup': {'/dev/sdc': {'something': '...'},
                                  'ephemeral0': False}}
        userdata = '#cloud-config' + yaml.dump(usercfg) + "\n"

        ovfcontent = construct_valid_ovf_env(data=odata, userdata=userdata)
        data = {'ovfcontent': ovfcontent, 'sys_cfg': {}}

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        cfg = dsrc.get_config_obj()
        self.assertTrue(cfg)

    def test_userdata_arrives(self):
        userdata = "This is my user-data"
        xml = construct_valid_ovf_env(data={}, userdata=userdata)
        data = {'ovfcontent': xml}
        dsrc = self._get_ds(data)
        dsrc.get_data()

        self.assertEqual(userdata.encode('us-ascii'), dsrc.userdata_raw)

    def test_password_redacted_in_ovf(self):
        odata = {'HostName': "myhost", 'UserName': "******",
                 'UserPassword': "******"}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata)}
        dsrc = self._get_ds(data)
        ret = dsrc.get_data()

        self.assertTrue(ret)
        ovf_env_path = os.path.join(self.waagent_d, 'ovf-env.xml')

        # The XML should not be same since the user password is redacted
        on_disk_ovf = load_file(ovf_env_path)
        self.xml_notequals(data['ovfcontent'], on_disk_ovf)

        # Make sure that the redacted password on disk is not used by CI
        self.assertNotEqual(dsrc.cfg.get('password'),
                            dsaz.DEF_PASSWD_REDACTION)

        # Make sure that the password was really encrypted
        et = ET.fromstring(on_disk_ovf)
        for elem in et.iter():
            if 'UserPassword' in elem.tag:
                self.assertEqual(dsaz.DEF_PASSWD_REDACTION, elem.text)

    def test_ovf_env_arrives_in_waagent_dir(self):
        xml = construct_valid_ovf_env(data={}, userdata="FOODATA")
        dsrc = self._get_ds({'ovfcontent': xml})
        dsrc.get_data()

        # 'data_dir' is '/var/lib/waagent' (walinux-agent's state dir)
        # we expect that the ovf-env.xml file is copied there.
        ovf_env_path = os.path.join(self.waagent_d, 'ovf-env.xml')
        self.assertTrue(os.path.exists(ovf_env_path))
        self.xml_equals(xml, load_file(ovf_env_path))

    def test_ovf_can_include_unicode(self):
        xml = construct_valid_ovf_env(data={})
        xml = u'\ufeff{0}'.format(xml)
        dsrc = self._get_ds({'ovfcontent': xml})
        dsrc.get_data()

    def test_exception_fetching_fabric_data_doesnt_propagate(self):
        """Errors communicating with fabric should warn, but return True."""
        dsrc = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
        dsrc.ds_cfg['agent_command'] = '__builtin__'
        self.get_metadata_from_fabric.side_effect = Exception
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)

    def test_fabric_data_included_in_metadata(self):
        dsrc = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
        dsrc.ds_cfg['agent_command'] = '__builtin__'
        self.get_metadata_from_fabric.return_value = {'test': 'value'}
        ret = self._get_and_setup(dsrc)
        self.assertTrue(ret)
        self.assertEqual('value', dsrc.metadata['test'])

    def test_instance_id_from_dmidecode_used(self):
        ds = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
        ds.get_data()
        self.assertEqual(self.instance_id, ds.metadata['instance-id'])

    def test_instance_id_from_dmidecode_used_for_builtin(self):
        ds = self._get_ds({'ovfcontent': construct_valid_ovf_env()})
        ds.ds_cfg['agent_command'] = '__builtin__'
        ds.get_data()
        self.assertEqual(self.instance_id, ds.metadata['instance-id'])

    @mock.patch("cloudinit.sources.DataSourceAzure.util.is_FreeBSD")
    @mock.patch("cloudinit.sources.DataSourceAzure._check_freebsd_cdrom")
    def test_list_possible_azure_ds_devs(self, m_check_fbsd_cdrom,
                                         m_is_FreeBSD):
        """On FreeBSD, possible devs should show /dev/cd0."""
        m_is_FreeBSD.return_value = True
        m_check_fbsd_cdrom.return_value = True
        self.assertEqual(dsaz.list_possible_azure_ds_devs(), ['/dev/cd0'])
        self.assertEqual(
            [mock.call("/dev/cd0")], m_check_fbsd_cdrom.call_args_list)

    @mock.patch('cloudinit.net.get_interface_mac')
    @mock.patch('cloudinit.net.get_devicelist')
    @mock.patch('cloudinit.net.device_driver')
    @mock.patch('cloudinit.net.generate_fallback_config')
    def test_network_config(self, mock_fallback, mock_dd,
                            mock_devlist, mock_get_mac):
        odata = {'HostName': "myhost", 'UserName': "******"}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata),
                'sys_cfg': {}}

        fallback_config = {
            'version': 1,
            'config': [{
                'type': 'physical', 'name': 'eth0',
                'mac_address': '00:11:22:33:44:55',
                'params': {'driver': 'hv_netsvc'},
                'subnets': [{'type': 'dhcp'}],
            }]
        }
        mock_fallback.return_value = fallback_config

        mock_devlist.return_value = ['eth0']
        mock_dd.return_value = ['hv_netsvc']
        mock_get_mac.return_value = '00:11:22:33:44:55'

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)

        netconfig = dsrc.network_config
        self.assertEqual(netconfig, fallback_config)
        mock_fallback.assert_called_with(blacklist_drivers=['mlx4_core'],
                                         config_driver=True)

    @mock.patch('cloudinit.net.get_interface_mac')
    @mock.patch('cloudinit.net.get_devicelist')
    @mock.patch('cloudinit.net.device_driver')
    @mock.patch('cloudinit.net.generate_fallback_config')
    def test_network_config_blacklist(self, mock_fallback, mock_dd,
                                      mock_devlist, mock_get_mac):
        odata = {'HostName': "myhost", 'UserName': "******"}
        data = {'ovfcontent': construct_valid_ovf_env(data=odata),
                'sys_cfg': {}}

        fallback_config = {
            'version': 1,
            'config': [{
                'type': 'physical', 'name': 'eth0',
                'mac_address': '00:11:22:33:44:55',
                'params': {'driver': 'hv_netsvc'},
                'subnets': [{'type': 'dhcp'}],
            }]
        }
        blacklist_config = {
            'type': 'physical',
            'name': 'eth1',
            'mac_address': '00:11:22:33:44:55',
            'params': {'driver': 'mlx4_core'}
        }
        mock_fallback.return_value = fallback_config

        mock_devlist.return_value = ['eth0', 'eth1']
        mock_dd.side_effect = [
            'hv_netsvc',  # list composition, skipped
            'mlx4_core',  # list composition, match
            'mlx4_core',  # config get driver name
        ]
        mock_get_mac.return_value = '00:11:22:33:44:55'

        dsrc = self._get_ds(data)
        ret = dsrc.get_data()
        self.assertTrue(ret)

        netconfig = dsrc.network_config
        expected_config = fallback_config
        expected_config['config'].append(blacklist_config)
        self.assertEqual(netconfig, expected_config)
Example #34
0
class TestNoCloudDataSource(CiTestCase):
    def setUp(self):
        super(TestNoCloudDataSource, self).setUp()
        self.tmp = self.tmp_dir()
        self.paths = helpers.Paths({
            'cloud_dir': self.tmp,
            'run_dir': self.tmp
        })

        self.cmdline = "root=TESTCMDLINE"

        self.mocks = ExitStack()
        self.addCleanup(self.mocks.close)

        self.mocks.enter_context(
            mock.patch.object(util, 'get_cmdline', return_value=self.cmdline))
        self.mocks.enter_context(
            mock.patch.object(util, 'read_dmi_data', return_value=None))

    def _test_fs_config_is_read(self, fs_label, fs_label_to_search):
        vfat_device = 'device-1'

        def m_mount_cb(device, callback, mtype):
            if (device == vfat_device):
                return {'meta-data': yaml.dump({'instance-id': 'IID'})}
            else:
                return {}

        def m_find_devs_with(query='', path=''):
            if 'TYPE=vfat' == query:
                return [vfat_device]
            elif 'LABEL={}'.format(fs_label) == query:
                return [vfat_device]
            else:
                return []

        self.mocks.enter_context(
            mock.patch.object(util,
                              'find_devs_with',
                              side_effect=m_find_devs_with))
        self.mocks.enter_context(
            mock.patch.object(util, 'mount_cb', side_effect=m_mount_cb))
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': fs_label_to_search}}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()

        self.assertEqual(dsrc.metadata.get('instance-id'), 'IID')
        self.assertTrue(ret)

    def test_nocloud_seed_dir_on_lxd(self, m_is_lxd):
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        ud = b"USER_DATA_HERE"
        seed_dir = os.path.join(self.paths.seed_dir, "nocloud")
        populate_dir(seed_dir, {
            'user-data': ud,
            'meta-data': yaml.safe_dump(md)
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, ud)
        self.assertEqual(dsrc.metadata, md)
        self.assertEqual(dsrc.platform_type, 'lxd')
        self.assertEqual(dsrc.subplatform, 'seed-dir (%s)' % seed_dir)
        self.assertTrue(ret)

    def test_nocloud_seed_dir_non_lxd_platform_is_nocloud(self, m_is_lxd):
        """Non-lxd environments will list nocloud as the platform."""
        m_is_lxd.return_value = False
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        seed_dir = os.path.join(self.paths.seed_dir, "nocloud")
        populate_dir(seed_dir, {
            'user-data': '',
            'meta-data': yaml.safe_dump(md)
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertTrue(dsrc.get_data())
        self.assertEqual(dsrc.platform_type, 'nocloud')
        self.assertEqual(dsrc.subplatform, 'seed-dir (%s)' % seed_dir)

    def test_fs_label(self, m_is_lxd):
        # find_devs_with should not be called ff fs_label is None
        class PsuedoException(Exception):
            pass

        self.mocks.enter_context(
            mock.patch.object(util,
                              'find_devs_with',
                              side_effect=PsuedoException))

        # by default, NoCloud should search for filesystems by label
        sys_cfg = {'datasource': {'NoCloud': {}}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertRaises(PsuedoException, dsrc.get_data)

        # but disabling searching should just end up with None found
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertFalse(ret)

    def test_fs_config_lowercase_label(self, m_is_lxd):
        self._test_fs_config_is_read('cidata', 'cidata')

    def test_fs_config_uppercase_label(self, m_is_lxd):
        self._test_fs_config_is_read('CIDATA', 'cidata')

    def test_fs_config_lowercase_label_search_uppercase(self, m_is_lxd):
        self._test_fs_config_is_read('cidata', 'CIDATA')

    def test_fs_config_uppercase_label_search_uppercase(self, m_is_lxd):
        self._test_fs_config_is_read('CIDATA', 'CIDATA')

    def test_no_datasource_expected(self, m_is_lxd):
        # no source should be found if no cmdline, config, and fs_label=None
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertFalse(dsrc.get_data())

    def test_seed_in_config(self, m_is_lxd):
        data = {
            'fs_label': None,
            'meta-data': yaml.safe_dump({'instance-id': 'IID'}),
            'user-data': b"USER_DATA_RAW",
        }

        sys_cfg = {'datasource': {'NoCloud': data}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, b"USER_DATA_RAW")
        self.assertEqual(dsrc.metadata.get('instance-id'), 'IID')
        self.assertTrue(ret)

    def test_nocloud_seed_with_vendordata(self, m_is_lxd):
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        ud = b"USER_DATA_HERE"
        vd = b"THIS IS MY VENDOR_DATA"

        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), {
            'user-data': ud,
            'meta-data': yaml.safe_dump(md),
            'vendor-data': vd
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, ud)
        self.assertEqual(dsrc.metadata, md)
        self.assertEqual(dsrc.vendordata_raw, vd)
        self.assertTrue(ret)

    def test_nocloud_no_vendordata(self, m_is_lxd):
        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), {
            'user-data': b"ud",
            'meta-data': "instance-id: IID\n"
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, b"ud")
        self.assertFalse(dsrc.vendordata)
        self.assertTrue(ret)

    def test_metadata_network_interfaces(self, m_is_lxd):
        gateway = "103.225.10.1"
        md = {
            'instance-id':
            'i-abcd',
            'local-hostname':
            'hostname1',
            'network-interfaces':
            textwrap.dedent("""\
                auto eth0
                iface eth0 inet static
                hwaddr 00:16:3e:70:e1:04
                address 103.225.10.12
                netmask 255.255.255.0
                gateway """ + gateway + """
                dns-servers 8.8.8.8""")
        }

        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), {
            'user-data': b"ud",
            'meta-data': yaml.dump(md) + "\n"
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        # very simple check just for the strings above
        self.assertIn(gateway, str(dsrc.network_config))

    def test_metadata_network_config(self, m_is_lxd):
        # network-config needs to get into network_config
        netconf = {
            'version':
            1,
            'config': [{
                'type': 'physical',
                'name': 'interface0',
                'subnets': [{
                    'type': 'dhcp'
                }]
            }]
        }
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"), {
                'user-data': b"ud",
                'meta-data': "instance-id: IID\n",
                'network-config': yaml.dump(netconf) + "\n"
            })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)

    def test_metadata_network_config_with_toplevel_network(self, m_is_lxd):
        """network-config may have 'network' top level key."""
        netconf = {'config': 'disabled'}
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"), {
                'user-data': b"ud",
                'meta-data': "instance-id: IID\n",
                'network-config': yaml.dump({'network': netconf}) + "\n"
            })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)

    def test_metadata_network_config_over_interfaces(self, m_is_lxd):
        # network-config should override meta-data/network-interfaces
        gateway = "103.225.10.1"
        md = {
            'instance-id':
            'i-abcd',
            'local-hostname':
            'hostname1',
            'network-interfaces':
            textwrap.dedent("""\
                auto eth0
                iface eth0 inet static
                hwaddr 00:16:3e:70:e1:04
                address 103.225.10.12
                netmask 255.255.255.0
                gateway """ + gateway + """
                dns-servers 8.8.8.8""")
        }

        netconf = {
            'version':
            1,
            'config': [{
                'type': 'physical',
                'name': 'interface0',
                'subnets': [{
                    'type': 'dhcp'
                }]
            }]
        }
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"), {
                'user-data': b"ud",
                'meta-data': yaml.dump(md) + "\n",
                'network-config': yaml.dump(netconf) + "\n"
            })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)
        self.assertNotIn(gateway, str(dsrc.network_config))
Example #35
0
class TestCloudStackPasswordFetching(CiTestCase):

    def setUp(self):
        super(TestCloudStackPasswordFetching, self).setUp()
        self.patches = ExitStack()
        self.addCleanup(self.patches.close)
        mod_name = 'cloudinit.sources.DataSourceCloudStack'
        self.patches.enter_context(mock.patch('{0}.ec2'.format(mod_name)))
        self.patches.enter_context(mock.patch('{0}.uhelp'.format(mod_name)))
        default_gw = "192.201.20.0"
        get_latest_lease = mock.MagicMock(return_value=None)
        self.patches.enter_context(mock.patch(
            mod_name + '.get_latest_lease', get_latest_lease))

        get_default_gw = mock.MagicMock(return_value=default_gw)
        self.patches.enter_context(mock.patch(
            mod_name + '.get_default_gateway', get_default_gw))

        get_networkd_server_address = mock.MagicMock(return_value=None)
        self.patches.enter_context(mock.patch(
            mod_name + '.dhcp.networkd_get_option_from_leases',
            get_networkd_server_address))
        self.tmp = self.tmp_dir()

    def _set_password_server_response(self, response_string):
        subp = mock.MagicMock(return_value=(response_string, ''))
        self.patches.enter_context(
            mock.patch('cloudinit.sources.DataSourceCloudStack.util.subp',
                       subp))
        return subp

    def test_empty_password_doesnt_create_config(self):
        self._set_password_server_response('')
        ds = DataSourceCloudStack(
            {}, None, helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertEqual({}, ds.get_config_obj())

    def test_saved_password_doesnt_create_config(self):
        self._set_password_server_response('saved_password')
        ds = DataSourceCloudStack(
            {}, None, helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertEqual({}, ds.get_config_obj())

    def test_password_sets_password(self):
        password = '******'
        self._set_password_server_response(password)
        ds = DataSourceCloudStack(
            {}, None, helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertEqual(password, ds.get_config_obj()['password'])

    def test_bad_request_doesnt_stop_ds_from_working(self):
        self._set_password_server_response('bad_request')
        ds = DataSourceCloudStack(
            {}, None, helpers.Paths({'run_dir': self.tmp}))
        self.assertTrue(ds.get_data())

    def assertRequestTypesSent(self, subp, expected_request_types):
        request_types = []
        for call in subp.call_args_list:
            args = call[0][0]
            for arg in args:
                if arg.startswith('DomU_Request'):
                    request_types.append(arg.split()[1])
        self.assertEqual(expected_request_types, request_types)

    def test_valid_response_means_password_marked_as_saved(self):
        password = '******'
        subp = self._set_password_server_response(password)
        ds = DataSourceCloudStack(
            {}, None, helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertRequestTypesSent(subp,
                                    ['send_my_password', 'saved_password'])

    def _check_password_not_saved_for(self, response_string):
        subp = self._set_password_server_response(response_string)
        ds = DataSourceCloudStack(
            {}, None, helpers.Paths({'run_dir': self.tmp}))
        ds.get_data()
        self.assertRequestTypesSent(subp, ['send_my_password'])

    def test_password_not_saved_if_empty(self):
        self._check_password_not_saved_for('')

    def test_password_not_saved_if_already_saved(self):
        self._check_password_not_saved_for('saved_password')

    def test_password_not_saved_if_bad_request(self):
        self._check_password_not_saved_for('bad_request')
Example #36
0
class TestNoCloudDataSource(CiTestCase):
    def setUp(self):
        super(TestNoCloudDataSource, self).setUp()
        self.tmp = self.tmp_dir()
        self.paths = helpers.Paths({
            'cloud_dir': self.tmp,
            'run_dir': self.tmp
        })

        self.cmdline = "root=TESTCMDLINE"

        self.mocks = ExitStack()
        self.addCleanup(self.mocks.close)

        self.mocks.enter_context(
            mock.patch.object(util, 'get_cmdline', return_value=self.cmdline))

    def test_nocloud_seed_dir(self):
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        ud = b"USER_DATA_HERE"
        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), {
            'user-data': ud,
            'meta-data': yaml.safe_dump(md)
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        ds = DataSourceNoCloud.DataSourceNoCloud

        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, ud)
        self.assertEqual(dsrc.metadata, md)
        self.assertTrue(ret)

    def test_fs_label(self):
        # find_devs_with should not be called ff fs_label is None
        ds = DataSourceNoCloud.DataSourceNoCloud

        class PsuedoException(Exception):
            pass

        self.mocks.enter_context(
            mock.patch.object(util,
                              'find_devs_with',
                              side_effect=PsuedoException))

        # by default, NoCloud should search for filesystems by label
        sys_cfg = {'datasource': {'NoCloud': {}}}
        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertRaises(PsuedoException, dsrc.get_data)

        # but disabling searching should just end up with None found
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertFalse(ret)

    def test_no_datasource_expected(self):
        # no source should be found if no cmdline, config, and fs_label=None
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        ds = DataSourceNoCloud.DataSourceNoCloud
        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertFalse(dsrc.get_data())

    def test_seed_in_config(self):
        ds = DataSourceNoCloud.DataSourceNoCloud

        data = {
            'fs_label': None,
            'meta-data': yaml.safe_dump({'instance-id': 'IID'}),
            'user-data': b"USER_DATA_RAW",
        }

        sys_cfg = {'datasource': {'NoCloud': data}}
        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, b"USER_DATA_RAW")
        self.assertEqual(dsrc.metadata.get('instance-id'), 'IID')
        self.assertTrue(ret)

    def test_nocloud_seed_with_vendordata(self):
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        ud = b"USER_DATA_HERE"
        vd = b"THIS IS MY VENDOR_DATA"

        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), {
            'user-data': ud,
            'meta-data': yaml.safe_dump(md),
            'vendor-data': vd
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        ds = DataSourceNoCloud.DataSourceNoCloud

        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, ud)
        self.assertEqual(dsrc.metadata, md)
        self.assertEqual(dsrc.vendordata_raw, vd)
        self.assertTrue(ret)

    def test_nocloud_no_vendordata(self):
        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), {
            'user-data': b"ud",
            'meta-data': "instance-id: IID\n"
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        ds = DataSourceNoCloud.DataSourceNoCloud

        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, b"ud")
        self.assertFalse(dsrc.vendordata)
        self.assertTrue(ret)

    def test_metadata_network_interfaces(self):
        gateway = "103.225.10.1"
        md = {
            'instance-id':
            'i-abcd',
            'local-hostname':
            'hostname1',
            'network-interfaces':
            textwrap.dedent("""\
                auto eth0
                iface eth0 inet static
                hwaddr 00:16:3e:70:e1:04
                address 103.225.10.12
                netmask 255.255.255.0
                gateway """ + gateway + """
                dns-servers 8.8.8.8""")
        }

        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"), {
            'user-data': b"ud",
            'meta-data': yaml.dump(md) + "\n"
        })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        ds = DataSourceNoCloud.DataSourceNoCloud

        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        # very simple check just for the strings above
        self.assertIn(gateway, str(dsrc.network_config))

    def test_metadata_network_config(self):
        # network-config needs to get into network_config
        netconf = {
            'version':
            1,
            'config': [{
                'type': 'physical',
                'name': 'interface0',
                'subnets': [{
                    'type': 'dhcp'
                }]
            }]
        }
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"), {
                'user-data': b"ud",
                'meta-data': "instance-id: IID\n",
                'network-config': yaml.dump(netconf) + "\n"
            })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        ds = DataSourceNoCloud.DataSourceNoCloud

        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)

    def test_metadata_network_config_over_interfaces(self):
        # network-config should override meta-data/network-interfaces
        gateway = "103.225.10.1"
        md = {
            'instance-id':
            'i-abcd',
            'local-hostname':
            'hostname1',
            'network-interfaces':
            textwrap.dedent("""\
                auto eth0
                iface eth0 inet static
                hwaddr 00:16:3e:70:e1:04
                address 103.225.10.12
                netmask 255.255.255.0
                gateway """ + gateway + """
                dns-servers 8.8.8.8""")
        }

        netconf = {
            'version':
            1,
            'config': [{
                'type': 'physical',
                'name': 'interface0',
                'subnets': [{
                    'type': 'dhcp'
                }]
            }]
        }
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"), {
                'user-data': b"ud",
                'meta-data': yaml.dump(md) + "\n",
                'network-config': yaml.dump(netconf) + "\n"
            })

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        ds = DataSourceNoCloud.DataSourceNoCloud

        dsrc = ds(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)
        self.assertNotIn(gateway, str(dsrc.network_config))
Example #37
0
class TestNoCloudDataSource(CiTestCase):

    def setUp(self):
        super(TestNoCloudDataSource, self).setUp()
        self.tmp = self.tmp_dir()
        self.paths = helpers.Paths(
            {'cloud_dir': self.tmp, 'run_dir': self.tmp})

        self.cmdline = "root=TESTCMDLINE"

        self.mocks = ExitStack()
        self.addCleanup(self.mocks.close)

        self.mocks.enter_context(
            mock.patch.object(util, 'get_cmdline', return_value=self.cmdline))
        self.mocks.enter_context(
            mock.patch.object(util, 'read_dmi_data', return_value=None))

    def _test_fs_config_is_read(self, fs_label, fs_label_to_search):
        vfat_device = 'device-1'

        def m_mount_cb(device, callback, mtype):
            if (device == vfat_device):
                return {'meta-data': yaml.dump({'instance-id': 'IID'})}
            else:
                return {}

        def m_find_devs_with(query='', path=''):
            if 'TYPE=vfat' == query:
                return [vfat_device]
            elif 'LABEL={}'.format(fs_label) == query:
                return [vfat_device]
            else:
                return []

        self.mocks.enter_context(
            mock.patch.object(util, 'find_devs_with',
                              side_effect=m_find_devs_with))
        self.mocks.enter_context(
            mock.patch.object(util, 'mount_cb',
                              side_effect=m_mount_cb))
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': fs_label_to_search}}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()

        self.assertEqual(dsrc.metadata.get('instance-id'), 'IID')
        self.assertTrue(ret)

    def test_nocloud_seed_dir_on_lxd(self, m_is_lxd):
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        ud = b"USER_DATA_HERE"
        seed_dir = os.path.join(self.paths.seed_dir, "nocloud")
        populate_dir(seed_dir,
                     {'user-data': ud, 'meta-data': yaml.safe_dump(md)})

        sys_cfg = {
            'datasource': {'NoCloud': {'fs_label': None}}
        }

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, ud)
        self.assertEqual(dsrc.metadata, md)
        self.assertEqual(dsrc.platform_type, 'lxd')
        self.assertEqual(
            dsrc.subplatform, 'seed-dir (%s)' % seed_dir)
        self.assertTrue(ret)

    def test_nocloud_seed_dir_non_lxd_platform_is_nocloud(self, m_is_lxd):
        """Non-lxd environments will list nocloud as the platform."""
        m_is_lxd.return_value = False
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        seed_dir = os.path.join(self.paths.seed_dir, "nocloud")
        populate_dir(seed_dir,
                     {'user-data': '', 'meta-data': yaml.safe_dump(md)})

        sys_cfg = {
            'datasource': {'NoCloud': {'fs_label': None}}
        }

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertTrue(dsrc.get_data())
        self.assertEqual(dsrc.platform_type, 'nocloud')
        self.assertEqual(
            dsrc.subplatform, 'seed-dir (%s)' % seed_dir)

    def test_fs_label(self, m_is_lxd):
        # find_devs_with should not be called ff fs_label is None
        class PsuedoException(Exception):
            pass

        self.mocks.enter_context(
            mock.patch.object(util, 'find_devs_with',
                              side_effect=PsuedoException))

        # by default, NoCloud should search for filesystems by label
        sys_cfg = {'datasource': {'NoCloud': {}}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertRaises(PsuedoException, dsrc.get_data)

        # but disabling searching should just end up with None found
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertFalse(ret)

    def test_fs_config_lowercase_label(self, m_is_lxd):
        self._test_fs_config_is_read('cidata', 'cidata')

    def test_fs_config_uppercase_label(self, m_is_lxd):
        self._test_fs_config_is_read('CIDATA', 'cidata')

    def test_fs_config_lowercase_label_search_uppercase(self, m_is_lxd):
        self._test_fs_config_is_read('cidata', 'CIDATA')

    def test_fs_config_uppercase_label_search_uppercase(self, m_is_lxd):
        self._test_fs_config_is_read('CIDATA', 'CIDATA')

    def test_no_datasource_expected(self, m_is_lxd):
        # no source should be found if no cmdline, config, and fs_label=None
        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        self.assertFalse(dsrc.get_data())

    def test_seed_in_config(self, m_is_lxd):
        data = {
            'fs_label': None,
            'meta-data': yaml.safe_dump({'instance-id': 'IID'}),
            'user-data': b"USER_DATA_RAW",
        }

        sys_cfg = {'datasource': {'NoCloud': data}}
        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, b"USER_DATA_RAW")
        self.assertEqual(dsrc.metadata.get('instance-id'), 'IID')
        self.assertTrue(ret)

    def test_nocloud_seed_with_vendordata(self, m_is_lxd):
        md = {'instance-id': 'IID', 'dsmode': 'local'}
        ud = b"USER_DATA_HERE"
        vd = b"THIS IS MY VENDOR_DATA"

        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
                     {'user-data': ud, 'meta-data': yaml.safe_dump(md),
                      'vendor-data': vd})

        sys_cfg = {
            'datasource': {'NoCloud': {'fs_label': None}}
        }

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, ud)
        self.assertEqual(dsrc.metadata, md)
        self.assertEqual(dsrc.vendordata_raw, vd)
        self.assertTrue(ret)

    def test_nocloud_no_vendordata(self, m_is_lxd):
        populate_dir(os.path.join(self.paths.seed_dir, "nocloud"),
                     {'user-data': b"ud", 'meta-data': "instance-id: IID\n"})

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertEqual(dsrc.userdata_raw, b"ud")
        self.assertFalse(dsrc.vendordata)
        self.assertTrue(ret)

    def test_metadata_network_interfaces(self, m_is_lxd):
        gateway = "103.225.10.1"
        md = {
            'instance-id': 'i-abcd',
            'local-hostname': 'hostname1',
            'network-interfaces': textwrap.dedent("""\
                auto eth0
                iface eth0 inet static
                hwaddr 00:16:3e:70:e1:04
                address 103.225.10.12
                netmask 255.255.255.0
                gateway """ + gateway + """
                dns-servers 8.8.8.8""")}

        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"),
            {'user-data': b"ud",
             'meta-data': yaml.dump(md) + "\n"})

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        # very simple check just for the strings above
        self.assertIn(gateway, str(dsrc.network_config))

    def test_metadata_network_config(self, m_is_lxd):
        # network-config needs to get into network_config
        netconf = {'version': 1,
                   'config': [{'type': 'physical', 'name': 'interface0',
                               'subnets': [{'type': 'dhcp'}]}]}
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"),
            {'user-data': b"ud",
             'meta-data': "instance-id: IID\n",
             'network-config': yaml.dump(netconf) + "\n"})

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)

    def test_metadata_network_config_with_toplevel_network(self, m_is_lxd):
        """network-config may have 'network' top level key."""
        netconf = {'config': 'disabled'}
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"),
            {'user-data': b"ud",
             'meta-data': "instance-id: IID\n",
             'network-config': yaml.dump({'network': netconf}) + "\n"})

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)

    def test_metadata_network_config_over_interfaces(self, m_is_lxd):
        # network-config should override meta-data/network-interfaces
        gateway = "103.225.10.1"
        md = {
            'instance-id': 'i-abcd',
            'local-hostname': 'hostname1',
            'network-interfaces': textwrap.dedent("""\
                auto eth0
                iface eth0 inet static
                hwaddr 00:16:3e:70:e1:04
                address 103.225.10.12
                netmask 255.255.255.0
                gateway """ + gateway + """
                dns-servers 8.8.8.8""")}

        netconf = {'version': 1,
                   'config': [{'type': 'physical', 'name': 'interface0',
                               'subnets': [{'type': 'dhcp'}]}]}
        populate_dir(
            os.path.join(self.paths.seed_dir, "nocloud"),
            {'user-data': b"ud",
             'meta-data': yaml.dump(md) + "\n",
             'network-config': yaml.dump(netconf) + "\n"})

        sys_cfg = {'datasource': {'NoCloud': {'fs_label': None}}}

        dsrc = dsNoCloud(sys_cfg=sys_cfg, distro=None, paths=self.paths)
        ret = dsrc.get_data()
        self.assertTrue(ret)
        self.assertEqual(netconf, dsrc.network_config)
        self.assertNotIn(gateway, str(dsrc.network_config))
Example #38
0
 def setUp(self):
     super(TestGetMbrHddSize, self).setUp()
     self.patches = ExitStack()
     self.subp = self.patches.enter_context(
         mock.patch.object(cc_disk_setup.util, 'subp'))