Skip to content

Commit

Permalink
Merge branch 'UI-update-vm-with-userdata' into '4.16.0.0-scclouds'
Browse files Browse the repository at this point in the history
[UI] Update vm userdata

Closes apache#662

See merge request scclouds/scclouds!288
  • Loading branch information
Daniel Augusto Veronezi Salvador committed Aug 5, 2022
2 parents 8df57a8 + ca4ed05 commit 9658b99
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd implements UserCmd {
since = "4.16.0.4")
private Boolean accumulate;

@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.16.0.8")
private Boolean showUserData;


/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -248,6 +252,10 @@ public Boolean getHaEnabled() {
return haEnabled;
}

public Boolean getShowUserData() {
return this.showUserData;
}

public EnumSet<VMDetails> getDetails() throws InvalidParameterValueException {
EnumSet<VMDetails> dv;
if (viewDetails == null || viewDetails.size() <= 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
@Param(description = "Base64 string representation of the resource icon", since = "4.16.0.0")
ResourceIconResponse resourceIconResponse;

@SerializedName(ApiConstants.USER_DATA)
@Param(description = "Base64 string containing the user data", since = "4.16.0.8-scclouds")
private String userData;

public UserVmResponse() {
securityGroupList = new LinkedHashSet<SecurityGroupResponse>();
nics = new TreeSet<>(Comparator.comparingInt(x -> Integer.parseInt(x.getDeviceId())));
Expand Down Expand Up @@ -604,6 +608,10 @@ public String getServiceState() {
return serviceState;
}

public String getUserData() {
return userData;
}

public void setIsDynamicallyScalable(Boolean isDynamicallyScalable) {
this.isDynamicallyScalable = isDynamicallyScalable;
}
Expand Down Expand Up @@ -952,4 +960,8 @@ public void setBytesReceived(Long bytesReceived) {
public void setBytesSent(Long bytesSent) {
this.bytesSent = bytesSent;
}

public void setUserData(String userData) {
this.userData = userData;
}
}
7 changes: 4 additions & 3 deletions server/src/main/java/com/cloud/api/ApiDBUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1782,11 +1782,12 @@ public static List<DomainRouterJoinVO> newDomainRouterView(VirtualRouter vr) {
}

public static UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Account caller) {
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, null, caller);
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, null, null, caller);
}

public static UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Account caller) {
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, accumulateStats, caller);
public static UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats,
Boolean showUserData, Account caller) {
return s_userVmJoinDao.newUserVmResponse(view, objectName, userVm, details, accumulateStats, showUserData, caller);
}

public static UserVmResponse fillVmDetails(ResponseView view, UserVmResponse vmData, UserVmJoinVO vm) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,8 @@ public ListResponse<UserVmResponse> searchForUserVMs(ListVMsCmd cmd) {
if (_accountMgr.isRootAdmin(caller.getId())) {
respView = ResponseView.Full;
}
List<UserVmResponse> vmResponses = ViewResponseHelper.createUserVmResponse(respView, "virtualmachine", cmd.getDetails(), cmd.getAccumulate(), result.first().toArray(new UserVmJoinVO[result.first().size()]));
List<UserVmResponse> vmResponses = ViewResponseHelper.createUserVmResponse(respView, "virtualmachine", cmd.getDetails(), cmd.getAccumulate(), cmd.getShowUserData(),
result.first().toArray(new UserVmJoinVO[result.first().size()]));

response.setResponses(vmResponses, result.second());
return response;
Expand Down
11 changes: 8 additions & 3 deletions server/src/main/java/com/cloud/api/query/ViewResponseHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,19 @@ public static List<InstanceGroupResponse> createInstanceGroupResponse(InstanceGr
}

public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, UserVmJoinVO... userVms) {
return createUserVmResponse(view, objectName, EnumSet.of(VMDetails.all), null, userVms);
return createUserVmResponse(view, objectName, EnumSet.of(VMDetails.all), null, null, userVms);
}

public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, EnumSet<VMDetails> details, UserVmJoinVO... userVms) {
return createUserVmResponse(view, objectName, details, null, userVms);
return createUserVmResponse(view, objectName, details, null, null, userVms);
}

public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, EnumSet<VMDetails> details, Boolean accumulateStats, UserVmJoinVO... userVms) {
return createUserVmResponse(view, objectName, details, accumulateStats, null, userVms);
}

public static List<UserVmResponse> createUserVmResponse(ResponseView view, String objectName, EnumSet<VMDetails> details, Boolean accumulateStats, Boolean showUserData,
UserVmJoinVO... userVms) {
Account caller = CallContext.current().getCallingAccount();

Hashtable<Long, UserVmResponse> vmDataList = new Hashtable<Long, UserVmResponse>();
Expand All @@ -152,7 +157,7 @@ public static List<UserVmResponse> createUserVmResponse(ResponseView view, Strin
UserVmResponse userVmData = vmDataList.get(userVm.getId());
if (userVmData == null) {
// first time encountering this vm
userVmData = ApiDBUtils.newUserVmResponse(view, objectName, userVm, details, accumulateStats, caller);
userVmData = ApiDBUtils.newUserVmResponse(view, objectName, userVm, details, accumulateStats, showUserData, caller);
} else{
// update nics, securitygroups, tags, affinitygroups for 1 to many mapping fields
userVmData = ApiDBUtils.fillVmDetails(view, userVmData, userVm);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@

public interface UserVmJoinDao extends GenericDao<UserVmJoinVO, Long> {

UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Account caller);
UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Boolean showUserData,
Account caller);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.query.QueryService;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

Expand Down Expand Up @@ -117,7 +118,8 @@ public List<UserVmJoinVO> listActiveByIsoId(Long isoId) {
}

@Override
public UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Account caller) {
public UserVmResponse newUserVmResponse(ResponseView view, String objectName, UserVmJoinVO userVm, EnumSet<VMDetails> details, Boolean accumulateStats, Boolean showUserData,
Account caller) {
UserVmResponse userVmResponse = new UserVmResponse();

if (userVm.getHypervisorType() != null) {
Expand Down Expand Up @@ -333,6 +335,10 @@ public UserVmResponse newUserVmResponse(ResponseView view, String objectName, Us
}
}

if (BooleanUtils.isTrue(showUserData)) {
userVmResponse.setUserData(userVm.getUserData());
}

// set resource details map
// Allow passing details to end user
// Honour the display field and only return if display is set to true
Expand Down
7 changes: 7 additions & 0 deletions ui/src/utils/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,10 @@ export function removeLoadingAnimate (id = '', timeout = 1500) {
document.body.removeChild(document.getElementById(id))
}, timeout)
}

export function sanitizeReverse (value) {
return value
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
}
3 changes: 2 additions & 1 deletion ui/src/views/compute/DeployVM.vue
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ import NetworkConfiguration from '@views/compute/wizard/NetworkConfiguration'
import SshKeyPairSelection from '@views/compute/wizard/SshKeyPairSelection'
import SecurityGroupSelection from '@views/compute/wizard/SecurityGroupSelection'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import { sanitizeReverse } from '@/utils/util'
export default {
name: 'Wizard',
Expand Down Expand Up @@ -1537,7 +1538,7 @@ export default {
deployVmData.bootmode = values.bootmode
deployVmData.dynamicscalingenabled = values.dynamicscalingenabled
if (values.userdata && values.userdata.length > 0) {
deployVmData.userdata = encodeURIComponent(btoa(this.sanitizeReverse(values.userdata)))
deployVmData.userdata = encodeURIComponent(btoa(sanitizeReverse(values.userdata)))
}
// step 2: select template/iso
if (this.tabKey === 'templateid') {
Expand Down
28 changes: 25 additions & 3 deletions ui/src/views/compute/EditVM.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@
}"
:dataSource="groups.opts" />
</a-form-item>
<a-form-item>
<tooltip-label slot="label" :title="$t('label.userdata')" :tooltip="apiParams.userdata.description"/>
<a-textarea
v-decorator="['userdata', { initialValue: resource.userdata || '' }]">
</a-textarea>
</a-form-item>

<div :span="24" class="action-button">
<a-button :loading="loading" @click="onCloseAction">{{ this.$t('label.cancel') }}</a-button>
Expand All @@ -86,6 +92,7 @@
<script>
import { api } from '@/api'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import { sanitizeReverse } from '@/utils/util'
export default {
name: 'EditVM',
Expand Down Expand Up @@ -132,6 +139,7 @@ export default {
this.fetchServiceOfferingData()
this.fetchTemplateData()
this.fetchDynamicScalingVmConfig()
this.fetchUserData()
},
fetchServiceOfferingData () {
const params = {}
Expand All @@ -145,7 +153,6 @@ export default {
},
fetchTemplateData () {
const params = {}
console.log('templateid ' + this.resource.templateid)
params.id = this.resource.templateid
params.isrecursive = true
params.templatefilter = 'all'
Expand Down Expand Up @@ -198,6 +205,16 @@ export default {
this.$notifyError(error)
}).finally(() => { this.groups.loading = false })
},
fetchUserData () {
const params = {
id: this.resource.virtualmachineid,
userdata: true
}
api('listVirtualMachines', params).then(json => {
this.resource.userdata = atob(json.listvirtualmachinesresponse.virtualmachine[0].userdata || '')
})
},
handleSubmit (e) {
e.preventDefault()
this.form.validateFields((err, values) => {
Expand All @@ -214,10 +231,15 @@ export default {
if (values.haenable !== undefined) {
params.haenable = values.haenable
}
params.group = values.group
if (values.group && values.group.length > 0) {
params.group = values.group
}
if (values.userdata && values.userdata.length > 0) {
params.userdata = encodeURIComponent(btoa(sanitizeReverse(values.userdata)))
}
this.loading = true
api('updateVirtualMachine', params).then(json => {
api('updateVirtualMachine', {}, 'POST', params).then(json => {
this.$message.success({
content: `${this.$t('label.action.edit.instance')} - ${values.name}`,
duration: 2
Expand Down

0 comments on commit 9658b99

Please sign in to comment.