Added user_vm_details table and corresponding access objects.

Moved saved encrypted passwds for getVMPassword API cmd to this new table.
Removed SSH keypair id from UserVm - only public key is needed.
This commit is contained in:
Ragnar B. Johannsson 2011-01-12 16:32:36 +00:00
parent ee923e5797
commit 3e59707dd2
10 changed files with 198 additions and 59 deletions

View File

@ -69,9 +69,5 @@ public interface UserVm extends VirtualMachine, ControlledEntity {
void setUserData(String userData);
String getEncryptedPassword();
Long getSSHKeyPairId();
String getSSHPublicKey();
}

View File

@ -0,0 +1,67 @@
package com.cloud.vm;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="user_vm_details")
public class UserVmDetailVO {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private long id;
@Column(name="vm_id")
private long vmId;
@Column(name="name")
private String name;
@Column(name="value")
private String value;
public UserVmDetailVO() {}
public UserVmDetailVO(long vmId, String name, String value) {
this.vmId = vmId;
this.name = name;
this.value = value;
}
public long getId() {
return id;
}
public long getVmId() {
return vmId;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
public void setId(long id) {
this.id = id;
}
public void setVmId(long vmId) {
this.vmId = vmId;
}
public void setName(String name) {
this.name = name;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -64,12 +64,6 @@ public class UserVmVO extends VMInstanceVO implements UserVm {
@Column(name="display_name", updatable=true, nullable=true)
private String displayName;
@Column(name="encrypted_password", updatable=true, nullable=true)
private String encryptedPassword;
@Column(name="ssh_keypair_id", updatable=true, nullable=true)
private Long sshKeyPairId;
@Column(name="ssh_public_key", updatable=true, nullable=true)
private String sshPublicKey;
@ -91,24 +85,6 @@ public class UserVmVO extends VMInstanceVO implements UserVm {
public void setSSHPublicKey(String publicKey) {
this.sshPublicKey = publicKey;
}
@Override
public String getEncryptedPassword() {
return encryptedPassword;
}
@Override
public Long getSSHKeyPairId() {
return sshKeyPairId;
}
public void setEncryptedPassword(String encryptedPassword) {
this.encryptedPassword = encryptedPassword;
}
public void setSSHKeyPairId(Long sshKeyPairId) {
this.sshKeyPairId = sshKeyPairId;
}
@Override
public String getGuestIpAddress() {
@ -181,10 +157,13 @@ public class UserVmVO extends VMInstanceVO implements UserVm {
long domainId,
long accountId,
long serviceOfferingId,
String userData, String name) {
String userData,
String name,
String sshPublicKey) {
super(id, serviceOfferingId, name, instanceName, Type.User, templateId, guestOsId, domainId, accountId, haEnabled);
this.userData = userData;
this.displayName = displayName != null ? displayName : null;
this.sshPublicKey = sshPublicKey;
}
public UserVmVO(long id,
@ -219,24 +198,6 @@ public class UserVmVO extends VMInstanceVO implements UserVm {
this.displayName = displayName;
}
public UserVmVO(long id,
String instanceName,
String displayName,
long templateId,
long guestOsId,
boolean haEnabled,
long domainId,
long accountId,
long serviceOfferingId,
String userData,
String name,
Long sshKeyPairId,
String sshPublicKey) {
this(id, instanceName, displayName, templateId, guestOsId, haEnabled, domainId, accountId, serviceOfferingId, userData, name);
this.sshKeyPairId = sshKeyPairId;
this.sshPublicKey = sshPublicKey;
}
protected UserVmVO() {
super();
}

View File

@ -130,6 +130,7 @@ import com.cloud.vm.dao.InstanceGroupVMMapDaoImpl;
import com.cloud.vm.dao.NicDaoImpl;
import com.cloud.vm.dao.SecondaryStorageVmDaoImpl;
import com.cloud.vm.dao.UserVmDaoImpl;
import com.cloud.vm.dao.UserVmDetailsDaoImpl;
import com.cloud.vm.dao.VMInstanceDaoImpl;
public class DefaultComponentLibrary implements ComponentLibrary {
@ -238,6 +239,8 @@ public class DefaultComponentLibrary implements ComponentLibrary {
addDao("SSHKeyPairDao", SSHKeyPairDaoImpl.class);
addDao("UsageEventDao", UsageEventDaoImpl.class);
addDao("ClusterDetailsDao", ClusterDetailsDaoImpl.class);
addDao("UserVmDetailsDao", UserVmDetailsDaoImpl.class);
}
Map<String, ComponentInfo<Manager>> _managers = new HashMap<String, ComponentInfo<Manager>>();

View File

@ -262,6 +262,7 @@ import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.InstanceGroupVO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
@ -272,6 +273,7 @@ import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
public class ManagementServerImpl implements ManagementServer {
@ -330,6 +332,7 @@ 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"));
@ -403,6 +406,7 @@ 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()) {
@ -4750,13 +4754,15 @@ public class ManagementServerImpl implements ManagementServer {
}
@Override
public String getVMPassword(GetVMPasswordCmd cmd) {
public String getVMPassword(GetVMPasswordCmd cmd) {
Account account = UserContext.current().getCaller();
UserVmVO vm = _userVmDao.findById(cmd.getId());
if (vm == null || vm.getEncryptedPassword() == null || vm.getEncryptedPassword().equals("") || vm.getAccountId() != account.getAccountId())
throw new InvalidParameterValueException("No password for VM with id '" + getId() + "' found.");
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.");
return vm.getEncryptedPassword();
return password.getValue();
}
}

View File

@ -207,6 +207,7 @@ import com.cloud.vm.dao.InstanceGroupDao;
import com.cloud.vm.dao.InstanceGroupVMMapDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
@Local(value={UserVmManager.class, UserVmService.class})
public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager {
private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class);
@ -264,6 +265,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
@Inject LoadBalancingRulesManager _lbMgr;
@Inject UsageEventDao _usageEventDao;
@Inject SSHKeyPairDao _sshKeyPairDao;
@Inject UserVmDetailsDao _vmDetailsDao;
private IpAddrAllocator _IpAllocator;
ScheduledExecutorService _executor = null;
@ -2237,7 +2239,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
// Find an SSH public key corresponding to the key pair name, if one is given
Long sshKeyPairId = null;
String sshPublicKey = null;
if (cmd.getSSHKeyPairName() != null && !cmd.getSSHKeyPairName().equals("")) {
Account account = UserContext.current().getCaller();
@ -2245,7 +2246,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
if (pair == null)
throw new InvalidParameterValueException("A key pair with name '" + cmd.getSSHKeyPairName() + "' was not found.");
sshKeyPairId = pair.getId();
sshPublicKey = pair.getPublicKey();
}
@ -2306,7 +2306,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
UserVmVO vm = new UserVmVO(id, instanceName, cmd.getDisplayName(),
template.getId(), template.getGuestOSId(), offering.getOfferHA(), domainId, owner.getId(), offering.getId(),
userData, hostName, sshKeyPairId, sshPublicKey);
userData, hostName, sshPublicKey);
if (_itMgr.allocate(vm, template, offering, rootDiskOffering, dataDiskOfferings, networks, null, plan, cmd.getHypervisor(), owner) == null) {
@ -2340,6 +2340,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<String, String> vmDetails = _vmDetailsDao.findDetails(vm.getId());
// Check that the password was passed in and is valid
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
@ -2355,13 +2356,13 @@ 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.getSSHKeyPairId() != null && vm.getSSHPublicKey() != null && password != null && !password.equals("saved_password") ) {
if (vm.getSSHPublicKey() != null && password != null && !password.equals("saved_password") ) {
String encryptedPasswd = RSAHelper.encryptWithSSHPublicKey(vm.getSSHPublicKey(), password);
if (encryptedPasswd == null)
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Error encrypting password");
vm.setEncryptedPassword(encryptedPasswd);
_vmDao.update(vm.getId(), vm);
vmDetails.put("Encrypted.Password", encryptedPasswd);
_vmDetailsDao.persist(vm.getId(), vmDetails);
}
long userId = UserContext.current().getCallerUserId();

View File

@ -0,0 +1,16 @@
package com.cloud.vm.dao;
import java.util.Map;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.UserVmDetailVO;
public interface UserVmDetailsDao extends GenericDao<UserVmDetailVO, Long> {
Map<String, String> findDetails(long vmId);
void persist(long vmId, Map<String, String> details);
UserVmDetailVO findDetail(long vmId, String name);
void deleteDetails(long vmId);
}

View File

@ -0,0 +1,80 @@
package com.cloud.vm.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.UserVmDetailVO;
@Local(value=UserVmDetailsDao.class)
public class UserVmDetailsDaoImpl extends GenericDaoBase<UserVmDetailVO, Long> implements UserVmDetailsDao {
protected final SearchBuilder<UserVmDetailVO> VmSearch;
protected final SearchBuilder<UserVmDetailVO> DetailSearch;
protected UserVmDetailsDaoImpl() {
VmSearch = createSearchBuilder();
VmSearch.and("vmId", VmSearch.entity().getVmId(), SearchCriteria.Op.EQ);
VmSearch.done();
DetailSearch = createSearchBuilder();
DetailSearch.and("hostId", DetailSearch.entity().getVmId(), SearchCriteria.Op.EQ);
DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ);
DetailSearch.done();
}
@Override
public void deleteDetails(long vmId) {
SearchCriteria<UserVmDetailVO> sc = VmSearch.create();
sc.setParameters("vmId", vmId);
List<UserVmDetailVO> results = search(sc, null);
for (UserVmDetailVO result : results) {
remove(result.getId());
}
}
@Override
public UserVmDetailVO findDetail(long vmId, String name) {
SearchCriteria<UserVmDetailVO> sc = DetailSearch.create();
sc.setParameters("vmId", vmId);
sc.setParameters("name", name);
return findOneBy(sc);
}
@Override
public Map<String, String> findDetails(long vmId) {
SearchCriteria<UserVmDetailVO> sc = VmSearch.create();
sc.setParameters("vmId", vmId);
List<UserVmDetailVO> results = search(sc, null);
Map<String, String> details = new HashMap<String, String>(results.size());
for (UserVmDetailVO result : results) {
details.put(result.getName(), result.getValue());
}
return details;
}
@Override
public void persist(long vmId, Map<String, String> details) {
Transaction txn = Transaction.currentTxn();
txn.start();
SearchCriteria<UserVmDetailVO> sc = VmSearch.create();
sc.setParameters("vmId", vmId);
expunge(sc);
for (Map.Entry<String, String> detail : details.entrySet()) {
UserVmDetailVO vo = new UserVmDetailVO(vmId, detail.getKey(), detail.getValue());
persist(vo);
}
txn.commit();
}
}

View File

@ -123,6 +123,8 @@ ALTER TABLE `cloud`.`user_vm` ADD INDEX `i_user_vm__external_ip_address`(`extern
ALTER TABLE `cloud`.`user_vm` ADD CONSTRAINT `fk_user_vm__external_vlan_db_id` FOREIGN KEY `fk_user_vm__external_vlan_db_id` (`external_vlan_db_id`) REFERENCES `vlan` (`id`);
ALTER TABLE `cloud`.`user_vm` ADD INDEX `i_user_vm__external_vlan_db_id`(`external_vlan_db_id`);
ALTER TABLE `cloud`.`user_vm_details` ADD CONSTRAINT `fk_user_vm_details__vm_id` FOREIGN KEY `fk_user_vm_details__vm_id`(`vm_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE;
#ALTER TABLE `cloud`.`domain_router` ADD CONSTRAINT `fk_domain_router__public_ip_address` FOREIGN KEY `fk_domain_router__public_ip_address` (`public_ip_address`) REFERENCES `user_ip_address` (`public_ip_address`);
ALTER TABLE `cloud`.`domain_router` ADD INDEX `i_domain_router__public_ip_address`(`public_ip_address`);
ALTER TABLE `cloud`.`domain_router` ADD CONSTRAINT `fk_domain_router__id` FOREIGN KEY `fk_domain_router__id` (`id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE;

View File

@ -760,12 +760,19 @@ 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),
`encrypted_password` varchar(1024) COMMENT 'vm password encrypted with the public key referenced in ssh_keypair',
`ssh_keypair_id` bigint unsigned COMMENT 'id of the ssh keypair used to access the vm and/or encrypt the password',
`ssh_public_key` varchar(5120) COMMENT 'ssh public key',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`user_vm_details` (
`id` bigint unsigned NOT NULL auto_increment,
`vm_id` bigint unsigned NOT NULL COMMENT 'vm id',
`name` varchar(255) NOT NULL,
`value` varchar(1024) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`domain_router` (
`id` bigint unsigned UNIQUE NOT NULL COMMENT 'Primary Key',
`gateway` varchar(15) COMMENT 'ip address of the gateway to this domR',