Skip to content

Commit d4c6586

Browse files
JoaoJandreJoão Paraquetti
andauthored
Return vm userdata (#6683)
* [UI] Update vm userdata * fix vm id * Address review * Address review Co-authored-by: João Paraquetti <joao@scclouds.com.br>
1 parent efbf74e commit d4c6586

File tree

10 files changed

+70
-31
lines changed

10 files changed

+70
-31
lines changed

api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd implements UserCmd {
141141
since = "4.17.0")
142142
private Boolean accumulate;
143143

144+
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.BOOLEAN, description = "Whether to return the VMs' user data or not. By default, user data will not be returned.", since = "4.18.0.0")
145+
private Boolean showUserData;
146+
147+
144148
/////////////////////////////////////////////////////
145149
/////////////////// Accessors ///////////////////////
146150
/////////////////////////////////////////////////////
@@ -219,6 +223,10 @@ public Boolean getHaEnabled() {
219223
return haEnabled;
220224
}
221225

226+
public Boolean getShowUserData() {
227+
return this.showUserData;
228+
}
229+
222230
public EnumSet<VMDetails> getDetails() throws InvalidParameterValueException {
223231
EnumSet<VMDetails> dv;
224232
if (viewDetails == null || viewDetails.size() <= 0) {

api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
332332
@Param(description = "Base64 string representation of the resource icon", since = "4.16.0.0")
333333
ResourceIconResponse resourceIconResponse;
334334

335+
@SerializedName(ApiConstants.USER_DATA)
336+
@Param(description = "Base64 string containing the user data", since = "4.18.0.0")
337+
private String userData;
338+
335339
public UserVmResponse() {
336340
securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
337341
nics = new TreeSet<>(Comparator.comparingInt(x -> Integer.parseInt(x.getDeviceId())));
@@ -604,6 +608,10 @@ public String getServiceState() {
604608
return serviceState;
605609
}
606610

611+
public String getUserData() {
612+
return userData;
613+
}
614+
607615
public void setIsDynamicallyScalable(Boolean isDynamicallyScalable) {
608616
this.isDynamicallyScalable = isDynamicallyScalable;
609617
}
@@ -952,4 +960,8 @@ public void setBytesReceived(Long bytesReceived) {
952960
public void setBytesSent(Long bytesSent) {
953961
this.bytesSent = bytesSent;
954962
}
963+
964+
public void setUserData(String userData) {
965+
this.userData = userData;
966+
}
955967
}

server/src/main/java/com/cloud/api/ApiDBUtils.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,12 +1805,13 @@ public static List<DomainRouterJoinVO> newDomainRouterView(VirtualRouter vr) {
18051805
return s_domainRouterJoinDao.newDomainRouterView(vr);
18061806
}
18071807

1808-
public static UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Account caller) {
1809-
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, null, caller);
1808+
public static UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, Set<VMDetails> details, Account caller) {
1809+
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, null, null, caller);
18101810
}
18111811

1812-
public static UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Account caller) {
1813-
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, accumulateStats, caller);
1812+
public static UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, Set<VMDetails> details, Boolean accumulateStats,
1813+
Boolean showUserData, Account caller) {
1814+
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, accumulateStats, showUserData, caller);
18141815
}
18151816

18161817
public static UserVmResponse fillVmDetails(ResponseView view, UserVmResponse vmData, UserVmJoinVO vm) {

server/src/main/java/com/cloud/api/query/QueryManagerImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,8 @@ public ListResponse<UserVmResponse> searchForUserVMs(ListVMsCmd cmd) {
965965
if (_accountMgr.isRootAdmin(caller.getId())) {
966966
respView = ResponseView.Full;
967967
}
968-
List<UserVmResponse> vmResponses = ViewResponseHelper.createUserVmResponse(respView, "virtualmachine", cmd.getDetails(), cmd.getAccumulate(), result.first().toArray(new UserVmJoinVO[result.first().size()]));
968+
List<UserVmResponse> vmResponses = ViewResponseHelper.createUserVmResponse(respView, "virtualmachine", cmd.getDetails(), cmd.getAccumulate(), cmd.getShowUserData(),
969+
result.first().toArray(new UserVmJoinVO[result.first().size()]));
969970

970971
response.setResponses(vmResponses, result.second());
971972
return response;

server/src/main/java/com/cloud/api/query/ViewResponseHelper.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.LinkedHashMap;
2626
import java.util.List;
2727
import java.util.Map;
28+
import java.util.Set;
2829

2930
import org.apache.cloudstack.api.ApiConstants;
3031
import org.apache.cloudstack.affinity.AffinityGroupResponse;
@@ -135,14 +136,19 @@ public static List<InstanceGroupResponse> createInstanceGroupResponse(InstanceGr
135136
}
136137

137138
public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, UserVmJoinVO... userVms) {
138-
return createUserVmResponse(view, objectName, EnumSet.of(VMDetails.all), null, userVms);
139+
return createUserVmResponse(view, objectName, EnumSet.of(VMDetails.all), null, null, userVms);
139140
}
140141

141-
public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, EnumSet<VMDetails> details, UserVmJoinVO... userVms) {
142-
return createUserVmResponse(view, objectName, details, null, userVms);
142+
public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, Set<VMDetails> details, UserVmJoinVO... userVms) {
143+
return createUserVmResponse(view, objectName, details, null, null, userVms);
143144
}
144145

145-
public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, EnumSet<VMDetails> details, Boolean accumulateStats, UserVmJoinVO... userVms) {
146+
public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, Set<VMDetails> details, Boolean accumulateStats, UserVmJoinVO... userVms) {
147+
return createUserVmResponse(view, objectName, details, accumulateStats, null, userVms);
148+
}
149+
150+
public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, Set<VMDetails> details, Boolean accumulateStats, Boolean showUserData,
151+
UserVmJoinVO... userVms) {
146152
Account caller = CallContext.current().getCallingAccount();
147153
Hashtable<Long, UserVmResponse> vmDataList = new Hashtable<Long, UserVmResponse>();
148154
// Initialise the vmdatalist with the input data
@@ -151,7 +157,7 @@ public static List<UserVmResponse> createUserVmResponse(ResponseView view, Strin
151157
UserVmResponse userVmData = vmDataList.get(userVm.getId());
152158
if (userVmData == null) {
153159
// first time encountering this vm
154-
userVmData = ApiDBUtils.newUserVmResponse(view, objectName, userVm, details, accumulateStats, caller);
160+
userVmData = ApiDBUtils.newUserVmResponse(view, objectName, userVm, details, accumulateStats, showUserData, caller);
155161
} else{
156162
// update nics, securitygroups, tags, affinitygroups for 1 to many mapping fields
157163
userVmData = ApiDBUtils.fillVmDetails(view, userVmData, userVm);

server/src/main/java/com/cloud/api/query/dao/UserVmJoinDao.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
// under the License.
1717
package com.cloud.api.query.dao;
1818

19-
import java.util.EnumSet;
2019
import java.util.List;
20+
import java.util.Set;
2121

2222
import org.apache.cloudstack.api.ApiConstants.VMDetails;
2323
import org.apache.cloudstack.api.ResponseObject.ResponseView;
@@ -30,7 +30,8 @@
3030

3131
public interface UserVmJoinDao extends GenericDao<UserVmJoinVO, Long> {
3232

33-
UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Account caller);
33+
UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, Set<VMDetails> details, Boolean accumulateStats, Boolean showUserData,
34+
Account caller);
3435

3536
UserVmResponse setUserVmResponse(ResponseView view, UserVmResponse userVmData, UserVmJoinVO uvo);
3637

server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.text.DecimalFormat;
2020
import java.util.ArrayList;
21-
import java.util.EnumSet;
2221
import java.util.HashMap;
2322
import java.util.Hashtable;
2423
import java.util.List;
@@ -45,6 +44,7 @@
4544
import org.apache.cloudstack.context.CallContext;
4645
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
4746
import org.apache.cloudstack.query.QueryService;
47+
import org.apache.commons.lang3.BooleanUtils;
4848
import org.apache.log4j.Logger;
4949
import org.springframework.stereotype.Component;
5050

@@ -122,7 +122,8 @@ public List<UserVmJoinVO> listActiveByIsoId(Long isoId) {
122122
}
123123

124124
@Override
125-
public UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Account caller) {
125+
public UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, Set<VMDetails> details, Boolean accumulateStats, Boolean showUserData,
126+
Account caller) {
126127
UserVmResponse userVmResponse = new UserVmResponse();
127128

128129
if (userVm.getHypervisorType() != null) {
@@ -347,6 +348,10 @@ public UserVmResponse newUserVmResponse(ResponseView view, String objectName, Us
347348
}
348349
}
349350

351+
if (BooleanUtils.isTrue(showUserData)) {
352+
userVmResponse.setUserData(userVm.getUserData());
353+
}
354+
350355
// set resource details map
351356
// Allow passing details to end user
352357
// Honour the display field and only return if display is set to true

ui/src/utils/util.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,10 @@ export function removeLoadingAnimate (id = '', timeout = 1500) {
6161
document.body.removeChild(document.getElementById(id))
6262
}, timeout)
6363
}
64+
65+
export function sanitizeReverse (value) {
66+
return value
67+
.replace(/&amp;/g, '&')
68+
.replace(/&lt;/g, '<')
69+
.replace(/&gt;/g, '>')
70+
}

ui/src/views/compute/DeployVM.vue

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ import SshKeyPairSelection from '@views/compute/wizard/SshKeyPairSelection'
700700
import SecurityGroupSelection from '@views/compute/wizard/SecurityGroupSelection'
701701
import TooltipLabel from '@/components/widgets/TooltipLabel'
702702
import InstanceNicsNetworkSelectListView from '@/components/view/InstanceNicsNetworkSelectListView.vue'
703+
import { sanitizeReverse } from '@/utils/util'
703704
704705
export default {
705706
name: 'Wizard',
@@ -1708,7 +1709,7 @@ export default {
17081709
}
17091710
deployVmData.dynamicscalingenabled = values.dynamicscalingenabled
17101711
if (values.userdata && values.userdata.length > 0) {
1711-
deployVmData.userdata = encodeURIComponent(btoa(this.sanitizeReverse(values.userdata)))
1712+
deployVmData.userdata = encodeURIComponent(btoa(sanitizeReverse(values.userdata)))
17121713
}
17131714
// step 2: select template/iso
17141715
if (this.tabKey === 'templateid') {
@@ -2148,14 +2149,6 @@ export default {
21482149
this.fetchAllIsos()
21492150
}
21502151
},
2151-
sanitizeReverse (value) {
2152-
const reversedValue = value
2153-
.replace(/&amp;/g, '&')
2154-
.replace(/&lt;/g, '<')
2155-
.replace(/&gt;/g, '>')
2156-
2157-
return reversedValue
2158-
},
21592152
fetchTemplateNics (template) {
21602153
var nics = []
21612154
this.nicToNetworkSelection = []

ui/src/views/compute/EditVM.vue

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
import { ref, reactive, toRaw } from 'vue'
124124
import { api } from '@/api'
125125
import TooltipLabel from '@/components/widgets/TooltipLabel'
126+
import { sanitizeReverse } from '@/utils/util'
126127
127128
export default {
128129
name: 'EditVM',
@@ -176,7 +177,8 @@ export default {
176177
ostypeid: this.resource.ostypeid,
177178
isdynamicallyscalable: this.resource.isdynamicallyscalable,
178179
group: this.resource.group,
179-
securitygroupids: this.resource.securitygroup.map(x => x.id)
180+
securitygroupids: this.resource.securitygroup.map(x => x.id),
181+
userdata: ''
180182
})
181183
this.rules = reactive({})
182184
},
@@ -188,6 +190,7 @@ export default {
188190
this.fetchServiceOfferingData()
189191
this.fetchTemplateData()
190192
this.fetchDynamicScalingVmConfig()
193+
this.fetchUserData()
191194
},
192195
fetchZoneDetails () {
193196
api('listZones', {
@@ -281,13 +284,15 @@ export default {
281284
this.$notifyError(error)
282285
}).finally(() => { this.groups.loading = false })
283286
},
284-
sanitizeReverse (value) {
285-
const reversedValue = value
286-
.replace(/&amp;/g, '&')
287-
.replace(/&lt;/g, '<')
288-
.replace(/&gt;/g, '>')
287+
fetchUserData () {
288+
const params = {
289+
id: this.resource.id,
290+
userdata: true
291+
}
289292
290-
return reversedValue
293+
api('listVirtualMachines', params).then(json => {
294+
this.form.userdata = atob(json.listvirtualmachinesresponse.virtualmachine[0].userdata || '')
295+
})
291296
},
292297
handleSubmit () {
293298
this.formRef.value.validate().then(() => {
@@ -312,7 +317,7 @@ export default {
312317
params.group = values.group
313318
}
314319
if (values.userdata && values.userdata.length > 0) {
315-
params.userdata = encodeURIComponent(btoa(this.sanitizeReverse(values.userdata)))
320+
params.userdata = encodeURIComponent(btoa(sanitizeReverse(values.userdata)))
316321
}
317322
this.loading = true
318323

0 commit comments

Comments
 (0)