diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index 10fb6df3a18..1cc5bc8ae01 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -84,6 +84,7 @@ import org.apache.cloudstack.api.response.RemoteAccessVpnResponse; import org.apache.cloudstack.api.response.ResourceCountResponse; import org.apache.cloudstack.api.response.ResourceLimitResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.SSHKeyPairResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.ServiceResponse; @@ -186,6 +187,7 @@ import com.cloud.storage.snapshot.SnapshotPolicy; import com.cloud.storage.snapshot.SnapshotSchedule; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; +import com.cloud.user.SSHKeyPair; import com.cloud.user.User; import com.cloud.user.UserAccount; import com.cloud.uservm.UserVm; @@ -446,4 +448,5 @@ public interface ResponseGenerator { ListResponse createUpgradeRouterTemplateResponse(List jobIds); + SSHKeyPairResponse createSSHKeyPairResponse(SSHKeyPair sshkeyPair, boolean privatekey); } diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java index bd7f613f897..c275f80cf3b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java @@ -91,7 +91,7 @@ public class CreateSSHKeyPairCmd extends BaseCmd { @Override public void execute() { SSHKeyPair r = _mgr.createSSHKeyPair(this); - CreateSSHKeyPairResponse response = new CreateSSHKeyPairResponse(r.getName(), r.getFingerprint(), r.getPrivateKey()); + CreateSSHKeyPairResponse response = (CreateSSHKeyPairResponse) _responseGenerator.createSSHKeyPairResponse(r, true); response.setResponseName(getCommandName()); response.setObjectName("keypair"); setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java index 022cbc5068f..1a77a660dcd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java @@ -68,7 +68,7 @@ public class ListSSHKeyPairsCmd extends BaseListProjectAndAccountResourcesCmd { Pair, Integer> resultList = _mgr.listSSHKeyPairs(this); List responses = new ArrayList(); for (SSHKeyPair result : resultList.first()) { - SSHKeyPairResponse r = new SSHKeyPairResponse(result.getName(), result.getFingerprint()); + SSHKeyPairResponse r = _responseGenerator.createSSHKeyPairResponse(result, false); r.setObjectName("sshkeypair"); responses.add(r); } diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java index c7cbc56ae65..ed9c4cd304e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java @@ -99,7 +99,7 @@ public class RegisterSSHKeyPairCmd extends BaseCmd { @Override public void execute() { SSHKeyPair result = _mgr.registerSSHKeyPair(this); - SSHKeyPairResponse response = new SSHKeyPairResponse(result.getName(), result.getFingerprint()); + SSHKeyPairResponse response = _responseGenerator.createSSHKeyPairResponse(result, false); response.setResponseName(getCommandName()); response.setObjectName("keypair"); setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java index 76e3db07b75..3d50fbe5551 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java @@ -120,6 +120,9 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd { @Parameter(name = ApiConstants.AFFINITY_GROUP_ID, type = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "list vms by affinity group") private Long affinityGroupId; + @Parameter(name = ApiConstants.SSH_KEYPAIR, type = CommandType.STRING, description = "list vms by ssh keypair name") + private String keypair; + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, description = "list by the service offering", since = "4.4") private Long serviceOffId; @@ -184,6 +187,10 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd { return affinityGroupId; } + public String getKeyPairName() { + return keypair; + } + public EnumSet getDetails() throws InvalidParameterValueException { EnumSet dv; if (viewDetails == null || viewDetails.size() <= 0) { diff --git a/api/src/org/apache/cloudstack/api/response/SSHKeyPairResponse.java b/api/src/org/apache/cloudstack/api/response/SSHKeyPairResponse.java index 4e1d3149951..9121957170e 100644 --- a/api/src/org/apache/cloudstack/api/response/SSHKeyPairResponse.java +++ b/api/src/org/apache/cloudstack/api/response/SSHKeyPairResponse.java @@ -29,6 +29,15 @@ public class SSHKeyPairResponse extends BaseResponse { @Param(description = "Name of the keypair") private String name; + @SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner of the keypair") + private String accountName; + + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain id of the keypair owner") + private String domainId; + + @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the keypair owner") + private String domain; + @SerializedName("fingerprint") @Param(description = "Fingerprint of the public key") private String fingerprint; @@ -57,4 +66,15 @@ public class SSHKeyPairResponse extends BaseResponse { this.fingerprint = fingerprint; } + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public void setDomainId(String domainId) { + this.domainId = domainId; + } + + public void setDomainName(String domain) { + this.domain = domain; + } } diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index 53ca37c9eaa..2f1d8fc3e5d 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -827,6 +827,7 @@ label.menu.templates=Templates label.menu.virtual.appliances=Virtual Appliances label.menu.virtual.resources=Virtual Resources label.menu.volumes=Volumes +label.menu.sshkeypair=SSH KeyPair label.migrate.instance.to.host=Migrate instance to another host label.migrate.instance.to.ps=Migrate instance to another primary storage label.migrate.instance.to=Migrate instance to diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index f4be820048f..89c1eb7c352 100644 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -58,6 +58,7 @@ import org.apache.cloudstack.api.response.ControlledEntityResponse; import org.apache.cloudstack.api.response.ControlledViewEntityResponse; import org.apache.cloudstack.api.response.CounterResponse; import org.apache.cloudstack.api.response.CreateCmdResponse; +import org.apache.cloudstack.api.response.CreateSSHKeyPairResponse; import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.DomainRouterResponse; @@ -105,6 +106,7 @@ import org.apache.cloudstack.api.response.RemoteAccessVpnResponse; import org.apache.cloudstack.api.response.ResourceCountResponse; import org.apache.cloudstack.api.response.ResourceLimitResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.SSHKeyPairResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.SecurityGroupRuleResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; @@ -291,6 +293,7 @@ import com.cloud.storage.snapshot.SnapshotSchedule; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountManager; +import com.cloud.user.SSHKeyPair; import com.cloud.user.User; import com.cloud.user.UserAccount; import com.cloud.uservm.UserVm; @@ -3654,4 +3657,17 @@ public class ApiResponseHelper implements ResponseGenerator { return response; } + @Override + public SSHKeyPairResponse createSSHKeyPairResponse(SSHKeyPair sshkeyPair, boolean privatekey) { + SSHKeyPairResponse response = new SSHKeyPairResponse(sshkeyPair.getName(), sshkeyPair.getFingerprint()); + if (privatekey) { + response = new CreateSSHKeyPairResponse(sshkeyPair.getName(), sshkeyPair.getFingerprint(), sshkeyPair.getPrivateKey()); + } + Account account = ApiDBUtils.findAccountById(sshkeyPair.getAccountId()); + response.setAccountName(account.getAccountName()); + Domain domain = ApiDBUtils.findDomainById(sshkeyPair.getDomainId()); + response.setDomainId(domain.getUuid()); + response.setDomainName(domain.getName()); + return response; + } } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index 9d97f3b6442..634b0655173 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -835,6 +835,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Object isoId = cmd.getIsoId(); Object vpcId = cmd.getVpcId(); Object affinityGroupId = cmd.getAffinityGroupId(); + Object keyPairName = cmd.getKeyPairName(); Object serviceOffId = cmd.getServiceOfferingId(); Object pod = null; Object hostId = null; @@ -886,6 +887,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("affinityGroupId", sb.entity().getAffinityGroupId(), SearchCriteria.Op.EQ); } + if (keyPairName != null) { + sb.and("keyPairName", sb.entity().getKeypairName(), SearchCriteria.Op.EQ); + } + if (!isRootAdmin) { sb.and("displayVm", sb.entity().isDisplayVm(), SearchCriteria.Op.EQ); } @@ -978,6 +983,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.setParameters("affinityGroupId", affinityGroupId); } + if (keyPairName != null) { + sc.setParameters("keyPairName", keyPairName); + } + if (cmd instanceof ListVMsCmdByAdmin) { ListVMsCmdByAdmin aCmd = (ListVMsCmdByAdmin)cmd; if (aCmd.getPodId() != null) { diff --git a/server/src/com/cloud/server/Criteria.java b/server/src/com/cloud/server/Criteria.java index 02bafa7b56f..47b799636bb 100644 --- a/server/src/com/cloud/server/Criteria.java +++ b/server/src/com/cloud/server/Criteria.java @@ -86,6 +86,7 @@ public class Criteria { public static final String AFFINITY_GROUP_ID = "affinitygroupid"; public static final String SERVICE_OFFERING_ID = "serviceofferingid"; public static final String DISPLAY = "display"; + public static final String SSH_KEYPAIR = "keypair"; public Criteria(String orderBy, Boolean ascending, Long offset, Long limit) { this.offset = offset; diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index f426b056ead..b525c0ef73a 100644 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -16,7 +16,9 @@ // under the License. package com.cloud.server; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; +import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -3607,7 +3609,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } String name = cmd.getName(); - String publicKey = SSHKeysHelper.getPublicKeyFromKeyMaterial(cmd.getPublicKey()); + String key = cmd.getPublicKey(); + try { + if (key != null) { + key = URLDecoder.decode(key, "UTF-8"); + } + } catch (UnsupportedEncodingException e) { + } finally { + } + String publicKey = SSHKeysHelper.getPublicKeyFromKeyMaterial(key); if (publicKey == null) { throw new InvalidParameterValueException("Public key is invalid"); diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 2ba0d5abcbf..d6225ea791a 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -5500,7 +5500,7 @@ label.error { } .multi-wizard .progress ul { - width: 780px; + width: 900px; height: 40px; float: left; clear: both; @@ -6072,7 +6072,7 @@ label.error { } /*** Data disk offering*/ -.multi-wizard.instance-wizard .data-disk-offering .content .section { +.multi-wizard.instance-wizard .content .section { padding: 9px 0 16px; margin: 12px 0 15px 8px; } @@ -12447,6 +12447,14 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it background-position: -68px -612px; } +.resetSSHKeyForVirtualMachine .icon { + background-position: -196px -3px; +} + +.resetSSHKeyForVirtualMachine:hover .icon { + background-position: -195px -586px; +} + .changeService .icon { background-position: -38px -33px; } diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index 2d15c97f347..4923b81fa26 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -829,6 +829,7 @@ dictionary = { 'label.menu.virtual.appliances': '', 'label.menu.virtual.resources': '', 'label.menu.volumes': '', +'label.menu.sshkeypair': '', 'label.migrate.instance.to': '', 'label.migrate.instance.to.host': '', 'label.migrate.instance.to.ps': '', diff --git a/ui/index.jsp b/ui/index.jsp index 086bcd06408..dee2f75ce5b 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -101,7 +101,8 @@
  • 4
  • 5
  • 6
  • -
  • 7
  • +
  • 7
  • +
  • 8
  • @@ -393,7 +394,18 @@ - + +
    +
    +
    + + +
    + +
    +
    +
    +
    @@ -535,6 +547,19 @@
    + +
    +
    + SSH Key Pairs +
    +
    + +
    +
    + +
    +
    +
    diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js index a1bf4c96e4a..62ed4b809fd 100644 --- a/ui/scripts/accounts.js +++ b/ui/scripts/accounts.js @@ -24,7 +24,7 @@ sectionSelect: { label: 'label.select-view', preFilter: function() { - return ['accounts']; + return ['accounts', 'sshkeypairs']; } }, sections: { @@ -1468,6 +1468,280 @@ } } } + }, + sshkeypairs: { + type: 'select', + id: 'sshkeypairs', + title: 'SSH Key Pairs', + listView: { + name: 'sshkeypairs', + fields: { + name: { + label: 'label.name' + }, + domain: { + label: 'label.domain' + }, + account: { + label: 'label.account' + }, + privatekey: { + label: 'Private Key', + span: false + } + }, + dataProvider: function(args) { + var data = { +// domainid: g_domainid, +// account: g_account + }; + + listViewDataProvider(args, data); + + $.ajax({ + url: createURL('listSSHKeyPairs'), + data: data, + success: function(json) { + var items = json.listsshkeypairsresponse.sshkeypair; + args.response.success({ + data: items + }); + } + }); + }, + actions: { + add: { + label: 'Create a SSH Key Pair', + + preFilter: function(args) { + return true; + }, + + messages: { + notification: function(args) { + return 'Created a SSH Key Pair.'; + } + }, + + createForm: { + title: 'Create a SSH Key Pair', + desc: 'Please fill in the following data to create or register a ssh key pair.

    (1) If public key is set, CloudStack will register the public key. You can use it through your private key.

    (2) If public key is not set, CloudStack will create a new SSH Key pair. In this case, please copy and save the private key. CloudStack will not keep it.
    ', + fields: { + name: { + label: 'label.name', + validation: { + required: true + }, + }, + publickey: { + label: 'Public Key' + }, + domain: { + label: 'label.domain', + isHidden: function(args) { + if (isAdmin() || isDomainAdmin()) + return false; + else + return true; + }, + select: function(args) { + if (isAdmin() || isDomainAdmin()) { + $.ajax({ + url: createURL("listDomains&listAll=true"), + success: function(json) { + var items = []; + items.push({ + id: "", + description: "" + }); + var domainObjs = json.listdomainsresponse.domain; + $(domainObjs).each(function() { + items.push({ + id: this.id, + description: this.path + }); + }); + args.response.success({ + data: items + }); + } + }); + args.$select.change(function() { + var $form = $(this).closest('form'); + if ($(this).val() == "") { + $form.find('.form-item[rel=account]').hide(); + } else { + $form.find('.form-item[rel=account]').css('display', 'inline-block'); + } + }); + } else { + var items = []; + items.push({ + id: "", + description: "" + }); + args.response.success({ + data: items + }); + } + }, + }, + account: { + label: 'label.account', + isHidden: function(args) { + if (isAdmin() || isDomainAdmin()) + return false; + else + return true; + } + } + } + }, + + action: function(args) { + + var data = { + name: args.data.name + }; + + if (args.data.domain != null && args.data.domain.length > 0) { + $.extend(data, { + domainid: args.data.domain + }); + if (args.data.account != null && args.data.account.length > 0) { + $.extend(data, { + account: args.data.account + }); + } + } + + if (args.data.publickey != null && args.data.publickey.length > 0) { + $.extend(data, { + publickey: encodeURIComponent(args.data.publickey) + }); + $.ajax({ + url: createURL('registerSSHKeyPair'), + data: data, + type: "POST", + success: function(json) { + var item = json.registersshkeypairresponse.keypair; + args.response.success({ + data: item + }); + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + args.response.error(errorMsg); + } + }); + } else { + $.ajax({ + url: createURL('createSSHKeyPair'), + data: data, + success: function(json) { + var item = json.createsshkeypairresponse.keypair; + args.response.success({ + data: item + }); + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + args.response.error(errorMsg); + } + }); + } + }, + + notification: { + poll: function(args) { + args.complete(); + } + } + } + }, + + detailView: { + name: 'SSH Key Pair Details', + isMaximized: true, + viewAll: { + label: 'label.instances', + path: 'instances' + }, + actions: { + remove: { + label: 'Remove SSH Key Pair', + messages: { + confirm: function(args) { + return 'Please confirm that you want to remove this SSH Key Pair'; + }, + notification: function(args) { + return 'Removed a SSH Key Pair'; + } + }, + action: function(args) { + var data = { + domainid: args.context.sshkeypairs[0].domainid, + account: args.context.sshkeypairs[0].account, + name: args.context.sshkeypairs[0].name + }; + $.ajax({ + url: createURL('deleteSSHKeyPair'), + data: data, + success: function(json) { + args.response.success(); + $(window).trigger('cloudStack.fullRefresh'); + } + }); + } + } + }, + tabs: { + details: { + title: 'label.details', + + fields: [{ + name: { + label: 'label.name', + isEditable: true, + validation: { + required: true + } + } + }, { + domain: { + label: 'label.domain' + }, + account: { + label: 'label.account' + }, + privatekey: { + label: 'Private Key', + span: false + }, + fingerprint: { + label: 'FingerPrint' + } + }], + + dataProvider: function(args) { + var data = { + name: args.context.sshkeypairs[0].name + }; + $.ajax({ + url: createURL('listSSHKeyPairs&listAll=true'), + data: data, + success: function(json) { + args.response.success({ + actionFilter: sshkeypairActionfilter, + data: json.listsshkeypairsresponse.sshkeypair[0] + }); + } + }); + } + } + } + } + } } } }; @@ -1546,4 +1820,9 @@ return allowedActions; } + var sshkeypairActionfilter = function(args) { + var allowedActions = []; + allowedActions.push("remove"); + return allowedActions; + } })(cloudStack); diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js index e4d3e30d93f..a4888853f9a 100644 --- a/ui/scripts/instanceWizard.js +++ b/ui/scripts/instanceWizard.js @@ -665,7 +665,22 @@ }, - // Step 7: Review + // Step 7: SSH Key Pairs + function(args) { + $.ajax({ + url: createURL('listSSHKeyPairs'), + success: function(json) { + var sshkeypair = json.listsshkeypairsresponse.sshkeypair; + args.response.success({ + data: { + sshkeyPairs: sshkeypair + } + }); + } + }); + }, + + // Step 8: Review function(args) { return false; } @@ -952,6 +967,13 @@ } } + //step 4: select ssh key pair + if (args.data.sshkeypair != null && args.data.sshkeypair.length > 0) { + $.extend(deployVmData, { + keypair : args.data.sshkeypair + }); + } + var displayname = args.data.displayname; if (displayname != null && displayname.length > 0) { $.extend(deployVmData, { diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index ee8ef0a70e9..90ce2b15d7b 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -362,6 +362,14 @@ }); } + if ("sshkeypairs" in args.context) { + $.extend(data, { + domainid: args.context.sshkeypairs[0].domainid, + account: args.context.sshkeypairs[0].account, + keypair: args.context.sshkeypairs[0].name + }); + } + $.ajax({ url: createURL('listVirtualMachines'), data: data, @@ -1624,7 +1632,99 @@ poll: pollAsyncJobResult } }, - + + resetSSHKeyForVirtualMachine: { + label: 'Reset SSH Key Pair', + createForm: { + title: 'Reset SSH Key Pair on VM', + desc: 'Please specify a ssh key pair that you would like to add to this VM. Please note the root password will be changed by this operation if password is enabled.', + fields: { + sshkeypair: { + label: 'New SSH Key Pair', + validation: { + required: true + }, + select: function(args) { + var data = { + domainid: args.context.instances[0].domainid, + account: args.context.instances[0].account, + listAll: true + }; + + $.ajax({ + url: createURL("listSSHKeyPairs"), + data: data, + async: false, + success: function(json) { + var items = []; + var sshkeypairs = json.listsshkeypairsresponse.sshkeypair; + if (sshkeypairs == null) { + } else { + for (var i = 0; i < sshkeypairs.length; i++) { + var sshkeypair = sshkeypairs[i]; + if (sshkeypair.name != args.context.instances[0].keypair) { + items.push({ + id: sshkeypair.name, + description: sshkeypair.name + }); + } + } + } + args.response.success({ + data: items + }); + } + }); + } + } + } + }, + + action: function(args) { + var data = { + domainid: args.context.instances[0].domainid, + account: args.context.instances[0].account, + id: args.context.instances[0].id, + keypair: args.data.sshkeypair + }; + + $.ajax({ + url: createURL("resetSSHKeyForVirtualMachine"), + data: data, + async: true, + success: function(json) { + var jid = json.resetSSHKeyforvirtualmachineresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.virtualmachine; + }, + getActionFilter: function() { + return vmActionfilter; + } + } + }); + } + }); + }, + messages: { + notification: function(args) { + return 'Reset SSH Key Pair on VM'; + }, + complete: function(args) { + if (args.password != null) { + return 'Password of the VM has been reset to ' + args.password; + } + + return false; + } + }, + notification: { + poll: pollAsyncJobResult + } + }, + assignVmToAnotherAccount: { label: 'label.assign.instance.another', createForm: { @@ -1899,6 +1999,9 @@ publicip: { label: 'label.public.ip' }, + keypair: { + label: 'SSH Key Pair' + }, domain: { label: 'label.domain' }, @@ -2387,7 +2490,7 @@ if (isAdmin() || isDomainAdmin()) { allowedActions.push("assignVmToAnotherAccount"); } - + allowedActions.push("resetSSHKeyForVirtualMachine"); } else if (jsonObj.state == 'Starting') { // allowedActions.push("stop"); } else if (jsonObj.state == 'Error') { diff --git a/ui/scripts/ui-custom/instanceWizard.js b/ui/scripts/ui-custom/instanceWizard.js index e8b0f394091..93b895aa258 100644 --- a/ui/scripts/ui-custom/instanceWizard.js +++ b/ui/scripts/ui-custom/instanceWizard.js @@ -715,6 +715,51 @@ }; }, + 'sshkeyPairs': function($step, formData) { + var originalValues = function(formData) { + if (formData.sshkeypair) { + $step.find('input[type=radio]').filter(function() { + return $(this).val() == formData.sshkeypair; + }).click(); + } else { + $step.find('input[type=radio]:first').click(); + } + }; + return { + response: { + success: function(args) { + $step.find('.main-desc, p.no-sshkey-pairs').remove(); + + if (args.data.sshkeyPairs && args.data.sshkeyPairs.length) { + $step.prepend( + $('
    ').addClass('main-desc').append( + $('

    ').html(_l('Please select a ssh key pair you want this VM to use:')) + ) + ); + $step.find('.section.no-thanks').show(); + $step.find('.select-container').append( + makeSelects( + 'sshkeypair', + args.data.sshkeyPairs, { + name: 'name', + id: 'name' + }, { + 'wizard-field': 'sshkey-pairs' + } + ) + ); + originalValues(formData); // if we can select only one. + } else { + $step.find('.section.no-thanks').hide(); + $step.find('.select-container').append( + $('

    ').addClass('no-sshkey-pairs').html(_l('You do not have any ssh key pairs. Please continue to the next step.')) + ); + } + } + } + }; + }, + 'network': function($step, formData) { var showAddNetwork = true; @@ -1253,7 +1298,7 @@ return $wizard.dialog({ title: _l('label.vm.add'), - width: 800, + width: 896, height: 570, closeOnEscape: false, zIndex: 5000 diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 07b60d95380..93eaa71a84b 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -1135,6 +1135,10 @@ }); $ul.appendTo($td); + } else if (field.span == false) { + $td.append( + $('

    ').html(_s(content))
    +                        );
                         } else {
                             $td.append(
                                 $('').html(_s(content))