Skip to content

Commit cd291f6

Browse files
author
frank
committed
From c72615de97b007517fb324044cb4625258c5fc61 Mon Sep 17 00:00:00 2001
From: Vijayendra <vijayendra.bhamidipati@citrix.com> Date: Mon, 25 Feb 2013 14:37:27 -0800 Subject: [PATCH] CS-670: Configurable setting to use linked clones or not on VMware Description: Providing support for creation of user VMs as full clones on ESX. Putting in unit tests for VO and Dao classes introduced in this commit. Signed-off-by: Vijayendra <vijayendra.bhamidipati@citrix.com> --- core/src/com/cloud/vm/UserVmCloneSettingVO.java | 50 ++++++ .../hypervisor/vmware/manager/VmwareManager.java | 3 + .../vmware/manager/VmwareManagerImpl.java | 18 +- .../hypervisor/vmware/resource/VmwareResource.java | 117 +++++++++---- server/conf/migration-components.xml | 1 + server/src/com/cloud/configuration/Config.java | 1 + server/src/com/cloud/vm/UserVmManagerImpl.java | 184 ++++++++++----------- .../com/cloud/vm/dao/UserVmCloneSettingDao.java | 37 +++++ .../cloud/vm/dao/UserVmCloneSettingDaoImpl.java | 74 +++++++++ .../vm/dao/UserVmCloneSettingDaoImplTest.java | 62 +++++++ .../UserVmCloneSettingDaoTestConfiguration.java | 52 ++++++ .../test/resources/CloneSettingDaoTestContext.xml | 42 +++++ setup/db/db/schema-410to420.sql | 9 + 13 files changed, 527 insertions(+), 123 deletions(-) create mode 100755 core/src/com/cloud/vm/UserVmCloneSettingVO.java create mode 100755 server/src/com/cloud/vm/dao/UserVmCloneSettingDao.java create mode 100755 server/src/com/cloud/vm/dao/UserVmCloneSettingDaoImpl.java create mode 100644 server/test/com/cloud/vm/dao/UserVmCloneSettingDaoImplTest.java create mode 100644 server/test/com/cloud/vm/dao/UserVmCloneSettingDaoTestConfiguration.java create mode 100644 server/test/resources/CloneSettingDaoTestContext.xml
1 parent cc25e58 commit cd291f6

13 files changed

Lines changed: 527 additions & 123 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.vm;
18+
19+
import javax.persistence.Column;
20+
import javax.persistence.Entity;
21+
import javax.persistence.Table;
22+
23+
@Entity
24+
@Table(name="user_vm_clone_setting")
25+
public class UserVmCloneSettingVO {
26+
27+
@Column(name="vm_id")
28+
private Long vmId;
29+
30+
@Column(name="clone_type")
31+
private String cloneType;
32+
33+
public UserVmCloneSettingVO() {
34+
35+
}
36+
37+
public UserVmCloneSettingVO(long id,
38+
String cloneType) {
39+
this.vmId = id;
40+
this.cloneType = cloneType;
41+
}
42+
43+
public long getVmId() {
44+
return this.vmId;
45+
}
46+
47+
public String getCloneType() {
48+
return this.cloneType;
49+
}
50+
}

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.Map;
2222

2323
import com.cloud.hypervisor.Hypervisor.HypervisorType;
24+
import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
2425
import com.cloud.hypervisor.vmware.mo.HostMO;
2526
import com.cloud.hypervisor.vmware.util.VmwareContext;
2627
import com.cloud.utils.Pair;
@@ -60,6 +61,8 @@ List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceContext, l
6061

6162
boolean getNexusVSwitchGlobalParameter();
6263

64+
boolean getFullCloneFlag();
65+
6366
Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId);
6467

6568
String getPrivateVSwitchName(long dcId, HypervisorType hypervisorType);

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
import com.vmware.vim25.HostConnectSpec;
9797
import com.vmware.vim25.ManagedObjectReference;
9898

99+
99100
@Local(value = {VmwareManager.class})
100101
public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener {
101102
private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class);
@@ -130,6 +131,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
130131
String _publicNetworkVSwitchName;
131132
String _guestNetworkVSwitchName;
132133
boolean _nexusVSwitchActive;
134+
boolean _fullCloneFlag;
133135
String _serviceConsoleName;
134136
String _managemetPortGroupName;
135137
String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
@@ -197,11 +199,17 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
197199
if(value == null) {
198200
_nexusVSwitchActive = false;
199201
}
200-
else
201-
{
202+
else {
202203
_nexusVSwitchActive = Boolean.parseBoolean(value);
203204
}
204205

206+
value = _configDao.getValue(Config.VmwareCreateFullClone.key());
207+
if (value == null) {
208+
_fullCloneFlag = false;
209+
} else {
210+
_fullCloneFlag = Boolean.parseBoolean(value);
211+
}
212+
205213
_privateNetworkVSwitchName = _configDao.getValue(Config.VmwarePrivateNetworkVSwitch.key());
206214

207215
if (_privateNetworkVSwitchName == null) {
@@ -315,6 +323,11 @@ public boolean getNexusVSwitchGlobalParameter() {
315323
return _nexusVSwitchActive;
316324
}
317325

326+
@Override
327+
public boolean getFullCloneFlag() {
328+
return _fullCloneFlag;
329+
}
330+
318331
@Override
319332
public String composeWorkerName() {
320333
return UUID.randomUUID().toString().replace("-", "");
@@ -495,6 +508,7 @@ public void setupResourceStartupParams(Map<String, Object> params) {
495508
params.put("public.network.vswitch.name", _publicNetworkVSwitchName);
496509
params.put("guest.network.vswitch.name", _guestNetworkVSwitchName);
497510
params.put("vmware.use.nexus.vswitch", _nexusVSwitchActive);
511+
params.put("vmware.create.full.clone", _fullCloneFlag);
498512
params.put("service.console.name", _serviceConsoleName);
499513
params.put("management.portgroup.name", _managemetPortGroupName);
500514
params.put("vmware.reserve.cpu", _reserveCpu);

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 89 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,9 @@
159159
import com.cloud.agent.api.storage.DestroyCommand;
160160
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
161161
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
162-
import com.cloud.agent.api.to.FirewallRuleTO;
163162
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
164163
import com.cloud.agent.api.storage.ResizeVolumeCommand;
164+
import com.cloud.agent.api.to.FirewallRuleTO;
165165
import com.cloud.agent.api.to.IpAddressTO;
166166
import com.cloud.agent.api.to.NicTO;
167167
import com.cloud.agent.api.to.PortForwardingRuleTO;
@@ -192,6 +192,7 @@
192192
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
193193
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostNetworkSummary;
194194
import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostResourceSummary;
195+
import com.cloud.hypervisor.vmware.resource.VmwareContextFactory;
195196
import com.cloud.hypervisor.vmware.util.VmwareContext;
196197
import com.cloud.hypervisor.vmware.util.VmwareGuestOsMapper;
197198
import com.cloud.hypervisor.vmware.util.VmwareHelper;
@@ -260,6 +261,7 @@
260261
import com.vmware.vim25.VirtualMachineRuntimeInfo;
261262
import com.vmware.vim25.VirtualSCSISharing;
262263

264+
263265
public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
264266
private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
265267

@@ -288,6 +290,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
288290
protected String _guestNetworkVSwitchName;
289291
protected VirtualSwitchType _vSwitchType = VirtualSwitchType.StandardVirtualSwitch;
290292
protected boolean _nexusVSwitch = false;
293+
protected boolean _fullCloneFlag = false;
291294

292295
protected boolean _reserveCpu = false;
293296

@@ -3695,9 +3698,17 @@ public Answer execute(DestroyCommand cmd) {
36953698
dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
36963699

36973700
// root volume may be created via linked-clone, delete the delta disk as well
3698-
if (s_logger.isInfoEnabled())
3701+
if (_fullCloneFlag) {
3702+
if (s_logger.isInfoEnabled()) {
3703+
s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
3704+
}
3705+
dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
3706+
} else {
3707+
if (s_logger.isInfoEnabled()) {
36993708
s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-delta.vmdk");
3709+
}
37003710
dsMo.deleteFile(cmd.getVolume().getPath() + "-delta.vmdk", morDc, true);
3711+
}
37013712
return new Answer(cmd, true, "Success");
37023713
}
37033714

@@ -3799,6 +3810,70 @@ public CopyVolumeAnswer execute(CopyVolumeCommand cmd) {
37993810
}
38003811
}
38013812

3813+
3814+
3815+
private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
3816+
String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
3817+
3818+
if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
3819+
dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
3820+
3821+
s_logger.info("creating full clone from template");
3822+
if (!vmTemplate.createFullClone(vmdkName, dcMo.getVmFolder(), morPool, morDatastore)) {
3823+
String msg = "Unable to create full clone from the template";
3824+
s_logger.error(msg);
3825+
throw new Exception(msg);
3826+
}
3827+
3828+
// we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
3829+
// to move files
3830+
s_logger.info("Move volume out of volume-wrapper VM ");
3831+
dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
3832+
dcMo.getMor(), dsMo.getMor(),
3833+
String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
3834+
3835+
dsMo.moveDatastoreFile(String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmdkName, vmdkName),
3836+
dcMo.getMor(), dsMo.getMor(),
3837+
String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
3838+
3839+
return true;
3840+
}
3841+
3842+
private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
3843+
String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
3844+
3845+
ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base");
3846+
if (morBaseSnapshot == null) {
3847+
String msg = "Unable to find template base snapshot, invalid template";
3848+
s_logger.error(msg);
3849+
throw new Exception(msg);
3850+
}
3851+
3852+
if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
3853+
dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
3854+
3855+
s_logger.info("creating linked clone from template");
3856+
if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) {
3857+
String msg = "Unable to clone from the template";
3858+
s_logger.error(msg);
3859+
throw new Exception(msg);
3860+
}
3861+
3862+
// we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
3863+
// to move files
3864+
s_logger.info("Move volume out of volume-wrapper VM ");
3865+
dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
3866+
dcMo.getMor(), dsMo.getMor(),
3867+
String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
3868+
3869+
dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName),
3870+
dcMo.getMor(), dsMo.getMor(),
3871+
String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
3872+
3873+
return true;
3874+
}
3875+
3876+
38023877
@Override
38033878
public synchronized CreateAnswer execute(CreateCommand cmd) {
38043879
if (s_logger.isInfoEnabled()) {
@@ -3858,37 +3933,16 @@ public synchronized CreateAnswer execute(CreateCommand cmd) {
38583933

38593934
ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
38603935
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
3861-
ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base");
3862-
if (morBaseSnapshot == null) {
3863-
String msg = "Unable to find template base snapshot, invalid template";
3864-
s_logger.error(msg);
3865-
throw new Exception(msg);
3866-
}
3867-
3868-
if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
3869-
dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
3870-
3871-
s_logger.info("create linked clone from template");
3872-
if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) {
3873-
String msg = "Unable to clone from the template";
3874-
s_logger.error(msg);
3875-
throw new Exception(msg);
3936+
//createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
3937+
if (!_fullCloneFlag) {
3938+
createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
3939+
} else {
3940+
createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
38763941
}
38773942

38783943
VirtualMachineMO vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName);
38793944
assert (vmMo != null);
38803945

3881-
// we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
3882-
// to move files
3883-
s_logger.info("Move volume out of volume-wrapper VM ");
3884-
dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
3885-
dcMo.getMor(), dsMo.getMor(),
3886-
String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
3887-
3888-
dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName),
3889-
dcMo.getMor(), dsMo.getMor(),
3890-
String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
3891-
38923946
s_logger.info("detach disks from volume-wrapper VM " + vmdkName);
38933947
vmMo.detachAllDisks();
38943948

@@ -4888,6 +4942,13 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
48884942
if(value != null && value.equalsIgnoreCase("true"))
48894943
_nexusVSwitch = true;
48904944

4945+
value = params.get("vmware.create.full.clone").toString();
4946+
if (value != null && value.equalsIgnoreCase("true")) {
4947+
_fullCloneFlag = true;
4948+
} else {
4949+
_fullCloneFlag = false;
4950+
}
4951+
48914952
s_logger.info("VmwareResource network configuration info. private vSwitch: " + _privateNetworkVSwitchName + ", public vSwitch: " + _publicNetworkVSwitchName + ", guest network: "
48924953
+ _guestNetworkVSwitchName);
48934954

server/conf/migration-components.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ under the License.
3535
<dao name="VM Instance dao" class="com.cloud.vm.dao.VMInstanceDaoImpl" />
3636
<dao name="Volume dao" class="com.cloud.storage.dao.VolumeDaoImpl" />
3737
<dao name="User VM dao" class="com.cloud.vm.dao.UserVmDaoImpl" />
38+
<dao name="User VM clone setting dao" class="com.cloud.vm.dao.UserVmCloneSettingDaoImpl" />
3839
<dao name="domain router dao" class="com.cloud.vm.dao.DomainRouterDaoImpl" />
3940
<dao name="Storage pool dao" class="com.cloud.storage.dao.StoragePoolDaoImpl" />
4041
<dao name="Account dao" class="com.cloud.user.dao.AccountDaoImpl" />

server/src/com/cloud/configuration/Config.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ public enum Config {
255255
VmwarePublicNetworkVSwitch("Hidden", ManagementServer.class, String.class, "vmware.public.vswitch", null, "Specify the vSwitch on host for public network", null),
256256
VmwareGuestNetworkVSwitch("Hidden", ManagementServer.class, String.class, "vmware.guest.vswitch", null, "Specify the vSwitch on host for guest network", null),
257257
VmwareUseNexusVSwitch("Network", ManagementServer.class, Boolean.class, "vmware.use.nexus.vswitch", "false", "Enable/Disable Cisco Nexus 1000v vSwitch in VMware environment", null),
258+
VmwareCreateFullClone("Advanced", ManagementServer.class, Boolean.class, "vmware.create.full.clone", "false", "If set to true, creates guest VMs as full clones on ESX", null),
258259
VmwareServiceConsole("Advanced", ManagementServer.class, String.class, "vmware.service.console", "Service Console", "Specify the service console network name(for ESX hosts)", null),
259260
VmwareManagementPortGroup("Advanced", ManagementServer.class, String.class, "vmware.management.portgroup", "Management Network", "Specify the management network name(for ESXi hosts)", null),
260261
VmwareAdditionalVncPortRangeStart("Advanced", ManagementServer.class, Integer.class, "vmware.additional.vnc.portrange.start", "50000", "Start port number of additional VNC port range", null),

0 commit comments

Comments
 (0)