This is an automated email from the ASF dual-hosted git repository. dahn pushed a commit to branch 4.20 in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push: new 011fced91ed ehancement: add password to configdrive vendor_data.json (#10061) 011fced91ed is described below commit 011fced91ed4cdd6c839abf977fd2b0c8c27a544 Author: Phsm Qwerty <p...@users.noreply.github.com> AuthorDate: Mon May 12 16:16:54 2025 +0200 ehancement: add password to configdrive vendor_data.json (#10061) --- .../storage/configdrive/ConfigDriveBuilder.java | 43 +++++++++++++++++++++- .../configdrive/ConfigDriveBuilderTest.java | 20 +++++----- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/engine/storage/configdrive/src/main/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilder.java b/engine/storage/configdrive/src/main/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilder.java index 58cc341a87b..d57afbb0a23 100644 --- a/engine/storage/configdrive/src/main/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilder.java +++ b/engine/storage/configdrive/src/main/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilder.java @@ -126,7 +126,26 @@ public class ConfigDriveBuilder { File openStackFolder = new File(tempDirName + ConfigDrive.openStackConfigDriveName); - writeVendorEmptyJsonFile(openStackFolder); + /* + Try to find VM password in the vmData. + If it is found, then write it into vendor-data.json + */ + String vmPassword = ""; + for (String[] item : vmData) { + String dataType = item[CONFIGDATA_DIR]; + String fileName = item[CONFIGDATA_FILE]; + String content = item[CONFIGDATA_CONTENT]; + if (PASSWORD_FILE.equals(fileName)) { + vmPassword = content; + break; + } + } + if (vmPassword.equals("")) { + writeVendorDataJsonFile(openStackFolder); + } else { + writeVendorDataJsonFile(openStackFolder, vmPassword); + } + writeNetworkData(nics, supportedServices, openStackFolder); for (NicProfile nic: nics) { if (supportedServices.get(nic.getId()).contains(Network.Service.UserData)) { @@ -253,7 +272,7 @@ public class ConfigDriveBuilder { * * If the folder does not exist, and we cannot create it, we throw a {@link CloudRuntimeException}. */ - static void writeVendorEmptyJsonFile(File openStackFolder) { + static void writeVendorDataJsonFile(File openStackFolder) { if (openStackFolder.exists() || openStackFolder.mkdirs()) { writeFile(openStackFolder, "vendor_data.json", "{}"); } else { @@ -261,6 +280,26 @@ public class ConfigDriveBuilder { } } + /** + * Writes vendor data containing Cloudstack-generated password into vendor-data.json + * + * If the folder does not exist, and we cannot create it, we throw a {@link CloudRuntimeException}. + */ + static void writeVendorDataJsonFile(File openStackFolder, String password) { + if (openStackFolder.exists() || openStackFolder.mkdirs()) { + writeFile( + openStackFolder, + "vendor_data.json", + String.format( + "{\"cloud-init\": \"#cloud-config\\npassword: %s\\nchpasswd:\\n expire: False\"}", + password + ) + ); + } else { + throw new CloudRuntimeException("Failed to create folder " + openStackFolder); + } + } + /** * Creates the {@link JsonObject} with VM's metadata. The vmData is a list of arrays; we expect this list to have the following entries: * <ul> diff --git a/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java b/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java index 3effdb5ba21..c04ff0a1601 100644 --- a/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java +++ b/engine/storage/configdrive/src/test/java/org/apache/cloudstack/storage/configdrive/ConfigDriveBuilderTest.java @@ -134,7 +134,7 @@ public class ConfigDriveBuilderTest { @Test(expected = CloudRuntimeException.class) public void buildConfigDriveTestIoException() { try (MockedStatic<ConfigDriveBuilder> configDriveBuilderMocked = Mockito.mockStatic(ConfigDriveBuilder.class)) { - configDriveBuilderMocked.when(() -> ConfigDriveBuilder.writeVendorEmptyJsonFile(nullable(File.class))).thenThrow(CloudRuntimeException.class); + configDriveBuilderMocked.when(() -> ConfigDriveBuilder.writeVendorDataJsonFile(nullable(File.class))).thenThrow(CloudRuntimeException.class); Mockito.when(ConfigDriveBuilder.buildConfigDrive(null, new ArrayList<>(), "teste", "C:", null, supportedServices)).thenCallRealMethod(); ConfigDriveBuilder.buildConfigDrive(null, new ArrayList<>(), "teste", "C:", null, supportedServices); } @@ -144,7 +144,7 @@ public class ConfigDriveBuilderTest { public void buildConfigDriveTest() { try (MockedStatic<ConfigDriveBuilder> configDriveBuilderMocked = Mockito.mockStatic(ConfigDriveBuilder.class)) { - configDriveBuilderMocked.when(() -> ConfigDriveBuilder.writeVendorEmptyJsonFile(Mockito.any(File.class))).then(invocationOnMock -> null); + configDriveBuilderMocked.when(() -> ConfigDriveBuilder.writeVendorDataJsonFile(Mockito.any(File.class))).then(invocationOnMock -> null); configDriveBuilderMocked.when(() -> ConfigDriveBuilder.writeVmMetadata(Mockito.anyList(), Mockito.anyString(), Mockito.any(File.class), anyMap())).then(invocationOnMock -> null); @@ -163,7 +163,7 @@ public class ConfigDriveBuilderTest { Assert.assertEquals("mockIsoDataBase64", returnedIsoData); configDriveBuilderMocked.verify(() -> { - ConfigDriveBuilder.writeVendorEmptyJsonFile(Mockito.any(File.class)); + ConfigDriveBuilder.writeVendorDataJsonFile(Mockito.any(File.class)); ConfigDriveBuilder.writeVmMetadata(Mockito.anyList(), Mockito.anyString(), Mockito.any(File.class), anyMap()); ConfigDriveBuilder.linkUserData(Mockito.anyString()); ConfigDriveBuilder.generateAndRetrieveIsoAsBase64Iso(Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); @@ -172,23 +172,23 @@ public class ConfigDriveBuilderTest { } @Test(expected = CloudRuntimeException.class) - public void writeVendorEmptyJsonFileTestCannotCreateOpenStackFolder() { + public void writeVendorDataJsonFileTestCannotCreateOpenStackFolder() { File folderFileMock = Mockito.mock(File.class); Mockito.doReturn(false).when(folderFileMock).mkdirs(); - ConfigDriveBuilder.writeVendorEmptyJsonFile(folderFileMock); + ConfigDriveBuilder.writeVendorDataJsonFile(folderFileMock); } @Test(expected = CloudRuntimeException.class) - public void writeVendorEmptyJsonFileTest() { + public void writeVendorDataJsonFileTest() { File folderFileMock = Mockito.mock(File.class); Mockito.doReturn(false).when(folderFileMock).mkdirs(); - ConfigDriveBuilder.writeVendorEmptyJsonFile(folderFileMock); + ConfigDriveBuilder.writeVendorDataJsonFile(folderFileMock); } @Test - public void writeVendorEmptyJsonFileTestCreatingFolder() { + public void writeVendorDataJsonFileTestCreatingFolder() { try (MockedStatic<ConfigDriveBuilder> configDriveBuilderMocked = Mockito.mockStatic(ConfigDriveBuilder.class)) { File folderFileMock = Mockito.mock(File.class); @@ -196,9 +196,9 @@ public class ConfigDriveBuilderTest { Mockito.doReturn(true).when(folderFileMock).mkdirs(); //force execution of real method - configDriveBuilderMocked.when(() -> ConfigDriveBuilder.writeVendorEmptyJsonFile(folderFileMock)).thenCallRealMethod(); + configDriveBuilderMocked.when(() -> ConfigDriveBuilder.writeVendorDataJsonFile(folderFileMock)).thenCallRealMethod(); - ConfigDriveBuilder.writeVendorEmptyJsonFile(folderFileMock); + ConfigDriveBuilder.writeVendorDataJsonFile(folderFileMock); Mockito.verify(folderFileMock).exists(); Mockito.verify(folderFileMock).mkdirs();