Skip to content

Commit d7b2b62

Browse files
committed
Add support for providing userdata to system VMs
1 parent 69998f7 commit d7b2b62

File tree

15 files changed

+255
-5
lines changed

15 files changed

+255
-5
lines changed

engine/api/src/main/java/com/cloud/vm/VirtualMachineManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ public interface VirtualMachineManager extends Manager {
106106
ConfigKey<Boolean> VmSyncPowerStateTransitioning = new ConfigKey<>("Advanced", Boolean.class, "vm.sync.power.state.transitioning", "true",
107107
"Whether to sync power states of the transitioning and stalled VMs while processing VM power reports.", false);
108108

109+
ConfigKey<Boolean> SystemVmEnableUserData = new ConfigKey<>(Boolean.class, "systemvm.userdata.enabled", "Advanced", "false",
110+
"Enable user data for system VMs. When enabled, the CPVM, SSVM, and Router system VMs will use the values from the global settings consoleproxy.userdata, secstorage.userdata, and router.userdata, respectively, to provide cloud-init user data to the VM.",
111+
true, ConfigKey.Scope.Zone, null);
109112

110113
interface Topics {
111114
String VM_POWER_STATE = "vm.powerstate";

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5121,7 +5121,7 @@ public ConfigKey<?>[] getConfigKeys() {
51215121
VmConfigDriveLabel, VmConfigDriveOnPrimaryPool, VmConfigDriveForceHostCacheUse, VmConfigDriveUseHostCacheOnUnsupportedPool,
51225122
HaVmRestartHostUp, ResourceCountRunningVMsonly, AllowExposeHypervisorHostname, AllowExposeHypervisorHostnameAccountLevel, SystemVmRootDiskSize,
51235123
AllowExposeDomainInMetadata, MetadataCustomCloudName, VmMetadataManufacturer, VmMetadataProductName,
5124-
VmSyncPowerStateTransitioning
5124+
VmSyncPowerStateTransitioning, SystemVmEnableUserData
51255125
};
51265126
}
51275127

framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,67 @@ public class ConfigKey<T> {
4141
public static final String CATEGORY_ADVANCED = "Advanced";
4242
public static final String CATEGORY_ALERT = "Alert";
4343
public static final String CATEGORY_NETWORK = "Network";
44+
public static final String CATEGORY_SECURE = "Secure";
4445
public static final String CATEGORY_SYSTEM = "System";
4546

47+
// Configuration Groups to be used to define group for a config key
48+
// Group name, description, precedence
49+
public static final Ternary<String, String, Long> GROUP_MISCELLANEOUS = new Ternary<>("Miscellaneous", "Miscellaneous configuration", 999L);
50+
public static final Ternary<String, String, Long> GROUP_ACCESS = new Ternary<>("Access", "Identity and Access management configuration", 1L);
51+
public static final Ternary<String, String, Long> GROUP_COMPUTE = new Ternary<>("Compute", "Compute configuration", 2L);
52+
public static final Ternary<String, String, Long> GROUP_STORAGE = new Ternary<>("Storage", "Storage configuration", 3L);
53+
public static final Ternary<String, String, Long> GROUP_NETWORK = new Ternary<>("Network", "Network configuration", 4L);
54+
public static final Ternary<String, String, Long> GROUP_HYPERVISOR = new Ternary<>("Hypervisor", "Hypervisor specific configuration", 5L);
55+
public static final Ternary<String, String, Long> GROUP_MANAGEMENT_SERVER = new Ternary<>("Management Server", "Management Server configuration", 6L);
56+
public static final Ternary<String, String, Long> GROUP_SYSTEM_VMS = new Ternary<>("System VMs", "System VMs related configuration", 7L);
57+
public static final Ternary<String, String, Long> GROUP_INFRASTRUCTURE = new Ternary<>("Infrastructure", "Infrastructure configuration", 8L);
58+
public static final Ternary<String, String, Long> GROUP_USAGE_SERVER = new Ternary<>("Usage Server", "Usage Server related configuration", 9L);
59+
60+
// Configuration Subgroups to be used to define subgroup for a config key
61+
// Subgroup name, description, precedence
62+
public static final Pair<String, Long> SUBGROUP_OTHERS = new Pair<>("Others", 999L);
63+
public static final Pair<String, Long> SUBGROUP_ACCOUNT = new Pair<>("Account", 1L);
64+
public static final Pair<String, Long> SUBGROUP_DOMAIN = new Pair<>("Domain", 2L);
65+
public static final Pair<String, Long> SUBGROUP_PROJECT = new Pair<>("Project", 3L);
66+
public static final Pair<String, Long> SUBGROUP_LDAP = new Pair<>("LDAP", 4L);
67+
public static final Pair<String, Long> SUBGROUP_SAML = new Pair<>("SAML", 5L);
68+
public static final Pair<String, Long> SUBGROUP_VIRTUAL_MACHINE = new Pair<>("Virtual Machine", 1L);
69+
public static final Pair<String, Long> SUBGROUP_KUBERNETES = new Pair<>("Kubernetes", 2L);
70+
public static final Pair<String, Long> SUBGROUP_HIGH_AVAILABILITY = new Pair<>("High Availability", 3L);
71+
public static final Pair<String, Long> SUBGROUP_IMAGES = new Pair<>("Images", 1L);
72+
public static final Pair<String, Long> SUBGROUP_VOLUME = new Pair<>("Volume", 2L);
73+
public static final Pair<String, Long> SUBGROUP_SNAPSHOT = new Pair<>("Snapshot", 3L);
74+
public static final Pair<String, Long> SUBGROUP_VM_SNAPSHOT = new Pair<>("VM Snapshot", 4L);
75+
public static final Pair<String, Long> SUBGROUP_NETWORK = new Pair<>("Network", 1L);
76+
public static final Pair<String, Long> SUBGROUP_DHCP = new Pair<>("DHCP", 2L);
77+
public static final Pair<String, Long> SUBGROUP_VPC = new Pair<>("VPC", 3L);
78+
public static final Pair<String, Long> SUBGROUP_LOADBALANCER = new Pair<>("LoadBalancer", 4L);
79+
public static final Pair<String, Long> SUBGROUP_API = new Pair<>("API", 1L);
80+
public static final Pair<String, Long> SUBGROUP_ALERTS = new Pair<>("Alerts", 2L);
81+
public static final Pair<String, Long> SUBGROUP_EVENTS = new Pair<>("Events", 3L);
82+
public static final Pair<String, Long> SUBGROUP_SECURITY = new Pair<>("Security", 4L);
83+
public static final Pair<String, Long> SUBGROUP_USAGE = new Pair<>("Usage", 1L);
84+
public static final Pair<String, Long> SUBGROUP_LIMITS = new Pair<>("Limits", 6L);
85+
public static final Pair<String, Long> SUBGROUP_JOBS = new Pair<>("Jobs", 7L);
86+
public static final Pair<String, Long> SUBGROUP_AGENT = new Pair<>("Agent", 8L);
87+
public static final Pair<String, Long> SUBGROUP_HYPERVISOR = new Pair<>("Hypervisor", 1L);
88+
public static final Pair<String, Long> SUBGROUP_KVM = new Pair<>("KVM", 2L);
89+
public static final Pair<String, Long> SUBGROUP_VMWARE = new Pair<>("VMware", 3L);
90+
public static final Pair<String, Long> SUBGROUP_XENSERVER = new Pair<>("XenServer", 4L);
91+
public static final Pair<String, Long> SUBGROUP_OVM = new Pair<>("OVM", 5L);
92+
public static final Pair<String, Long> SUBGROUP_BAREMETAL = new Pair<>("Baremetal", 6L);
93+
public static final Pair<String, Long> SUBGROUP_CONSOLE_PROXY_VM = new Pair<>("ConsoleProxyVM", 1L);
94+
public static final Pair<String, Long> SUBGROUP_SEC_STORAGE_VM = new Pair<>("SecStorageVM", 2L);
95+
public static final Pair<String, Long> SUBGROUP_VIRTUAL_ROUTER = new Pair<>("VirtualRouter", 3L);
96+
public static final Pair<String, Long> SUBGROUP_DIAGNOSTICS = new Pair<>("Diagnostics", 4L);
97+
public static final Pair<String, Long> SUBGROUP_PRIMARY_STORAGE = new Pair<>("Primary Storage", 1L);
98+
public static final Pair<String, Long> SUBGROUP_SECONDARY_STORAGE = new Pair<>("Secondary Storage", 2L);
99+
public static final Pair<String, Long> SUBGROUP_BACKUP_AND_RECOVERY = new Pair<>("Backup & Recovery", 1L);
100+
public static final Pair<String, Long> SUBGROUP_CERTIFICATE_AUTHORITY = new Pair<>("Certificate Authority", 2L);
101+
public static final Pair<String, Long> SUBGROUP_QUOTA = new Pair<>("Quota", 3L);
102+
public static final Pair<String, Long> SUBGROUP_CLOUDIAN = new Pair<>("Cloudian", 4L);
103+
public static final Pair<String, Long> SUBGROUP_DRS = new Pair<>("DRS", 4L);
104+
46105
public enum Scope {
47106
Global(null, 1),
48107
Zone(Global, 1 << 1),

plugins/network-elements/elastic-loadbalancer/src/main/java/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.cloud.network.lb;
1818

1919
import java.util.ArrayList;
20+
import java.util.Base64;
2021
import java.util.Collections;
2122
import java.util.HashSet;
2223
import java.util.List;
@@ -35,6 +36,7 @@
3536
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
3637
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
3738
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
39+
import org.apache.commons.lang3.StringUtils;
3840
import org.springframework.stereotype.Component;
3941

4042
import com.cloud.agent.AgentManager;
@@ -101,6 +103,9 @@
101103
import com.cloud.vm.dao.DomainRouterDao;
102104
import com.cloud.vm.dao.NicDao;
103105

106+
import static com.cloud.network.router.VirtualNetworkApplianceManager.RouterUserData;
107+
import static com.cloud.vm.VirtualMachineManager.SystemVmEnableUserData;
108+
104109
@Component
105110
public class ElasticLoadBalancerManagerImpl extends ManagerBase implements ElasticLoadBalancerManager, VirtualMachineGuru {
106111

@@ -477,6 +482,15 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl
477482
}
478483
String msPublicKey = _configDao.getValue("ssh.publickey");
479484
buf.append(" authorized_key=").append(VirtualMachineGuru.getEncodedMsPublicKey(msPublicKey));
485+
486+
if (SystemVmEnableUserData.valueIn(dc.getId())) {
487+
String userData = RouterUserData.valueIn(dc.getId());
488+
if (StringUtils.isNotBlank(userData)) {
489+
String encodedUserData = Base64.getEncoder().encodeToString(userData.getBytes());
490+
buf.append(" userdata=").append(encodedUserData);
491+
}
492+
}
493+
480494
if (logger.isDebugEnabled()) {
481495
logger.debug("Boot Args for " + profile + ": " + buf.toString());
482496
}

plugins/network-elements/internal-loadbalancer/src/main/java/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@
2121
import static com.cloud.hypervisor.Hypervisor.HypervisorType.LXC;
2222
import static com.cloud.hypervisor.Hypervisor.HypervisorType.VMware;
2323
import static com.cloud.hypervisor.Hypervisor.HypervisorType.XenServer;
24+
import static com.cloud.network.router.VirtualNetworkApplianceManager.RouterUserData;
25+
import static com.cloud.vm.VirtualMachineManager.SystemVmEnableUserData;
2426

2527
import java.util.ArrayList;
2628
import java.util.Arrays;
29+
import java.util.Base64;
2730
import java.util.Iterator;
2831
import java.util.LinkedHashMap;
2932
import java.util.List;
@@ -126,6 +129,7 @@
126129
import com.cloud.vm.VirtualMachineProfile.Param;
127130
import com.cloud.vm.dao.DomainRouterDao;
128131
import com.cloud.vm.dao.NicDao;
132+
import org.apache.commons.lang3.StringUtils;
129133

130134
public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements InternalLoadBalancerVMManager, InternalLoadBalancerVMService, VirtualMachineGuru {
131135
static final private String InternalLbVmNamePrefix = "b";
@@ -243,6 +247,15 @@ public boolean finalizeVirtualMachineProfile(final VirtualMachineProfile profile
243247
final String type = "ilbvm";
244248
buf.append(" type=" + type);
245249

250+
long dcId = profile.getVirtualMachine().getDataCenterId();
251+
if (SystemVmEnableUserData.valueIn(dcId)) {
252+
String userData = RouterUserData.valueIn(dcId);
253+
if (StringUtils.isNotBlank(userData)) {
254+
String encodedUserData = Base64.getEncoder().encodeToString(userData.getBytes());
255+
buf.append(" userdata=").append(encodedUserData);
256+
}
257+
}
258+
246259
if (logger.isDebugEnabled()) {
247260
logger.debug("Boot Args for " + profile + ": " + buf.toString());
248261
}

server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@
5050
import javax.naming.ConfigurationException;
5151

5252
import com.cloud.consoleproxy.ConsoleProxyManager;
53+
import com.cloud.network.router.VirtualNetworkApplianceManager;
54+
import com.cloud.storage.secondary.SecondaryStorageVmManager;
55+
import com.cloud.vm.VirtualMachineManager;
5356
import org.apache.cloudstack.acl.RoleType;
5457
import org.apache.cloudstack.acl.SecurityChecker;
5558
import org.apache.cloudstack.affinity.AffinityGroup;
@@ -638,6 +641,11 @@ protected void overProvisioningFactorsForValidation() {
638641
protected void populateConfigKeysAllowedOnlyForDefaultAdmin() {
639642
configKeysAllowedOnlyForDefaultAdmin.add(AccountManagerImpl.listOfRoleTypesAllowedForOperationsOfSameRoleType.key());
640643
configKeysAllowedOnlyForDefaultAdmin.add(AccountManagerImpl.allowOperationsOnUsersInSameAccount.key());
644+
645+
configKeysAllowedOnlyForDefaultAdmin.add(VirtualMachineManager.SystemVmEnableUserData.key());
646+
configKeysAllowedOnlyForDefaultAdmin.add(ConsoleProxyManager.ConsoleProxyUserData.key());
647+
configKeysAllowedOnlyForDefaultAdmin.add(SecondaryStorageVmManager.SecondaryStorageUserData.key());
648+
configKeysAllowedOnlyForDefaultAdmin.add(VirtualNetworkApplianceManager.RouterUserData.key());
641649
}
642650

643651
private void initMessageBusListener() {

server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManager.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ public interface ConsoleProxyManager extends Manager, ConsoleProxyService {
9393
ConfigKey<String> ConsoleProxyManagementLastState = new ConfigKey<String>(ConfigKey.CATEGORY_ADVANCED, String.class, "consoleproxy.management.state.last", com.cloud.consoleproxy.ConsoleProxyManagementState.Auto.toString(),
9494
"last console proxy service management state", false, ConfigKey.Kind.Select, consoleProxyManagementStates);
9595

96+
ConfigKey<String> ConsoleProxyUserData = new ConfigKey<>(String.class, "consoleproxy.userdata",
97+
ConfigKey.CATEGORY_SECURE, "",
98+
"Default user data for console proxy VMs. This works only when systemvm.userdata.enabled is set to true",
99+
true, ConfigKey.Scope.Zone, null, "User Data for CPVMs",
100+
null, ConfigKey.GROUP_SYSTEM_VMS, ConfigKey.SUBGROUP_CONSOLE_PROXY_VM);
101+
96102
void setManagementState(ConsoleProxyManagementState state);
97103

98104
ConsoleProxyManagementState getManagementState();

server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.nio.charset.Charset;
2020
import java.util.ArrayList;
2121
import java.util.Arrays;
22+
import java.util.Base64;
2223
import java.util.Date;
2324
import java.util.HashMap;
2425
import java.util.HashSet;
@@ -152,6 +153,8 @@
152153
import com.google.gson.GsonBuilder;
153154
import com.google.gson.JsonParseException;
154155

156+
import static com.cloud.vm.VirtualMachineManager.SystemVmEnableUserData;
157+
155158
/**
156159
* Class to manage console proxys. <br><br>
157160
* Possible console proxy state transition cases:<br>
@@ -1265,6 +1268,15 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl
12651268
buf.append(" vncport=").append(getVncPort(datacenterId));
12661269
}
12671270
buf.append(" keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16)));
1271+
1272+
if (SystemVmEnableUserData.valueIn(dc.getId())) {
1273+
String userData = ConsoleProxyUserData.valueIn(dc.getId());
1274+
if (StringUtils.isNotBlank(userData)) {
1275+
String encodedUserData = Base64.getEncoder().encodeToString(userData.getBytes());
1276+
buf.append(" userdata=").append(encodedUserData);
1277+
}
1278+
}
1279+
12681280
String bootArgs = buf.toString();
12691281
if (logger.isDebugEnabled()) {
12701282
logger.debug("Boot Args for " + profile + ": " + bootArgs);
@@ -1572,7 +1584,7 @@ public String getConfigComponentName() {
15721584
public ConfigKey<?>[] getConfigKeys() {
15731585
return new ConfigKey<?>[] { ConsoleProxySslEnabled, NoVncConsoleDefault, NoVncConsoleSourceIpCheckEnabled, ConsoleProxyServiceOffering,
15741586
ConsoleProxyCapacityStandby, ConsoleProxyCapacityScanInterval, ConsoleProxyCmdPort, ConsoleProxyRestart, ConsoleProxyUrlDomain, ConsoleProxySessionMax, ConsoleProxySessionTimeout, ConsoleProxyDisableRpFilter, ConsoleProxyLaunchMax,
1575-
ConsoleProxyManagementLastState, ConsoleProxyServiceManagementState };
1587+
ConsoleProxyManagementLastState, ConsoleProxyServiceManagementState, ConsoleProxyUserData };
15761588
}
15771589

15781590
protected ConsoleProxyStatus parseJsonToConsoleProxyStatus(String json) throws JsonParseException {

server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
6464
ConfigKey<String> RouterTemplateOvm3 = new ConfigKey<>(String.class, RouterTemplateOvm3CK, "Advanced", "SystemVM Template (Ovm3)",
6565
"Name of the default router template on Ovm3.", true, ConfigKey.Scope.Zone, null);
6666

67+
ConfigKey<String> RouterUserData = new ConfigKey<>(String.class, "router.userdata",
68+
ConfigKey.CATEGORY_SECURE, "",
69+
"Default user data for VR, VPC VR, internal LB, and elastic LB. This works only when systemvm.userdata.enabled is set to true",
70+
true, ConfigKey.Scope.Zone, null, "User Data for VRs",
71+
null, ConfigKey.GROUP_SYSTEM_VMS, ConfigKey.SUBGROUP_VIRTUAL_ROUTER);
72+
6773
ConfigKey<Boolean> SetServiceMonitor = new ConfigKey<>(Boolean.class, SetServiceMonitorCK, "Advanced", "true",
6874
"service monitoring in router enable/disable option, default true", true, ConfigKey.Scope.Zone, null);
6975

server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.cloud.network.router;
1919

2020
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
21+
import static com.cloud.vm.VirtualMachineManager.SystemVmEnableUserData;
2122

2223
import java.lang.reflect.Type;
2324
import java.math.BigInteger;
@@ -27,6 +28,7 @@
2728
import java.text.ParseException;
2829
import java.text.SimpleDateFormat;
2930
import java.util.ArrayList;
31+
import java.util.Base64;
3032
import java.util.Calendar;
3133
import java.util.Collections;
3234
import java.util.Date;
@@ -2096,6 +2098,14 @@ public boolean finalizeVirtualMachineProfile(final VirtualMachineProfile profile
20962098
" on the virtual router.", RouterLogrotateFrequency.key(), routerLogrotateFrequency, dc.getUuid()));
20972099
buf.append(String.format(" logrotatefrequency=%s", routerLogrotateFrequency));
20982100

2101+
if (SystemVmEnableUserData.valueIn(router.getDataCenterId())) {
2102+
String userData = RouterUserData.valueIn(router.getDataCenterId());
2103+
if (StringUtils.isNotBlank(userData)) {
2104+
String encodedUserData = Base64.getEncoder().encodeToString(userData.getBytes());
2105+
buf.append(" userdata=").append(encodedUserData);
2106+
}
2107+
}
2108+
20992109
if (logger.isDebugEnabled()) {
21002110
logger.debug("Boot Args for " + profile + ": " + buf);
21012111
}
@@ -3355,7 +3365,8 @@ public ConfigKey<?>[] getConfigKeys() {
33553365
RouterHealthChecksMaxMemoryUsageThreshold,
33563366
ExposeDnsAndBootpServer,
33573367
RouterLogrotateFrequency,
3358-
RemoveControlIpOnStop
3368+
RemoveControlIpOnStop,
3369+
RouterUserData
33593370
};
33603371
}
33613372

0 commit comments

Comments
 (0)