mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
UI improvements (#9773)
* Show Usage Server configuration in a separate pane * UI: Option to attach volume to an instance during create volume * Show service ip in management server details tab * change Schedule Snapshots to Recurring Snapshots * Change the hypervisor order so that kvm, vmware, xenserver show up first * Remove extra space in hypervisor names in config.java * Fix `updateTemplatePermission` when the UI is set to a language other than English (#9766) * Fix updateTemplatePermission UI in non-english language * Improve fix --------- Co-authored-by: Lucas Martins <lucas.martins@scclouds.com.br> * Autofill vcenter details in add cluster form * UI: condition to display create vm-vol-snapshots to same as create vol-snapshots * Fix alignment on wrapping in global settings tabs * rename Autofill vCenter credentials to Autofill vCenter credentials from Zone * Rename Service Ip to Ip Address in management server response * Change description of kvm.snapshot.enabled to say that it applies to volume snapshots * Return error when kvm vm snapshot is taken withoutsnapshot memory * Minor naming changes and grammar * Fix tooltip for attach volume to instance button * Show Usage Server configuration in a separate pane * UI: Option to attach volume to an instance during create volume * Show service ip in management server details tab * change Schedule Snapshots to Recurring Snapshots * Change the hypervisor order so that kvm, vmware, xenserver show up first * Remove extra space in hypervisor names in config.java * Autofill vcenter details in add cluster form * UI: condition to display create vm-vol-snapshots to same as create vol-snapshots * Fix alignment on wrapping in global settings tabs * rename Autofill vCenter credentials to Autofill vCenter credentials from Zone * Rename Service Ip to Ip Address in management server response * Change description of kvm.snapshot.enabled to say that it applies to volume snapshots * Return error when kvm vm snapshot is taken withoutsnapshot memory * Minor naming changes and grammar * Fix tooltip for attach volume to instance button * Show Usage Server configuration in a separate pane * UI: Option to attach volume to an instance during create volume * Show service ip in management server details tab * change Schedule Snapshots to Recurring Snapshots * Change the hypervisor order so that kvm, vmware, xenserver show up first * Remove extra space in hypervisor names in config.java * Autofill vcenter details in add cluster form * UI: condition to display create vm-vol-snapshots to same as create vol-snapshots * Fix alignment on wrapping in global settings tabs * rename Autofill vCenter credentials to Autofill vCenter credentials from Zone * Rename Service Ip to Ip Address in management server response * Change description of kvm.snapshot.enabled to say that it applies to volume snapshots * Return error when kvm vm snapshot is taken withoutsnapshot memory * Minor naming changes and grammar * Fix tooltip for attach volume to instance button * UI: Option to attach volume to an instance during create volume * UI: condition to display create vm-vol-snapshots to same as create vol-snapshots * moved db changes from 41900to42000 to 42000to42010 * Update group_id in already present usage configuration settings * remove "schedule" from message in create Recurring Snapshots form * Update server/src/main/java/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java --------- Co-authored-by: Daan Hoogland <daan@onecht.net> Co-authored-by: Lucas Martins <56271185+lucas-a-martins@users.noreply.github.com> Co-authored-by: Lucas Martins <lucas.martins@scclouds.com.br> Co-authored-by: Boris Stoyanov - a.k.a Bobby <bss.stoyanov@gmail.com> Co-authored-by: Andrija Panic <45762285+andrijapanicsb@users.noreply.github.com>
This commit is contained in:
parent
986ec81b66
commit
c5afee2101
@ -447,7 +447,6 @@ public class ApiConstants {
|
||||
public static final String SENT = "sent";
|
||||
public static final String SENT_BYTES = "sentbytes";
|
||||
public static final String SERIAL = "serial";
|
||||
public static final String SERVICE_IP = "serviceip";
|
||||
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
|
||||
public static final String SESSIONKEY = "sessionkey";
|
||||
public static final String SHOW_CAPACITIES = "showcapacities";
|
||||
|
||||
@ -74,9 +74,9 @@ public class ManagementServerResponse extends BaseResponse {
|
||||
@Param(description = "the running OS kernel version for this Management Server")
|
||||
private String kernelVersion;
|
||||
|
||||
@SerializedName(ApiConstants.SERVICE_IP)
|
||||
@SerializedName(ApiConstants.IP_ADDRESS)
|
||||
@Param(description = "the IP Address for this Management Server")
|
||||
private String serviceIp;
|
||||
private String ipAddress;
|
||||
|
||||
@SerializedName(ApiConstants.PEERS)
|
||||
@Param(description = "the Management Server Peers")
|
||||
@ -122,8 +122,8 @@ public class ManagementServerResponse extends BaseResponse {
|
||||
return lastBoot;
|
||||
}
|
||||
|
||||
public String getServiceIp() {
|
||||
return serviceIp;
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
@ -170,8 +170,8 @@ public class ManagementServerResponse extends BaseResponse {
|
||||
this.kernelVersion = kernelVersion;
|
||||
}
|
||||
|
||||
public void setServiceIp(String serviceIp) {
|
||||
this.serviceIp = serviceIp;
|
||||
public void setIpAddress(String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
|
||||
public String getKernelVersion() {
|
||||
|
||||
@ -24,6 +24,14 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.user', 'api_key_access', 'boolean DE
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" ');
|
||||
CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" ');
|
||||
|
||||
-- Create a new group for Usage Server related configurations
|
||||
INSERT INTO `cloud`.`configuration_group` (`name`, `description`, `precedence`) VALUES ('Usage Server', 'Usage Server related configuration', 9);
|
||||
UPDATE `cloud`.`configuration_subgroup` set `group_id` = (SELECT `id` FROM `cloud`.`configuration_group` WHERE `name` = 'Usage Server'), `precedence` = 1 WHERE `name`='Usage';
|
||||
UPDATE `cloud`.`configuration` SET `group_id` = (SELECT `id` FROM `cloud`.`configuration_group` WHERE `name` = 'Usage Server') where `subgroup_id` = (SELECT `id` FROM `cloud`.`configuration_subgroup` WHERE `name` = 'Usage');
|
||||
|
||||
-- Update the description to indicate this setting applies only to volume snapshots on running instances
|
||||
UPDATE `cloud`.`configuration` SET `description`='whether volume snapshot is enabled on running instances on KVM hosts' WHERE `name`='kvm.snapshot.enabled';
|
||||
|
||||
-- Modify index for mshost_peer
|
||||
DELETE FROM `cloud`.`mshost_peer`;
|
||||
CALL `cloud`.`IDEMPOTENT_DROP_FOREIGN_KEY`('cloud.mshost_peer','fk_mshost_peer__owner_mshost');
|
||||
|
||||
@ -5413,13 +5413,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
||||
mgmtResponse.setLastServerStart(mgmt.getLastJvmStart());
|
||||
mgmtResponse.setLastServerStop(mgmt.getLastJvmStop());
|
||||
mgmtResponse.setLastBoot(mgmt.getLastSystemBoot());
|
||||
mgmtResponse.setServiceIp(mgmt.getServiceIP());
|
||||
if (listPeers) {
|
||||
List<ManagementServerHostPeerJoinVO> peers = mshostPeerJoinDao.listByOwnerMshostId(mgmt.getId());
|
||||
for (ManagementServerHostPeerJoinVO peer: peers) {
|
||||
mgmtResponse.addPeer(createPeerManagementServerNodeResponse(peer));
|
||||
}
|
||||
}
|
||||
mgmtResponse.setIpAddress(mgmt.getServiceIP());
|
||||
mgmtResponse.setObjectName("managementserver");
|
||||
return mgmtResponse;
|
||||
}
|
||||
|
||||
@ -506,7 +506,7 @@ public enum Config {
|
||||
"The time interval in seconds when the management server polls for snapshots to be scheduled.",
|
||||
null),
|
||||
SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null),
|
||||
KVMSnapshotEnabled("Hidden", SnapshotManager.class, Boolean.class, "kvm.snapshot.enabled", "false", "whether snapshot is enabled for KVM hosts", null),
|
||||
KVMSnapshotEnabled("Hidden", SnapshotManager.class, Boolean.class, "kvm.snapshot.enabled", "false", "Whether volume snapshot is enabled on running instances on a KVM host", null),
|
||||
|
||||
// Advanced
|
||||
EventPurgeInterval(
|
||||
@ -665,8 +665,8 @@ public enum Config {
|
||||
ManagementServer.class,
|
||||
String.class,
|
||||
"hypervisor.list",
|
||||
HypervisorType.Hyperv + "," + HypervisorType.KVM + "," + HypervisorType.XenServer + "," + HypervisorType.VMware + "," + HypervisorType.BareMetal + "," +
|
||||
HypervisorType.Ovm + "," + HypervisorType.LXC + "," + HypervisorType.Ovm3,
|
||||
HypervisorType.KVM + "," + HypervisorType.VMware + "," + HypervisorType.XenServer + "," + HypervisorType.Hyperv + "," +
|
||||
HypervisorType.BareMetal + "," + HypervisorType.Ovm + "," + HypervisorType.LXC + "," + HypervisorType.Ovm3,
|
||||
"The list of hypervisors that this deployment will use.",
|
||||
"hypervisorList",
|
||||
ConfigKey.Kind.CSV,
|
||||
|
||||
@ -343,7 +343,7 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
||||
private void validatePrerequisiteVpnGateway(Site2SiteVpnGateway vpnGateway) {
|
||||
// check if gateway has been defined on the VPC
|
||||
if (_vpnGatewayDao.findByVpcId(vpnGateway.getVpcId()) == null) {
|
||||
throw new InvalidParameterValueException("we can not create a VPN connection for a VPC that does not have a VPN gateway defined");
|
||||
throw new InvalidParameterValueException("We can not create a VPN connection for a VPC that does not have a VPN gateway defined");
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,7 +590,7 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn
|
||||
private void stopVpnConnection(Long id) throws ResourceUnavailableException {
|
||||
Site2SiteVpnConnectionVO conn = _vpnConnectionDao.acquireInLockTable(id);
|
||||
if (conn == null) {
|
||||
throw new CloudRuntimeException("Unable to acquire lock for stopping of VPN connection with ID " + id);
|
||||
throw new CloudRuntimeException("Unable to acquire lock for stopping VPN connection with ID " + id);
|
||||
}
|
||||
try {
|
||||
if (conn.getState() == State.Pending) {
|
||||
|
||||
@ -27,6 +27,7 @@ import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
@ -377,9 +378,14 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
||||
//StorageVMSnapshotStrategy - allows volume snapshots without memory; VM has to be in Running state; No limitation of the image format if the storage plugin supports volume snapshots; "kvm.vmstoragesnapshot.enabled" has to be enabled
|
||||
//Other Storage volume plugins could integrate this with their own functionality for group snapshots
|
||||
VMSnapshotStrategy snapshotStrategy = storageStrategyFactory.getVmSnapshotStrategy(userVmVo.getId(), rootVolumePool.getId(), snapshotMemory);
|
||||
|
||||
if (snapshotStrategy == null) {
|
||||
String message = "KVM does not support the type of snapshot requested";
|
||||
String message;
|
||||
if (!SnapshotManager.VmStorageSnapshotKvm.value() && !snapshotMemory) {
|
||||
message = "Creating a snapshot of a running KVM instance without memory is not supported";
|
||||
} else {
|
||||
message = "KVM does not support the type of snapshot requested";
|
||||
}
|
||||
|
||||
logger.debug(message);
|
||||
throw new CloudRuntimeException(message);
|
||||
}
|
||||
|
||||
@ -1265,7 +1265,6 @@
|
||||
"label.save.new.rule": "Neue Regel Speichern",
|
||||
"label.schedule": "Zeitplan",
|
||||
"label.scheduled.backups": "geplante Backups",
|
||||
"label.scheduled.snapshots": "geplante Schnappschüsse",
|
||||
"label.scope": "Geltungsbereich",
|
||||
"label.search": "Suche",
|
||||
"label.secondary.isolated.vlan.type.isolated": "Isoliert",
|
||||
|
||||
@ -1517,7 +1517,6 @@
|
||||
"label.scale.vm": "Κλίμακα εικονικής μηχανής",
|
||||
"label.schedule": "Πρόγραμμα",
|
||||
"label.scheduled.backups": "Προγραμματισμένα αντίγραφα ασφαλείας",
|
||||
"label.scheduled.snapshots": "Προγραμματισμένα στιγμιότυπα",
|
||||
"label.scope": "Πεδίο εφαρμογής",
|
||||
"label.search": "Αναζήτηση",
|
||||
"label.secondary.isolated.vlan.type.isolated": "Απομονωμένες",
|
||||
|
||||
@ -54,6 +54,7 @@
|
||||
"label.action": "Action",
|
||||
"label.action.attach.disk": "Attach disk",
|
||||
"label.action.attach.iso": "Attach ISO",
|
||||
"label.action.attach.to.instance": "Attach to Instance",
|
||||
"label.action.bulk.delete.egress.firewall.rules": "Bulk delete egress firewall rules",
|
||||
"label.action.bulk.delete.firewall.rules": "Bulk delete firewall rules",
|
||||
"label.action.bulk.delete.ip.v6.firewall.rules": "Bulk remove IPv6 firewall rules",
|
||||
@ -399,9 +400,11 @@
|
||||
"label.associatednetworkid": "Associated Network ID",
|
||||
"label.associatednetworkname": "Network name",
|
||||
"label.asyncbackup": "Async backup",
|
||||
"label.attach.vol.to.instance": "Attach the created Volume to an existing Instance",
|
||||
"label.attaching": "Attaching",
|
||||
"label.authentication.method": "Authentication Method",
|
||||
"label.authentication.sshkey": "System SSH Key",
|
||||
"label.use.existing.vcenter.credentials.from.zone": "Use existing vCenter credentials from the Zone",
|
||||
"label.autoscale": "AutoScale",
|
||||
"label.autoscalevmgroupname": "AutoScaling Group",
|
||||
"label.author.email": "Author e-mail",
|
||||
@ -1073,7 +1076,7 @@
|
||||
"label.hastate": "HA state",
|
||||
"label.headers": "Headers",
|
||||
"label.header.backup.schedule": "You can set up recurring backup schedules by selecting from the available options below and applying your policy preference.",
|
||||
"label.header.volume.snapshot": "You can set up recurring Snapshot schedules by selecting from the available options below and applying your policy preference.",
|
||||
"label.header.volume.snapshot": "You can set up recurring Snapshots by selecting from the available options below and applying your policy preference.",
|
||||
"label.header.volume.take.snapshot": "Please confirm that you want to take a Snapshot of this volume.",
|
||||
"label.health.check": "Health check",
|
||||
"label.heapmemoryused": "Heap-memory used",
|
||||
@ -1999,7 +2002,6 @@
|
||||
"label.schedule": "Schedule",
|
||||
"label.schedule.add": "Add schedule",
|
||||
"label.scheduled.backups": "Scheduled backups",
|
||||
"label.scheduled.snapshots": "Scheduled Snapshots",
|
||||
"label.schedules": "Schedules",
|
||||
"label.scope": "Scope",
|
||||
"label.scope.tooltip": "Primary Storage Pool Scope",
|
||||
|
||||
@ -1969,7 +1969,6 @@
|
||||
"label.scaleup.policy": "スケールアップポリシー",
|
||||
"label.schedule": "スケジュール",
|
||||
"label.scheduled.backups": "スケジュールされたバックアップ",
|
||||
"label.scheduled.snapshots": "スケジュールされたスナップショット",
|
||||
"label.scope": "スコープ",
|
||||
"label.search": "検索",
|
||||
"label.secondary.isolated.vlan.type.isolated": "隔離",
|
||||
|
||||
@ -1322,7 +1322,6 @@
|
||||
"label.scale.vm": "VM \ud655\uc7a5",
|
||||
"label.schedule": "\uc2a4\ucf00\uc904",
|
||||
"label.scheduled.backups": "\uc608\uc57d\ub41c \ubc31\uc5c5",
|
||||
"label.scheduled.snapshots": "\uc608\uc57d\ub41c \uc2a4\ub0c5\uc0f7",
|
||||
"label.scope": "\ubc94\uc704",
|
||||
"label.search": "\uac80\uc0c9",
|
||||
"label.secondary.isolated.vlan.type.isolated": "isolated",
|
||||
|
||||
@ -1428,7 +1428,6 @@
|
||||
"label.scale.vm": "Escalar VM",
|
||||
"label.schedule": "Programar",
|
||||
"label.scheduled.backups": "Backups programados",
|
||||
"label.scheduled.snapshots": "Snapshots programados",
|
||||
"label.scope": "Escopo",
|
||||
"label.search": "Pesquisar",
|
||||
"label.secondary.isolated.vlan.type.isolated": "Isolada",
|
||||
|
||||
@ -2248,7 +2248,6 @@
|
||||
|
||||
"label.schedule": "\u65E5\u7A0B",
|
||||
"label.scheduled.backups": "\u5B9A\u65F6\u5907\u4EFD",
|
||||
"label.scheduled.snapshots": "\u8BA1\u5212\u5FEB\u7167",
|
||||
"label.scope": "\u8303\u56F4",
|
||||
"label.search": "\u641C\u7D22",
|
||||
|
||||
|
||||
@ -207,9 +207,10 @@ export default {
|
||||
docHelp: 'adminguide/virtual_machines.html#virtual-machine-snapshots',
|
||||
dataView: true,
|
||||
popup: true,
|
||||
show: (record) => {
|
||||
return ((['Running'].includes(record.state) && record.hypervisor !== 'LXC') ||
|
||||
(['Stopped'].includes(record.state) && !['KVM', 'LXC'].includes(record.hypervisor)))
|
||||
show: (record, store) => {
|
||||
return (record.hypervisor !== 'KVM') ||
|
||||
['Stopped', 'Destroyed'].includes(record.state) ||
|
||||
store.features.kvmsnapshotenabled
|
||||
},
|
||||
disabled: (record) => { return record.hostcontrolstate === 'Offline' && record.hypervisor === 'KVM' },
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/compute/CreateSnapshotWizard.vue')))
|
||||
|
||||
@ -26,14 +26,14 @@ export default {
|
||||
permission: ['listManagementServersMetrics'],
|
||||
resourceType: 'ManagementServer',
|
||||
columns: () => {
|
||||
const fields = ['name', 'state', 'serviceip', 'version', 'osdistribution', 'agentcount']
|
||||
const fields = ['name', 'state', 'ipaddress', 'version', 'osdistribution', 'agentcount']
|
||||
const metricsFields = ['collectiontime', 'availableprocessors', 'cpuload', 'heapmemoryused']
|
||||
if (store.getters.metrics) {
|
||||
fields.push(...metricsFields)
|
||||
}
|
||||
return fields
|
||||
},
|
||||
details: ['collectiontime', 'usageislocal', 'dbislocal', 'lastserverstart', 'lastserverstop', 'lastboottime', 'version', 'loginfo', 'systemtotalcpucycles', 'systemloadaverages', 'systemcycleusage', 'systemmemorytotal', 'systemmemoryfree', 'systemmemoryvirtualsize', 'availableprocessors', 'javadistribution', 'javaversion', 'osdistribution', 'kernelversion', 'agentcount', 'sessions', 'heapmemoryused', 'heapmemorytotal', 'threadsblockedcount', 'threadsdeamoncount', 'threadsnewcount', 'threadsrunnablecount', 'threadsterminatedcount', 'threadstotalcount', 'threadswaitingcount'],
|
||||
details: ['ipaddress', 'collectiontime', 'usageislocal', 'dbislocal', 'lastserverstart', 'lastserverstop', 'lastboottime', 'version', 'loginfo', 'systemtotalcpucycles', 'systemloadaverages', 'systemcycleusage', 'systemmemorytotal', 'systemmemoryfree', 'systemmemoryvirtualsize', 'availableprocessors', 'javadistribution', 'javaversion', 'osdistribution', 'kernelversion', 'agentcount', 'sessions', 'heapmemoryused', 'heapmemorytotal', 'threadsblockedcount', 'threadsdeamoncount', 'threadsnewcount', 'threadsrunnablecount', 'threadsterminatedcount', 'threadstotalcount', 'threadswaitingcount'],
|
||||
tabs: [
|
||||
{
|
||||
name: 'details',
|
||||
|
||||
@ -165,9 +165,10 @@ export default {
|
||||
label: 'label.action.take.snapshot',
|
||||
dataView: true,
|
||||
show: (record, store) => {
|
||||
return record.state === 'Ready' && (record.hypervisor !== 'KVM' ||
|
||||
record.hypervisor === 'KVM' && record.vmstate === 'Running' && store.features.kvmsnapshotenabled ||
|
||||
record.hypervisor === 'KVM' && record.vmstate !== 'Running')
|
||||
return record.state === 'Ready' &&
|
||||
(record.hypervisor !== 'KVM' ||
|
||||
['Stopped', 'Destroyed'].includes(record.vmstate) ||
|
||||
store.features.kvmsnapshotenabled)
|
||||
},
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/TakeSnapshot.vue')))
|
||||
@ -179,9 +180,10 @@ export default {
|
||||
label: 'label.action.recurring.snapshot',
|
||||
dataView: true,
|
||||
show: (record, store) => {
|
||||
return record.state === 'Ready' && (record.hypervisor !== 'KVM' ||
|
||||
record.hypervisor === 'KVM' && record.vmstate === 'Running' && store.features.kvmsnapshotenabled ||
|
||||
record.hypervisor === 'KVM' && record.vmstate !== 'Running')
|
||||
return record.state === 'Ready' &&
|
||||
(record.hypervisor !== 'KVM' ||
|
||||
(['Stopped', 'Destroyed'].includes(record.vmstate)) ||
|
||||
(store.features.kvmsnapshotenabled))
|
||||
},
|
||||
popup: true,
|
||||
component: shallowRef(defineAsyncComponent(() => import('@/views/storage/RecurringSnapshotVolume.vue'))),
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
<div class="form__label">{{ $t('label.hypervisor') }}</div>
|
||||
<a-select
|
||||
v-model:value="hypervisor"
|
||||
@change="resetAllFields"
|
||||
@change="hypervisor => onChangeHypervisor(hypervisor)"
|
||||
showSearch
|
||||
optionFilterProp="value"
|
||||
:filterOption="(input, option) => {
|
||||
@ -109,19 +109,28 @@
|
||||
</div>
|
||||
|
||||
<div class="form__item">
|
||||
<div class="form__label">{{ $t('label.vcenterusername') }}</div>
|
||||
<div class="form__label">{{ $t('label.vcenterdatacenter') }}</div>
|
||||
<a-input v-model:value="dataCenter"></a-input>
|
||||
</div>
|
||||
|
||||
<div class="form__item" name="useDefaultVMwareCred">
|
||||
<div class="form__label">{{ $t('label.use.existing.vcenter.credentials.from.zone') }}</div>
|
||||
<a-switch v-model="useDefaultVMwareCred" :checked="useDefaultVMwareCred" @change="onChangeUseDefaultVMwareCred()" />
|
||||
</div>
|
||||
|
||||
<template v-if="useDefaultVMwareCred === false">
|
||||
<div class="form__item">
|
||||
<div class="form__label"><span class="required">* </span>{{ $t('label.vcenterusername') }}</div>
|
||||
<span class="required required-label" ref="requiredUsername">{{ $t('label.required') }}</span>
|
||||
<a-input v-model:value="username"></a-input>
|
||||
</div>
|
||||
|
||||
<div class="form__item">
|
||||
<div class="form__label">{{ $t('label.vcenterpassword') }}</div>
|
||||
<div class="form__label"><span class="required">* </span>{{ $t('label.vcenterpassword') }}</div>
|
||||
<span class="required required-label" ref="requiredPassword">{{ $t('label.required') }}</span>
|
||||
<a-input type="password" v-model:value="password"></a-input>
|
||||
</div>
|
||||
|
||||
<div class="form__item">
|
||||
<div class="form__label">{{ $t('label.vcenterdatacenter') }}</div>
|
||||
<a-input v-model:value="dataCenter"></a-input>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<div class="form__item">
|
||||
@ -176,6 +185,7 @@ export default {
|
||||
username: null,
|
||||
password: null,
|
||||
url: null,
|
||||
useDefaultVMwareCred: true,
|
||||
host: null,
|
||||
dataCenter: null,
|
||||
ovm3pool: null,
|
||||
@ -257,6 +267,27 @@ export default {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
fetchVMwareCred () {
|
||||
this.loading = true
|
||||
this.clustertype = 'ExternalManaged'
|
||||
api('listVmwareDcs', {
|
||||
zoneid: this.zoneId
|
||||
}).then(response => {
|
||||
var vmwaredcs = response.listvmwaredcsresponse.VMwareDC
|
||||
if (vmwaredcs !== null) {
|
||||
this.host = vmwaredcs[0].vcenter
|
||||
this.dataCenter = vmwaredcs[0].name
|
||||
}
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: `${this.$t('label.error')} ${error.response.status}`,
|
||||
description: error.response.data.listvmwaredcsresponse.errortext,
|
||||
duration: 0
|
||||
})
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
toggleDedicated () {
|
||||
this.dedicatedDomainId = null
|
||||
this.dedicatedAccount = null
|
||||
@ -270,35 +301,24 @@ export default {
|
||||
}
|
||||
this.$refs.requiredCluster.classList.remove('required-label--visible')
|
||||
|
||||
if (this.hypervisor === 'VMware' && this.useDefaultVMwareCred === false) {
|
||||
if (!this.username) {
|
||||
this.$refs.requiredUsername.classList.add('required-label--visible')
|
||||
return
|
||||
}
|
||||
if (!this.password) {
|
||||
this.$refs.requiredPassword.classList.add('required-label--visible')
|
||||
return
|
||||
}
|
||||
this.$refs.requiredUsername.classList.remove('required-label--visible')
|
||||
this.$refs.requiredPassword.classList.remove('required-label--visible')
|
||||
}
|
||||
|
||||
if (this.hypervisor === 'Ovm3') {
|
||||
this.ovm3pool = 'on'
|
||||
this.ovm3cluster = 'undefined'
|
||||
this.ovm3vip = ''
|
||||
}
|
||||
|
||||
if (this.hypervisor === 'VMware') {
|
||||
this.clustertype = 'ExternalManaged'
|
||||
if ((this.host === null || this.host.length === 0) &&
|
||||
(this.dataCenter === null || this.dataCenter.length === 0)) {
|
||||
api('listVmwareDcs', {
|
||||
zoneid: this.zoneId
|
||||
}).then(response => {
|
||||
var vmwaredcs = response.listvmwaredcsresponse.VMwareDC
|
||||
if (vmwaredcs !== null) {
|
||||
this.host = vmwaredcs[0].vcenter
|
||||
this.dataCenter = vmwaredcs[0].name
|
||||
}
|
||||
this.addCluster()
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: `${this.$t('label.error')} ${error.response.status}`,
|
||||
description: error.response.data.listvmwaredcsresponse.errortext,
|
||||
duration: 0
|
||||
})
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
this.addCluster()
|
||||
},
|
||||
addCluster () {
|
||||
@ -387,7 +407,7 @@ export default {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
resetAllFields () {
|
||||
onChangeHypervisor (hypervisor) {
|
||||
this.clustertype = 'CloudManaged'
|
||||
this.username = null
|
||||
this.password = null
|
||||
@ -397,6 +417,16 @@ export default {
|
||||
this.ovm3pool = null
|
||||
this.ovm3cluster = null
|
||||
this.ovm3vip = null
|
||||
if (hypervisor === 'VMware') {
|
||||
this.fetchVMwareCred()
|
||||
}
|
||||
},
|
||||
onChangeUseDefaultVMwareCred () {
|
||||
this.useDefaultVMwareCred = !this.useDefaultVMwareCred
|
||||
if (this.useDefaultVMwareCred) {
|
||||
this.username = null
|
||||
this.password = null
|
||||
}
|
||||
},
|
||||
returnPlaceholder (field) {
|
||||
this.params.find(i => {
|
||||
|
||||
@ -28,10 +28,9 @@
|
||||
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<span :style="hierarchyExists ? 'padding-left: 0px;' : 'padding-left: 25px;'">
|
||||
<b><span v-if="record.parent">└─ </span>{{record.displaytext }} </b> {{ ' (' + record.name + ')' }}
|
||||
</span>
|
||||
<br/>
|
||||
<a-row :style="hierarchyExists ? 'padding-left: 0px;' : 'padding-left: 25px;'">
|
||||
<b><span v-if="record.parent">└─ </span>{{record.displaytext }} </b> {{ '(' + record.name + ')' }}
|
||||
</a-row>
|
||||
<span :style="record.parent ? 'padding-left: 50px; display:block' : 'padding-left: 25px; display:block'">{{ record.description }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'value'">
|
||||
|
||||
@ -116,6 +116,48 @@
|
||||
:placeholder="apiParams.maxiops.description"/>
|
||||
</a-form-item>
|
||||
</span>
|
||||
<a-form-item name="attachVolume" ref="attachVolume" v-if="!createVolumeFromVM">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.action.attach.to.instance')" :tooltip="$t('label.attach.vol.to.instance')" />
|
||||
</template>
|
||||
<a-switch v-model:checked="form.attachVolume" :checked="attachVolume" @change="zone => onChangeAttachToVM(zone.id)" />
|
||||
</a-form-item>
|
||||
<span v-if="attachVolume">
|
||||
<a-form-item :label="$t('label.virtualmachineid')" name="virtualmachineid" ref="virtualmachineid">
|
||||
<a-select
|
||||
v-focus="true"
|
||||
v-model:value="form.virtualmachineid"
|
||||
:placeholder="attachVolumeApiParams.virtualmachineid.description"
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
:filterOption="(input, option) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}" >
|
||||
<a-select-option v-for="vm in virtualmachines" :key="vm.id" :label="vm.name || vm.displayname">
|
||||
{{ vm.name || vm.displayname }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item >
|
||||
<a-form-item :label="$t('label.deviceid')">
|
||||
<div style="margin-bottom: 10px">
|
||||
<a-collapse>
|
||||
<a-collapse-panel header="More information about deviceID">
|
||||
<a-alert type="warning">
|
||||
<template #message>
|
||||
<span v-html="attachVolumeApiParams.deviceid.description" />
|
||||
</template>
|
||||
</a-alert>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</div>
|
||||
<a-input-number
|
||||
v-model:value="form.deviceid"
|
||||
style="width: 100%;"
|
||||
:min="0"
|
||||
:placeholder="$t('label.deviceid')"
|
||||
/>
|
||||
</a-form-item>
|
||||
</span>
|
||||
<div :span="24" class="action-button">
|
||||
<a-button @click="closeModal">{{ $t('label.cancel') }}</a-button>
|
||||
<a-button type="primary" ref="submit" @click="handleSubmit">{{ $t('label.ok') }}</a-button>
|
||||
@ -159,7 +201,10 @@ export default {
|
||||
offerings: [],
|
||||
customDiskOffering: false,
|
||||
loading: false,
|
||||
isCustomizedDiskIOps: false
|
||||
isCustomizedDiskIOps: false,
|
||||
virtualmachines: [],
|
||||
attachVolume: false,
|
||||
vmidtoattach: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -204,6 +249,10 @@ export default {
|
||||
}
|
||||
}]
|
||||
})
|
||||
if (this.attachVolume) {
|
||||
this.rules.virtualmachineid = [{ required: true, message: this.$t('message.error.select') }]
|
||||
this.rules.deviceid = [{ required: true, message: this.$t('message.error.select') }]
|
||||
}
|
||||
if (!this.createVolumeFromSnapshot) {
|
||||
this.rules.name = [{ required: true, message: this.$t('message.error.volume.name') }]
|
||||
this.rules.diskofferingid = [{ required: true, message: this.$t('message.error.select') }]
|
||||
@ -248,6 +297,9 @@ export default {
|
||||
this.zones = json.listzonesresponse.zone || []
|
||||
this.form.zoneid = this.zones[0].id || ''
|
||||
this.fetchDiskOfferings(this.form.zoneid)
|
||||
if (this.attachVolume) {
|
||||
this.fetchVirtualMachines(this.form.zoneid)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
@ -301,6 +353,31 @@ export default {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
fetchVirtualMachines (zoneId) {
|
||||
var params = {
|
||||
zoneid: zoneId,
|
||||
details: 'min'
|
||||
}
|
||||
if (this.owner.projectid) {
|
||||
params.projectid = this.owner.projectid
|
||||
} else {
|
||||
params.account = this.owner.account
|
||||
params.domainid = this.owner.domainid
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
var vmStates = ['Running', 'Stopped']
|
||||
vmStates.forEach((state) => {
|
||||
params.state = state
|
||||
api('listVirtualMachines', params).then(response => {
|
||||
this.virtualmachines = this.virtualmachines.concat(response.listvirtualmachinesresponse.virtualmachine || [])
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
if (this.loading) return
|
||||
this.formRef.value.validate().then(() => {
|
||||
@ -315,6 +392,10 @@ export default {
|
||||
if (this.createVolumeFromSnapshot) {
|
||||
values.snapshotid = this.resource.id
|
||||
}
|
||||
if (this.attachVolume) {
|
||||
this.vmidtoattach = values.virtualmachineid
|
||||
values.virtualmachineid = null
|
||||
}
|
||||
values.domainid = this.owner.domainid
|
||||
if (this.owner.projectid) {
|
||||
values.projectid = this.owner.projectid
|
||||
@ -330,10 +411,15 @@ export default {
|
||||
successMessage: this.$t('message.success.create.volume'),
|
||||
successMethod: (result) => {
|
||||
this.closeModal()
|
||||
if (this.createVolumeFromVM) {
|
||||
if (this.createVolumeFromVM || this.attachVolume) {
|
||||
const params = {}
|
||||
params.id = result.jobresult.volume.id
|
||||
if (this.createVolumeFromVM) {
|
||||
params.virtualmachineid = this.resource.id
|
||||
} else {
|
||||
params.virtualmachineid = this.vmidtoattach
|
||||
params.deviceid = values.deviceid
|
||||
}
|
||||
api('attachVolume', params).then(response => {
|
||||
this.$pollJob({
|
||||
jobId: response.attachvolumeresponse.jobid,
|
||||
@ -368,6 +454,14 @@ export default {
|
||||
const offering = this.offerings.filter(x => x.id === id)
|
||||
this.customDiskOffering = offering[0]?.iscustomized || false
|
||||
this.isCustomizedDiskIOps = offering[0]?.iscustomizediops || false
|
||||
},
|
||||
onChangeAttachToVM (zone) {
|
||||
this.attachVolume = !this.attachVolume
|
||||
this.virtualmachines = []
|
||||
if (this.attachVolume) {
|
||||
this.attachVolumeApiParams = this.$getApiParams('attachVolume')
|
||||
this.fetchVirtualMachines(this.form.zoneid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
@close-action="closeAction"
|
||||
@refresh="handleRefresh"/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane :tab="$t('label.scheduled.snapshots')" key="2">
|
||||
<a-tab-pane :tab="$t('label.action.recurring.snapshot')" key="2">
|
||||
<ScheduledSnapshots
|
||||
:loading="loading"
|
||||
:resource="resource"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user