diff --git a/api/src/com/cloud/uservm/UserVm.java b/api/src/com/cloud/uservm/UserVm.java index 61a839d7815..4b0c90abe73 100755 --- a/api/src/com/cloud/uservm/UserVm.java +++ b/api/src/com/cloud/uservm/UserVm.java @@ -69,5 +69,6 @@ public interface UserVm extends VirtualMachine, ControlledEntity { void setUserData(String userData); - String getSSHPublicKey(); + String getDetail(String name); + } diff --git a/core/src/com/cloud/vm/UserVmVO.java b/core/src/com/cloud/vm/UserVmVO.java index 80e7b8f66f0..eff39465915 100755 --- a/core/src/com/cloud/vm/UserVmVO.java +++ b/core/src/com/cloud/vm/UserVmVO.java @@ -17,11 +17,15 @@ */ package com.cloud.vm; +import java.util.HashMap; +import java.util.Map; + import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; +import javax.persistence.Transient; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.uservm.UserVm; @@ -65,11 +69,11 @@ public class UserVmVO extends VMInstanceVO implements UserVm { @Column(name="display_name", updatable=true, nullable=true) private String displayName; - @Column(name="ssh_public_key", updatable=true, nullable=true) - private String sshPublicKey; - transient String password; + @Transient + Map details; + @Override public String getPassword() { return password; @@ -78,15 +82,6 @@ public class UserVmVO extends VMInstanceVO implements UserVm { public void setPassword(String password) { this.password = password; } - - @Override - public String getSSHPublicKey() { - return sshPublicKey; - } - - public void setSSHPublicKey(String publicKey) { - this.sshPublicKey = publicKey; - } @Override public String getGuestIpAddress() { @@ -161,12 +156,11 @@ public class UserVmVO extends VMInstanceVO implements UserVm { long accountId, long serviceOfferingId, String userData, - String name, - String sshPublicKey) { + String name) { super(id, serviceOfferingId, name, instanceName, Type.User, templateId, hypervisorType, guestOsId, domainId, accountId, haEnabled); this.userData = userData; this.displayName = displayName != null ? displayName : null; - this.sshPublicKey = sshPublicKey; + this.details = new HashMap(); } protected UserVmVO() { @@ -219,4 +213,26 @@ public class UserVmVO extends VMInstanceVO implements UserVm { public void setDisplayName(String displayName) { this.displayName = displayName; } + + public Map getDetails() { + return details; + } + + @Override + public String getDetail(String name) { + assert (details != null) : "Did you forget to load the details?"; + + return details != null ? details.get(name) : null; + } + + public void setDetail(String name, String value) { + assert (details != null) : "Did you forget to load the details?"; + + details.put(name, value); + } + + public void setDetails(Map details) { + this.details = details; + } + } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 091d3ac1234..e2697ca5a18 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1440,6 +1440,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian String password = profile.getVirtualMachine().getPassword(); String userData = profile.getVirtualMachine().getUserData(); + String sshPublicKey = profile.getVirtualMachine().getDetail("SSH.PublicKey"); Commands cmds = new Commands(OnError.Stop); String routerControlIpAddress = null; @@ -1469,7 +1470,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian cmds.addCommand( "vmdata", generateVmDataCommand(router, nic.getIp4Address(), userData, serviceOffering, zoneName, - nic.getIp4Address(), profile.getVirtualMachine().getName(), profile.getVirtualMachine().getInstanceName(), profile.getId(), profile.getVirtualMachine().getSSHPublicKey())); + nic.getIp4Address(), profile.getVirtualMachine().getName(), profile.getVirtualMachine().getInstanceName(), profile.getId(), sshPublicKey)); try { _agentMgr.send(router.getHostId(), cmds); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index a968d184db3..0ec6d3b4642 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -332,7 +332,6 @@ public class ManagementServerImpl implements ManagementServer { private final UploadDao _uploadDao; private final CertificateDao _certDao; private final SSHKeyPairDao _sshKeyPairDao; - private final UserVmDetailsDao _userVmDetailsDao; private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); @@ -406,7 +405,6 @@ public class ManagementServerImpl implements ManagementServer { _tmpltMgr = locator.getManager(TemplateManager.class); _uploadMonitor = locator.getManager(UploadMonitor.class); _sshKeyPairDao = locator.getDao(SSHKeyPairDao.class); - _userVmDetailsDao = locator.getDao(UserVmDetailsDao.class); _userAuthenticators = locator.getAdapters(UserAuthenticator.class); if (_userAuthenticators == null || !_userAuthenticators.isSet()) { @@ -4757,12 +4755,15 @@ public class ManagementServerImpl implements ManagementServer { public String getVMPassword(GetVMPasswordCmd cmd) { Account account = UserContext.current().getCaller(); UserVmVO vm = _userVmDao.findById(cmd.getId()); - UserVmDetailVO password = _userVmDetailsDao.findDetail(cmd.getId(), "Encrypted.Password"); - - if (vm == null || password == null || password.getValue() == null || password.getValue().equals("") || vm.getAccountId() != account.getAccountId()) - throw new InvalidParameterValueException("No password for VM with id '" + getId() + "' found."); + if (vm == null || vm.getAccountId() != account.getAccountId()) + throw new InvalidParameterValueException("No VM with id '" + cmd.getId() + "' found."); + + _userVmDao.loadDetails(vm); + String password = vm.getDetail("Encrypted.Password"); + if (password == null || password.equals("")) + throw new InvalidParameterValueException("No password for VM with id '" + cmd.getId() + "' found."); - return password.getValue(); + return password; } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index f3d01f78d0b..8d3035a9e8f 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2314,13 +2314,16 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } UserVmVO vm = new UserVmVO(id, instanceName, cmd.getDisplayName(), template.getId(), hypervisorType, - template.getGuestOSId(), offering.getOfferHA(), domainId, owner.getId(), offering.getId(), userData, hostName, sshPublicKey); + template.getGuestOSId(), offering.getOfferHA(), domainId, owner.getId(), offering.getId(), userData, hostName); + vm.setDetail("SSH.PublicKey", sshPublicKey); if (_itMgr.allocate(vm, template, offering, rootDiskOffering, dataDiskOfferings, networks, null, plan, cmd.getHypervisor(), owner) == null) { return null; } + _vmDao.saveDetails(vm); + if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully allocated DB entry for " + vm); } @@ -2348,7 +2351,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException { long vmId = cmd.getEntityId(); UserVmVO vm = _vmDao.findById(vmId); - Map vmDetails = _vmDetailsDao.findDetails(vm.getId()); + _vmDao.loadDetails(vm); // Check that the password was passed in and is valid VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); @@ -2364,13 +2367,14 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager vm.setPassword(password); // Check if an SSH key pair was selected for the instance and if so use it to encrypt & save the vm password - if (vm.getSSHPublicKey() != null && password != null && !password.equals("saved_password") ) { - String encryptedPasswd = RSAHelper.encryptWithSSHPublicKey(vm.getSSHPublicKey(), password); + String sshPublicKey = vm.getDetail("SSH.PublicKey"); + if (sshPublicKey != null && !sshPublicKey.equals("") && password != null && !password.equals("saved_password") ) { + String encryptedPasswd = RSAHelper.encryptWithSSHPublicKey(sshPublicKey, password); if (encryptedPasswd == null) throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Error encrypting password"); - vmDetails.put("Encrypted.Password", encryptedPasswd); - _vmDetailsDao.persist(vm.getId(), vmDetails); + vm.setDetail("Encrypted.Password", encryptedPasswd); + _vmDao.saveDetails(vm); } long userId = UserContext.current().getCallerUserId(); diff --git a/server/src/com/cloud/vm/dao/UserVmDao.java b/server/src/com/cloud/vm/dao/UserVmDao.java index d372d9bd811..f40f52d5708 100755 --- a/server/src/com/cloud/vm/dao/UserVmDao.java +++ b/server/src/com/cloud/vm/dao/UserVmDao.java @@ -101,4 +101,9 @@ public interface UserVmDao extends GenericDao, StateDao listByAccountIdAndHostId(long accountId, long hostId); + + void loadDetails(UserVmVO vm); + + void saveDetails(UserVmVO vm); + } diff --git a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java index 73e439ded71..41170718b4c 100755 --- a/server/src/com/cloud/vm/dao/UserVmDaoImpl.java +++ b/server/src/com/cloud/vm/dao/UserVmDaoImpl.java @@ -19,6 +19,7 @@ package com.cloud.vm.dao; import java.util.Date; import java.util.List; +import java.util.Map; import javax.ejb.Local; @@ -63,6 +64,8 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use protected SearchBuilder AccountDataCenterVirtualSearch; protected final Attribute _updateTimeAttr; + protected final UserVmDetailsDaoImpl _detailsDao = ComponentLocator.inject(UserVmDetailsDaoImpl.class); + protected UserVmDaoImpl() { AccountSearch = createSearchBuilder(); AccountSearch.and("account", AccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ); @@ -415,4 +418,19 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use sc.setParameters("accountId", accountId); return listBy(sc); } + + @Override + public void loadDetails(UserVmVO vm) { + Map details = _detailsDao.findDetails(vm.getId()); + vm.setDetails(details); + } + + @Override + public void saveDetails(UserVmVO vm) { + Map details = vm.getDetails(); + if (details == null) { + return; + } + _detailsDao.persist(vm.getId(), details); + } } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index b1bf554c1ed..abe5efe9537 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -779,7 +779,6 @@ CREATE TABLE `cloud`.`user_vm` ( `external_mac_address` varchar(17) COMMENT 'mac address within the external network', `external_vlan_db_id` bigint unsigned COMMENT 'foreign key into vlan table', `user_data` varchar(2048), - `ssh_public_key` varchar(5120) COMMENT 'ssh public key', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;