mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge branch 'pluggable_vm_snapshot'
Conflicts: client/tomcatconf/applicationContext.xml.in engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java engine/storage/integration-test/test/resources/storageContext.xml server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
This commit is contained in:
commit
51a8086cf6
@ -17,21 +17,21 @@
|
|||||||
|
|
||||||
package com.cloud.agent.api;
|
package com.cloud.agent.api;
|
||||||
|
|
||||||
import java.util.List;
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
import java.util.List;
|
||||||
|
|
||||||
public class CreateVMSnapshotAnswer extends Answer {
|
public class CreateVMSnapshotAnswer extends Answer {
|
||||||
|
|
||||||
private List<VolumeTO> volumeTOs;
|
private List<VolumeObjectTO> volumeTOs;
|
||||||
private VMSnapshotTO vmSnapshotTo;
|
private VMSnapshotTO vmSnapshotTo;
|
||||||
|
|
||||||
|
|
||||||
public List<VolumeTO> getVolumeTOs() {
|
public List<VolumeObjectTO> getVolumeTOs() {
|
||||||
return volumeTOs;
|
return volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVolumeTOs(List<VolumeTO> volumeTOs) {
|
public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ public class CreateVMSnapshotAnswer extends Answer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CreateVMSnapshotAnswer(CreateVMSnapshotCommand cmd,
|
public CreateVMSnapshotAnswer(CreateVMSnapshotCommand cmd,
|
||||||
VMSnapshotTO vmSnapshotTo, List<VolumeTO> volumeTOs) {
|
VMSnapshotTO vmSnapshotTo, List<VolumeObjectTO> volumeTOs) {
|
||||||
super(cmd, true, "");
|
super(cmd, true, "");
|
||||||
this.vmSnapshotTo = vmSnapshotTo;
|
this.vmSnapshotTo = vmSnapshotTo;
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
|
|||||||
@ -18,12 +18,14 @@ package com.cloud.agent.api;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.to.DataTO;
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
public class CreateVMSnapshotCommand extends VMSnapshotBaseCommand {
|
public class CreateVMSnapshotCommand extends VMSnapshotBaseCommand {
|
||||||
|
|
||||||
public CreateVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType, VirtualMachine.State vmState) {
|
public CreateVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType, VirtualMachine.State vmState) {
|
||||||
super(vmName, snapshot, volumeTOs, guestOSType);
|
super(vmName, snapshot, volumeTOs, guestOSType);
|
||||||
this.vmState = vmState;
|
this.vmState = vmState;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,12 +16,12 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.agent.api;
|
package com.cloud.agent.api;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
|
||||||
|
|
||||||
public class DeleteVMSnapshotAnswer extends Answer {
|
public class DeleteVMSnapshotAnswer extends Answer {
|
||||||
private List<VolumeTO> volumeTOs;
|
private List<VolumeObjectTO> volumeTOs;
|
||||||
|
|
||||||
public DeleteVMSnapshotAnswer() {
|
public DeleteVMSnapshotAnswer() {
|
||||||
}
|
}
|
||||||
@ -32,16 +32,16 @@ public class DeleteVMSnapshotAnswer extends Answer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DeleteVMSnapshotAnswer(DeleteVMSnapshotCommand cmd,
|
public DeleteVMSnapshotAnswer(DeleteVMSnapshotCommand cmd,
|
||||||
List<VolumeTO> volumeTOs) {
|
List<VolumeObjectTO> volumeTOs) {
|
||||||
super(cmd, true, "");
|
super(cmd, true, "");
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<VolumeTO> getVolumeTOs() {
|
public List<VolumeObjectTO> getVolumeTOs() {
|
||||||
return volumeTOs;
|
return volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVolumeTOs(List<VolumeTO> volumeTOs) {
|
public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,11 @@ package com.cloud.agent.api;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
|
|
||||||
public class DeleteVMSnapshotCommand extends VMSnapshotBaseCommand {
|
public class DeleteVMSnapshotCommand extends VMSnapshotBaseCommand {
|
||||||
public DeleteVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType) {
|
public DeleteVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType) {
|
||||||
super( vmName, snapshot, volumeTOs, guestOSType);
|
super( vmName, snapshot, volumeTOs, guestOSType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,14 +17,14 @@
|
|||||||
|
|
||||||
package com.cloud.agent.api;
|
package com.cloud.agent.api;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class RevertToVMSnapshotAnswer extends Answer {
|
public class RevertToVMSnapshotAnswer extends Answer {
|
||||||
|
|
||||||
private List<VolumeTO> volumeTOs;
|
private List<VolumeObjectTO> volumeTOs;
|
||||||
private VirtualMachine.State vmState;
|
private VirtualMachine.State vmState;
|
||||||
|
|
||||||
public RevertToVMSnapshotAnswer(RevertToVMSnapshotCommand cmd, boolean result,
|
public RevertToVMSnapshotAnswer(RevertToVMSnapshotCommand cmd, boolean result,
|
||||||
@ -37,7 +37,7 @@ public class RevertToVMSnapshotAnswer extends Answer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public RevertToVMSnapshotAnswer(RevertToVMSnapshotCommand cmd,
|
public RevertToVMSnapshotAnswer(RevertToVMSnapshotCommand cmd,
|
||||||
List<VolumeTO> volumeTOs,
|
List<VolumeObjectTO> volumeTOs,
|
||||||
VirtualMachine.State vmState) {
|
VirtualMachine.State vmState) {
|
||||||
super(cmd, true, "");
|
super(cmd, true, "");
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
@ -48,11 +48,11 @@ public class RevertToVMSnapshotAnswer extends Answer {
|
|||||||
return vmState;
|
return vmState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<VolumeTO> getVolumeTOs() {
|
public List<VolumeObjectTO> getVolumeTOs() {
|
||||||
return volumeTOs;
|
return volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVolumeTOs(List<VolumeTO> volumeTOs) {
|
public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,11 @@ package com.cloud.agent.api;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
public class RevertToVMSnapshotCommand extends VMSnapshotBaseCommand {
|
public class RevertToVMSnapshotCommand extends VMSnapshotBaseCommand {
|
||||||
|
|
||||||
public RevertToVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType) {
|
public RevertToVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType) {
|
||||||
super(vmName, snapshot, volumeTOs, guestOSType);
|
super(vmName, snapshot, volumeTOs, guestOSType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,27 +19,29 @@ package com.cloud.agent.api;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.to.DataTO;
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
public class VMSnapshotBaseCommand extends Command{
|
public class VMSnapshotBaseCommand extends Command{
|
||||||
protected List<VolumeTO> volumeTOs;
|
protected List<VolumeObjectTO> volumeTOs;
|
||||||
protected VMSnapshotTO target;
|
protected VMSnapshotTO target;
|
||||||
protected String vmName;
|
protected String vmName;
|
||||||
protected String guestOSType;
|
protected String guestOSType;
|
||||||
|
|
||||||
|
|
||||||
public VMSnapshotBaseCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType) {
|
public VMSnapshotBaseCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType) {
|
||||||
this.vmName = vmName;
|
this.vmName = vmName;
|
||||||
this.target = snapshot;
|
this.target = snapshot;
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
this.guestOSType = guestOSType;
|
this.guestOSType = guestOSType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<VolumeTO> getVolumeTOs() {
|
public List<VolumeObjectTO> getVolumeTOs() {
|
||||||
return volumeTOs;
|
return volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVolumeTOs(List<VolumeTO> volumeTOs) {
|
public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
|
||||||
this.volumeTOs = volumeTOs;
|
this.volumeTOs = volumeTOs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,8 @@ public class VolumeObjectTO implements DataTO {
|
|||||||
private String chainInfo;
|
private String chainInfo;
|
||||||
private Storage.ImageFormat format;
|
private Storage.ImageFormat format;
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
|
private Long deviceId;
|
||||||
private Long bytesReadRate;
|
private Long bytesReadRate;
|
||||||
private Long bytesWriteRate;
|
private Long bytesWriteRate;
|
||||||
private Long iopsReadRate;
|
private Long iopsReadRate;
|
||||||
@ -70,6 +72,7 @@ public class VolumeObjectTO implements DataTO {
|
|||||||
this.iopsReadRate = volume.getIopsReadRate();
|
this.iopsReadRate = volume.getIopsReadRate();
|
||||||
this.iopsWriteRate = volume.getIopsWriteRate();
|
this.iopsWriteRate = volume.getIopsWriteRate();
|
||||||
this.hypervisorType = volume.getHypervisorType();
|
this.hypervisorType = volume.getHypervisorType();
|
||||||
|
setDeviceId(volume.getDeviceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
@ -220,4 +223,13 @@ public class VolumeObjectTO implements DataTO {
|
|||||||
return iopsWriteRate;
|
return iopsWriteRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(Long deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||||
|
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshot;
|
||||||
|
|
||||||
|
public interface VMSnapshotStrategy {
|
||||||
|
VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot);
|
||||||
|
boolean deleteVMSnapshot(VMSnapshot vmSnapshot);
|
||||||
|
boolean revertVMSnapshot(VMSnapshot vmSnapshot);
|
||||||
|
boolean canHandle(VMSnapshot vmSnapshot);
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package com.cloud.vm.snapshot;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.api.InternalIdentity;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.TableGenerator;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "vm_snapshot_details")
|
||||||
|
public class VMSnapshotDetailsVO implements InternalIdentity {
|
||||||
|
@Id
|
||||||
|
@TableGenerator(name = "vm_snapshot_details_seq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "vm_snapshot_details_seq", allocationSize = 1)
|
||||||
|
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||||
|
@Column(name = "id")
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Column(name = "vm_snapshot_id")
|
||||||
|
Long vmSnapshotId;
|
||||||
|
|
||||||
|
@Column(name = "name")
|
||||||
|
String name;
|
||||||
|
|
||||||
|
@Column(name = "value")
|
||||||
|
String value;
|
||||||
|
|
||||||
|
public VMSnapshotDetailsVO() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public VMSnapshotDetailsVO(Long vmSnapshotId, String name, String value) {
|
||||||
|
this.vmSnapshotId = vmSnapshotId;
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getVmSnapshotId() {
|
||||||
|
return this.vmSnapshotId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVmSnapshotId(Long vmSnapshotId) {
|
||||||
|
this.vmSnapshotId = vmSnapshotId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,7 +41,7 @@ public class VMSnapshotVO implements VMSnapshot {
|
|||||||
@TableGenerator(name = "vm_snapshots_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "vm_snapshots_seq", allocationSize = 1)
|
@TableGenerator(name = "vm_snapshots_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "vm_snapshots_seq", allocationSize = 1)
|
||||||
@GeneratedValue(strategy = GenerationType.TABLE)
|
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||||
@Column(name = "id")
|
@Column(name = "id")
|
||||||
long id;
|
Long id;
|
||||||
|
|
||||||
@Column(name = "uuid")
|
@Column(name = "uuid")
|
||||||
String uuid = UUID.randomUUID().toString();
|
String uuid = UUID.randomUUID().toString();
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package com.cloud.vm.snapshot.dao;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface VMSnapshotDetailsDao extends GenericDao<VMSnapshotDetailsVO, Long> {
|
||||||
|
Map<String, String> getDetails(Long vmSnapshotId);
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package com.cloud.vm.snapshot.dao;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class VMSnapshotDetailsDaoImpl extends GenericDaoBase<VMSnapshotDetailsVO, Long> implements VMSnapshotDetailsDao {
|
||||||
|
protected final SearchBuilder<VMSnapshotDetailsVO> searchDetails;
|
||||||
|
|
||||||
|
protected VMSnapshotDetailsDaoImpl() {
|
||||||
|
super();
|
||||||
|
searchDetails = createSearchBuilder();
|
||||||
|
searchDetails.and("vmsnapshotId", searchDetails.entity().getVmSnapshotId(), SearchCriteria.Op.EQ);
|
||||||
|
searchDetails.done();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getDetails(Long vmSnapshotId) {
|
||||||
|
SearchCriteria<VMSnapshotDetailsVO> sc = searchDetails.create();
|
||||||
|
sc.setParameters("vmsnapshotId", vmSnapshotId);
|
||||||
|
|
||||||
|
List<VMSnapshotDetailsVO> details = listBy(sc);
|
||||||
|
Map<String, String> detailsMap = new HashMap<String, String>();
|
||||||
|
for (VMSnapshotDetailsVO detail : details) {
|
||||||
|
detailsMap.put(detail.getName(), detail.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return detailsMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -87,38 +87,12 @@ AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
@Inject
|
@Inject
|
||||||
EndPointSelector selector;
|
EndPointSelector selector;
|
||||||
@Inject
|
@Inject
|
||||||
TemplateManager templateMgr;
|
|
||||||
@Inject
|
|
||||||
VolumeDataStoreDao volumeStoreDao;
|
|
||||||
@Inject
|
|
||||||
HostDao hostDao;
|
|
||||||
@Inject
|
|
||||||
ConfigurationDao configDao;
|
ConfigurationDao configDao;
|
||||||
@Inject
|
@Inject
|
||||||
StorageManager storageMgr;
|
|
||||||
@Inject
|
|
||||||
VolumeDao volDao;
|
VolumeDao volDao;
|
||||||
@Inject
|
@Inject
|
||||||
VMTemplateDao templateDao;
|
|
||||||
@Inject
|
|
||||||
SnapshotManager snapshotMgr;
|
|
||||||
@Inject
|
|
||||||
SnapshotDao snapshotDao;
|
|
||||||
@Inject
|
|
||||||
SnapshotDataStoreDao _snapshotStoreDao;
|
|
||||||
@Inject
|
|
||||||
PrimaryDataStoreDao primaryDataStoreDao;
|
|
||||||
@Inject
|
|
||||||
DataStoreManager dataStoreMgr;
|
DataStoreManager dataStoreMgr;
|
||||||
@Inject
|
@Inject
|
||||||
TemplateDataStoreDao templateStoreDao;
|
|
||||||
@Inject
|
|
||||||
DiskOfferingDao diskOfferingDao;
|
|
||||||
@Inject
|
|
||||||
VMTemplatePoolDao templatePoolDao;
|
|
||||||
@Inject
|
|
||||||
VolumeOrchestrationService volumeMgr;
|
|
||||||
@Inject
|
|
||||||
StorageCacheManager cacheMgr;
|
StorageCacheManager cacheMgr;
|
||||||
@Inject
|
@Inject
|
||||||
ManagementService _mgmtServer;
|
ManagementService _mgmtServer;
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package com.cloud.vm.snapshot.dao;
|
||||||
|
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import org.apache.cloudstack.storage.test.CloudStackTestNGBase;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(locations = "classpath:/storageContext.xml")
|
||||||
|
public class VmSnapshotDaoTest extends CloudStackTestNGBase {
|
||||||
|
@Inject
|
||||||
|
VMSnapshotDetailsDao vmsnapshotDetailsDao;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVmSnapshotDetails() {
|
||||||
|
VMSnapshotDetailsVO detailsVO = new VMSnapshotDetailsVO(1L, "test", "foo");
|
||||||
|
vmsnapshotDetailsDao.persist(detailsVO);
|
||||||
|
Map<String, String> details = vmsnapshotDetailsDao.getDetails(1L);
|
||||||
|
Assert.assertTrue(details.containsKey("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,30 +16,6 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.storage.test;
|
package org.apache.cloudstack.storage.test;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.cloud.event.ActionEventUtils;
|
|
||||||
import com.cloud.event.dao.EventDaoImpl;
|
|
||||||
import org.apache.cloudstack.acl.APIChecker;
|
|
||||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
|
||||||
import org.apache.cloudstack.engine.service.api.OrchestrationService;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
|
||||||
import org.apache.cloudstack.framework.rpc.RpcProvider;
|
|
||||||
import org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl;
|
|
||||||
import org.apache.cloudstack.storage.test.ChildTestConfiguration.Library;
|
|
||||||
import org.apache.cloudstack.test.utils.SpringUtils;
|
|
||||||
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.FilterType;
|
|
||||||
import org.springframework.core.type.classreading.MetadataReader;
|
|
||||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
|
||||||
import org.springframework.core.type.filter.TypeFilter;
|
|
||||||
|
|
||||||
import com.cloud.agent.AgentManager;
|
import com.cloud.agent.AgentManager;
|
||||||
import com.cloud.alert.AlertManager;
|
import com.cloud.alert.AlertManager;
|
||||||
import com.cloud.capacity.dao.CapacityDaoImpl;
|
import com.cloud.capacity.dao.CapacityDaoImpl;
|
||||||
@ -55,6 +31,8 @@ import com.cloud.dc.dao.DataCenterDetailsDaoImpl;
|
|||||||
import com.cloud.dc.dao.HostPodDaoImpl;
|
import com.cloud.dc.dao.HostPodDaoImpl;
|
||||||
import com.cloud.dc.dao.PodVlanDaoImpl;
|
import com.cloud.dc.dao.PodVlanDaoImpl;
|
||||||
import com.cloud.domain.dao.DomainDaoImpl;
|
import com.cloud.domain.dao.DomainDaoImpl;
|
||||||
|
import com.cloud.event.ActionEventUtils;
|
||||||
|
import com.cloud.event.dao.EventDaoImpl;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.host.dao.HostDaoImpl;
|
import com.cloud.host.dao.HostDaoImpl;
|
||||||
import com.cloud.host.dao.HostDetailsDaoImpl;
|
import com.cloud.host.dao.HostDetailsDaoImpl;
|
||||||
@ -80,7 +58,6 @@ import com.cloud.storage.dao.VolumeDaoImpl;
|
|||||||
import com.cloud.storage.dao.VolumeHostDaoImpl;
|
import com.cloud.storage.dao.VolumeHostDaoImpl;
|
||||||
import com.cloud.storage.download.DownloadMonitorImpl;
|
import com.cloud.storage.download.DownloadMonitorImpl;
|
||||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||||
import com.cloud.storage.snapshot.SnapshotManager;
|
|
||||||
import com.cloud.tags.dao.ResourceTagsDaoImpl;
|
import com.cloud.tags.dao.ResourceTagsDaoImpl;
|
||||||
import com.cloud.template.TemplateManager;
|
import com.cloud.template.TemplateManager;
|
||||||
import com.cloud.user.AccountManager;
|
import com.cloud.user.AccountManager;
|
||||||
@ -96,6 +73,26 @@ import com.cloud.vm.dao.UserVmDaoImpl;
|
|||||||
import com.cloud.vm.dao.UserVmDetailsDaoImpl;
|
import com.cloud.vm.dao.UserVmDetailsDaoImpl;
|
||||||
import com.cloud.vm.dao.VMInstanceDaoImpl;
|
import com.cloud.vm.dao.VMInstanceDaoImpl;
|
||||||
import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
|
import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
|
||||||
|
import org.apache.cloudstack.acl.APIChecker;
|
||||||
|
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||||
|
import org.apache.cloudstack.engine.service.api.OrchestrationService;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
|
||||||
|
import org.apache.cloudstack.framework.rpc.RpcProvider;
|
||||||
|
import org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl;
|
||||||
|
import org.apache.cloudstack.storage.test.ChildTestConfiguration.Library;
|
||||||
|
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.FilterType;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ComponentScan(basePackageClasses = { NicDaoImpl.class, VMInstanceDaoImpl.class, VMTemplateHostDaoImpl.class,
|
@ComponentScan(basePackageClasses = { NicDaoImpl.class, VMInstanceDaoImpl.class, VMTemplateHostDaoImpl.class,
|
||||||
|
|||||||
@ -18,16 +18,42 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cloudstack.storage.test;
|
package org.apache.cloudstack.storage.test;
|
||||||
|
|
||||||
import java.net.URI;
|
import com.cloud.agent.AgentManager;
|
||||||
import java.util.ArrayList;
|
import com.cloud.agent.api.Command;
|
||||||
import java.util.List;
|
import com.cloud.dc.ClusterVO;
|
||||||
import java.util.UUID;
|
import com.cloud.dc.DataCenter.NetworkType;
|
||||||
import java.util.concurrent.ExecutionException;
|
import com.cloud.dc.DataCenterVO;
|
||||||
|
import com.cloud.dc.HostPodVO;
|
||||||
import javax.inject.Inject;
|
import com.cloud.dc.dao.ClusterDao;
|
||||||
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.dc.dao.HostPodDao;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.Host.Type;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.hypervisor.HypervisorGuruManager;
|
||||||
|
import com.cloud.org.Cluster.ClusterType;
|
||||||
|
import com.cloud.org.Managed.ManagedState;
|
||||||
|
import com.cloud.resource.ResourceManager;
|
||||||
|
import com.cloud.resource.ResourceState;
|
||||||
|
import com.cloud.storage.DataStoreRole;
|
||||||
|
import com.cloud.storage.ScopeType;
|
||||||
|
import com.cloud.storage.Snapshot;
|
||||||
|
import com.cloud.storage.SnapshotVO;
|
||||||
|
import com.cloud.storage.Storage;
|
||||||
|
import com.cloud.storage.Storage.ImageFormat;
|
||||||
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
|
import com.cloud.storage.Storage.TemplateType;
|
||||||
|
import com.cloud.storage.StoragePoolStatus;
|
||||||
|
import com.cloud.storage.VMTemplateVO;
|
||||||
|
import com.cloud.storage.Volume;
|
||||||
|
import com.cloud.storage.VolumeVO;
|
||||||
|
import com.cloud.storage.dao.SnapshotDao;
|
||||||
|
import com.cloud.storage.dao.VMTemplateDao;
|
||||||
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.utils.component.ComponentContext;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||||
@ -67,41 +93,12 @@ import org.springframework.test.context.ContextConfiguration;
|
|||||||
import org.testng.AssertJUnit;
|
import org.testng.AssertJUnit;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.cloud.agent.AgentManager;
|
import javax.inject.Inject;
|
||||||
import com.cloud.agent.api.Command;
|
import java.net.URI;
|
||||||
import com.cloud.dc.ClusterVO;
|
import java.util.ArrayList;
|
||||||
import com.cloud.dc.DataCenter.NetworkType;
|
import java.util.List;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import java.util.UUID;
|
||||||
import com.cloud.dc.HostPodVO;
|
import java.util.concurrent.ExecutionException;
|
||||||
import com.cloud.dc.dao.ClusterDao;
|
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
|
||||||
import com.cloud.dc.dao.HostPodDao;
|
|
||||||
import com.cloud.host.Host;
|
|
||||||
import com.cloud.host.Host.Type;
|
|
||||||
import com.cloud.host.HostVO;
|
|
||||||
import com.cloud.host.dao.HostDao;
|
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
|
||||||
import com.cloud.hypervisor.HypervisorGuruManager;
|
|
||||||
import com.cloud.org.Cluster.ClusterType;
|
|
||||||
import com.cloud.org.Managed.ManagedState;
|
|
||||||
import com.cloud.resource.ResourceManager;
|
|
||||||
import com.cloud.resource.ResourceState;
|
|
||||||
import com.cloud.storage.DataStoreRole;
|
|
||||||
import com.cloud.storage.ScopeType;
|
|
||||||
import com.cloud.storage.Snapshot;
|
|
||||||
import com.cloud.storage.SnapshotVO;
|
|
||||||
import com.cloud.storage.Storage;
|
|
||||||
import com.cloud.storage.Storage.ImageFormat;
|
|
||||||
import com.cloud.storage.Storage.StoragePoolType;
|
|
||||||
import com.cloud.storage.Storage.TemplateType;
|
|
||||||
import com.cloud.storage.StoragePoolStatus;
|
|
||||||
import com.cloud.storage.VMTemplateVO;
|
|
||||||
import com.cloud.storage.Volume;
|
|
||||||
import com.cloud.storage.VolumeVO;
|
|
||||||
import com.cloud.storage.dao.SnapshotDao;
|
|
||||||
import com.cloud.storage.dao.VMTemplateDao;
|
|
||||||
import com.cloud.storage.dao.VolumeDao;
|
|
||||||
import com.cloud.utils.component.ComponentContext;
|
|
||||||
|
|
||||||
@ContextConfiguration(locations = { "classpath:/storageContext.xml" })
|
@ContextConfiguration(locations = { "classpath:/storageContext.xml" })
|
||||||
public class SnapshotTest extends CloudStackTestNGBase {
|
public class SnapshotTest extends CloudStackTestNGBase {
|
||||||
@ -406,6 +403,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
|
|||||||
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
|
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
|
|
||||||
SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.TAKE);
|
SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.TAKE);
|
||||||
if (snapshotStrategy != null) {
|
if (snapshotStrategy != null) {
|
||||||
snapshot = snapshotStrategy.takeSnapshot(snapshot);
|
snapshot = snapshotStrategy.takeSnapshot(snapshot);
|
||||||
@ -428,9 +426,11 @@ public class SnapshotTest extends CloudStackTestNGBase {
|
|||||||
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
|
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
|
||||||
SnapshotInfo newSnapshot = null;
|
SnapshotInfo newSnapshot = null;
|
||||||
|
|
||||||
|
|
||||||
SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.TAKE);
|
SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.TAKE);
|
||||||
if (snapshotStrategy != null) {
|
if (snapshotStrategy != null) {
|
||||||
newSnapshot = snapshotStrategy.takeSnapshot(snapshot);
|
newSnapshot = snapshotStrategy.takeSnapshot(snapshot);
|
||||||
|
|
||||||
}
|
}
|
||||||
AssertJUnit.assertNotNull(newSnapshot);
|
AssertJUnit.assertNotNull(newSnapshot);
|
||||||
|
|
||||||
@ -480,6 +480,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
|
|||||||
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
|
SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
|
||||||
SnapshotInfo newSnapshot = null;
|
SnapshotInfo newSnapshot = null;
|
||||||
|
|
||||||
|
|
||||||
SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.TAKE);
|
SnapshotStrategy snapshotStrategy = storageStrategyFactory.getSnapshotStrategy(snapshot, SnapshotOperation.TAKE);
|
||||||
if (snapshotStrategy != null) {
|
if (snapshotStrategy != null) {
|
||||||
newSnapshot = snapshotStrategy.takeSnapshot(snapshot);
|
newSnapshot = snapshotStrategy.takeSnapshot(snapshot);
|
||||||
|
|||||||
@ -85,5 +85,10 @@
|
|||||||
<bean id="AccountGuestVlanMapDaoImpl" class="com.cloud.network.dao.AccountGuestVlanMapDaoImpl" />
|
<bean id="AccountGuestVlanMapDaoImpl" class="com.cloud.network.dao.AccountGuestVlanMapDaoImpl" />
|
||||||
<bean id="StorageCacheReplacementAlgorithm" class="org.apache.cloudstack.storage.cache.manager.StorageCacheReplacementAlgorithmLRU" />
|
<bean id="StorageCacheReplacementAlgorithm" class="org.apache.cloudstack.storage.cache.manager.StorageCacheReplacementAlgorithmLRU" />
|
||||||
<bean id="ServiceOfferingDetailsDao" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl" />
|
<bean id="ServiceOfferingDetailsDao" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl" />
|
||||||
|
<<<<<<< HEAD
|
||||||
<bean id="storageStrategyFactoryImpl" class="org.apache.cloudstack.storage.helper.StorageStrategyFactoryImpl" />
|
<bean id="storageStrategyFactoryImpl" class="org.apache.cloudstack.storage.helper.StorageStrategyFactoryImpl" />
|
||||||
|
=======
|
||||||
|
<bean id="vmsnapshotDetailsDao" class="com.cloud.vm.snapshot.dao.VMSnapshotDetailsDaoImpl" />
|
||||||
|
<bean id="snapshotManager" class="com.cloud.storage.snapshot.SnapshotManagerImpl" />
|
||||||
|
>>>>>>> pluggable_vm_snapshot
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
@ -30,5 +30,37 @@
|
|||||||
<artifactId>cloud-engine-api</artifactId>
|
<artifactId>cloud-engine-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.cloudstack</groupId>
|
||||||
|
<artifactId>cloud-api</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -17,11 +17,10 @@
|
|||||||
|
|
||||||
package org.apache.cloudstack.storage.snapshot;
|
package org.apache.cloudstack.storage.snapshot;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import com.cloud.storage.DataStoreRole;
|
||||||
|
import com.cloud.storage.Snapshot;
|
||||||
import javax.inject.Inject;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.fsm.NoTransitionException;
|
||||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
|
||||||
@ -41,57 +40,26 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
|||||||
import org.apache.cloudstack.framework.async.AsyncRpcContext;
|
import org.apache.cloudstack.framework.async.AsyncRpcContext;
|
||||||
import org.apache.cloudstack.storage.command.CommandResult;
|
import org.apache.cloudstack.storage.command.CommandResult;
|
||||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||||
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
|
|
||||||
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
|
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
|
||||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
|
||||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.cloud.dc.dao.ClusterDao;
|
import javax.inject.Inject;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import java.util.concurrent.ExecutionException;
|
||||||
import com.cloud.storage.Snapshot;
|
|
||||||
import com.cloud.storage.dao.SnapshotDao;
|
|
||||||
import com.cloud.storage.dao.VolumeDao;
|
|
||||||
import com.cloud.storage.snapshot.SnapshotManager;
|
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
|
||||||
import com.cloud.utils.fsm.NoTransitionException;
|
|
||||||
import com.cloud.vm.dao.UserVmDao;
|
|
||||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class SnapshotServiceImpl implements SnapshotService {
|
public class SnapshotServiceImpl implements SnapshotService {
|
||||||
private static final Logger s_logger = Logger.getLogger(SnapshotServiceImpl.class);
|
private static final Logger s_logger = Logger.getLogger(SnapshotServiceImpl.class);
|
||||||
@Inject
|
@Inject
|
||||||
protected VolumeDao _volsDao;
|
|
||||||
@Inject
|
|
||||||
protected UserVmDao _vmDao;
|
|
||||||
@Inject
|
|
||||||
protected PrimaryDataStoreDao _storagePoolDao;
|
|
||||||
@Inject
|
|
||||||
protected ClusterDao _clusterDao;
|
|
||||||
@Inject
|
|
||||||
protected SnapshotDao _snapshotDao;
|
|
||||||
@Inject
|
|
||||||
protected SnapshotDataStoreDao _snapshotStoreDao;
|
protected SnapshotDataStoreDao _snapshotStoreDao;
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected SnapshotManager snapshotMgr;
|
|
||||||
@Inject
|
|
||||||
protected VolumeOrchestrationService volumeMgr;
|
|
||||||
@Inject
|
|
||||||
protected SnapshotStateMachineManager stateMachineManager;
|
|
||||||
@Inject
|
@Inject
|
||||||
SnapshotDataFactory snapshotfactory;
|
SnapshotDataFactory snapshotfactory;
|
||||||
@Inject
|
@Inject
|
||||||
DataStoreManager dataStoreMgr;
|
DataStoreManager dataStoreMgr;
|
||||||
@Inject
|
@Inject
|
||||||
DataMotionService motionSrv;
|
DataMotionService motionSrv;
|
||||||
@Inject
|
|
||||||
ObjectInDataStoreManager objInStoreMgr;
|
|
||||||
@Inject
|
|
||||||
VMSnapshotDao _vmSnapshotDao;
|
|
||||||
|
|
||||||
static private class CreateSnapshotContext<T> extends AsyncRpcContext<T> {
|
static private class CreateSnapshotContext<T> extends AsyncRpcContext<T> {
|
||||||
final SnapshotInfo snapshot;
|
final SnapshotInfo snapshot;
|
||||||
|
|||||||
@ -16,8 +16,17 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.storage.snapshot;
|
package org.apache.cloudstack.storage.snapshot;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
|
import com.cloud.storage.DataStoreRole;
|
||||||
|
import com.cloud.storage.Snapshot;
|
||||||
|
import com.cloud.storage.SnapshotVO;
|
||||||
|
import com.cloud.storage.Volume;
|
||||||
|
import com.cloud.storage.dao.SnapshotDao;
|
||||||
|
import com.cloud.storage.snapshot.SnapshotManager;
|
||||||
|
import com.cloud.utils.NumbersUtil;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.fsm.NoTransitionException;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||||
@ -36,24 +45,12 @@ import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
|||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.cloud.exception.InvalidParameterValueException;
|
import javax.inject.Inject;
|
||||||
import com.cloud.storage.DataStoreRole;
|
|
||||||
import com.cloud.storage.Snapshot;
|
|
||||||
import com.cloud.storage.SnapshotVO;
|
|
||||||
import com.cloud.storage.Volume;
|
|
||||||
import com.cloud.storage.dao.SnapshotDao;
|
|
||||||
import com.cloud.storage.snapshot.SnapshotManager;
|
|
||||||
import com.cloud.utils.NumbersUtil;
|
|
||||||
import com.cloud.utils.db.DB;
|
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
|
||||||
import com.cloud.utils.fsm.NoTransitionException;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
|
||||||
private static final Logger s_logger = Logger.getLogger(XenserverSnapshotStrategy.class);
|
private static final Logger s_logger = Logger.getLogger(XenserverSnapshotStrategy.class);
|
||||||
|
|
||||||
@Inject
|
|
||||||
SnapshotManager snapshotMgr;
|
|
||||||
@Inject
|
@Inject
|
||||||
SnapshotService snapshotSvr;
|
SnapshotService snapshotSvr;
|
||||||
@Inject
|
@Inject
|
||||||
|
|||||||
@ -0,0 +1,370 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.cloudstack.storage.vmsnapshot;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotStrategy;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import com.cloud.agent.AgentManager;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
|
import com.cloud.agent.api.CreateVMSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.CreateVMSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.DeleteVMSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.DeleteVMSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.RevertToVMSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.RevertToVMSnapshotCommand;
|
||||||
|
import com.cloud.agent.api.VMSnapshotTO;
|
||||||
|
import com.cloud.event.EventTypes;
|
||||||
|
import com.cloud.event.UsageEventUtils;
|
||||||
|
import com.cloud.exception.AgentUnavailableException;
|
||||||
|
import com.cloud.exception.OperationTimedoutException;
|
||||||
|
import com.cloud.storage.DiskOfferingVO;
|
||||||
|
import com.cloud.storage.GuestOSVO;
|
||||||
|
import com.cloud.storage.VolumeVO;
|
||||||
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
|
import com.cloud.storage.dao.GuestOSDao;
|
||||||
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.uservm.UserVm;
|
||||||
|
import com.cloud.utils.NumbersUtil;
|
||||||
|
import com.cloud.utils.component.ManagerBase;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
|
||||||
|
import com.cloud.utils.db.TransactionStatus;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.fsm.NoTransitionException;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshot;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||||
|
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||||
|
|
||||||
|
public class DefaultVMSnapshotStrategy extends ManagerBase implements VMSnapshotStrategy {
|
||||||
|
private static final Logger s_logger = Logger.getLogger(DefaultVMSnapshotStrategy.class);
|
||||||
|
@Inject
|
||||||
|
VMSnapshotHelper vmSnapshotHelper;
|
||||||
|
@Inject
|
||||||
|
GuestOSDao guestOSDao;
|
||||||
|
@Inject
|
||||||
|
UserVmDao userVmDao;
|
||||||
|
@Inject
|
||||||
|
VMSnapshotDao vmSnapshotDao;
|
||||||
|
int _wait;
|
||||||
|
@Inject
|
||||||
|
ConfigurationDao configurationDao;
|
||||||
|
@Inject
|
||||||
|
AgentManager agentMgr;
|
||||||
|
@Inject
|
||||||
|
VolumeDao volumeDao;
|
||||||
|
@Inject
|
||||||
|
DiskOfferingDao diskOfferingDao;
|
||||||
|
@Override
|
||||||
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
|
String value = configurationDao.getValue("vmsnapshot.create.wait");
|
||||||
|
_wait = NumbersUtil.parseInt(value, 1800);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
|
||||||
|
Long hostId = vmSnapshotHelper.pickRunningHost(vmSnapshot.getVmId());
|
||||||
|
UserVm userVm = userVmDao.findById(vmSnapshot.getVmId());
|
||||||
|
VMSnapshotVO vmSnapshotVO = (VMSnapshotVO)vmSnapshot;
|
||||||
|
try {
|
||||||
|
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshotVO, VMSnapshot.Event.CreateRequested);
|
||||||
|
} catch (NoTransitionException e) {
|
||||||
|
throw new CloudRuntimeException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateVMSnapshotAnswer answer = null;
|
||||||
|
boolean result = false;
|
||||||
|
try {
|
||||||
|
GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId());
|
||||||
|
|
||||||
|
List<VolumeObjectTO> volumeTOs = vmSnapshotHelper.getVolumeTOList(userVm.getId());
|
||||||
|
|
||||||
|
VMSnapshotTO current = null;
|
||||||
|
VMSnapshotVO currentSnapshot = vmSnapshotDao.findCurrentSnapshotByVmId(userVm.getId());
|
||||||
|
if (currentSnapshot != null)
|
||||||
|
current = vmSnapshotHelper.getSnapshotWithParents(currentSnapshot);
|
||||||
|
VMSnapshotTO target = new VMSnapshotTO(vmSnapshot.getId(), vmSnapshot.getName(), vmSnapshot.getType(), null, vmSnapshot.getDescription(), false,
|
||||||
|
current);
|
||||||
|
if (current == null)
|
||||||
|
vmSnapshotVO.setParent(null);
|
||||||
|
else
|
||||||
|
vmSnapshotVO.setParent(current.getId());
|
||||||
|
|
||||||
|
CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(userVm.getInstanceName(),target ,volumeTOs, guestOS.getDisplayName(),userVm.getState());
|
||||||
|
ccmd.setWait(_wait);
|
||||||
|
|
||||||
|
answer = (CreateVMSnapshotAnswer)agentMgr.send(hostId, ccmd);
|
||||||
|
if (answer != null && answer.getResult()) {
|
||||||
|
processAnswer(vmSnapshotVO, userVm, answer, hostId);
|
||||||
|
s_logger.debug("Create vm snapshot " + vmSnapshot.getName() + " succeeded for vm: " + userVm.getInstanceName());
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
for (VolumeObjectTO volumeTo : answer.getVolumeTOs()){
|
||||||
|
publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_CREATE,vmSnapshot,userVm,volumeTo);
|
||||||
|
}
|
||||||
|
return vmSnapshot;
|
||||||
|
} else {
|
||||||
|
String errMsg = "Creating VM snapshot: " + vmSnapshot.getName() + " failed";
|
||||||
|
if(answer != null && answer.getDetails() != null)
|
||||||
|
errMsg = errMsg + " due to " + answer.getDetails();
|
||||||
|
s_logger.error(errMsg);
|
||||||
|
throw new CloudRuntimeException(errMsg);
|
||||||
|
}
|
||||||
|
} catch (OperationTimedoutException e) {
|
||||||
|
s_logger.debug("Creating VM snapshot: " + vmSnapshot.getName() + " failed: " + e.toString());
|
||||||
|
throw new CloudRuntimeException("Creating VM snapshot: " + vmSnapshot.getName() + " failed: " + e.toString());
|
||||||
|
} catch (AgentUnavailableException e) {
|
||||||
|
s_logger.debug("Creating VM snapshot: " + vmSnapshot.getName() + " failed", e);
|
||||||
|
throw new CloudRuntimeException("Creating VM snapshot: " + vmSnapshot.getName() + " failed: " + e.toString());
|
||||||
|
} finally{
|
||||||
|
if (!result) {
|
||||||
|
try {
|
||||||
|
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
|
||||||
|
} catch (NoTransitionException e1) {
|
||||||
|
s_logger.error("Cannot set vm snapshot state due to: " + e1.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteVMSnapshot(VMSnapshot vmSnapshot) {
|
||||||
|
UserVmVO userVm = userVmDao.findById(vmSnapshot.getVmId());
|
||||||
|
VMSnapshotVO vmSnapshotVO = (VMSnapshotVO)vmSnapshot;
|
||||||
|
try {
|
||||||
|
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot,VMSnapshot.Event.ExpungeRequested);
|
||||||
|
} catch (NoTransitionException e) {
|
||||||
|
s_logger.debug("Failed to change vm snapshot state with event ExpungeRequested");
|
||||||
|
throw new CloudRuntimeException("Failed to change vm snapshot state with event ExpungeRequested: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Long hostId = vmSnapshotHelper.pickRunningHost(vmSnapshot.getVmId());
|
||||||
|
|
||||||
|
List<VolumeObjectTO> volumeTOs = vmSnapshotHelper.getVolumeTOList(vmSnapshot.getVmId());
|
||||||
|
|
||||||
|
String vmInstanceName = userVm.getInstanceName();
|
||||||
|
VMSnapshotTO parent = vmSnapshotHelper.getSnapshotWithParents(vmSnapshotVO).getParent();
|
||||||
|
VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(vmSnapshot.getId(), vmSnapshot.getName(), vmSnapshot.getType(),
|
||||||
|
vmSnapshot.getCreated().getTime(), vmSnapshot.getDescription(), vmSnapshot.getCurrent(), parent);
|
||||||
|
GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId());
|
||||||
|
DeleteVMSnapshotCommand deleteSnapshotCommand = new DeleteVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs,guestOS.getDisplayName());
|
||||||
|
|
||||||
|
Answer answer = agentMgr.send(hostId, deleteSnapshotCommand);
|
||||||
|
|
||||||
|
if (answer != null && answer.getResult()) {
|
||||||
|
DeleteVMSnapshotAnswer deleteVMSnapshotAnswer = (DeleteVMSnapshotAnswer)answer;
|
||||||
|
processAnswer(vmSnapshotVO, userVm, answer, hostId);
|
||||||
|
for (VolumeObjectTO volumeTo : deleteVMSnapshotAnswer.getVolumeTOs()){
|
||||||
|
publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_DELETE,vmSnapshot,userVm,volumeTo);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
String errMsg = (answer == null) ? null : answer.getDetails();
|
||||||
|
s_logger.error("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + errMsg);
|
||||||
|
throw new CloudRuntimeException("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + errMsg);
|
||||||
|
}
|
||||||
|
} catch (OperationTimedoutException e) {
|
||||||
|
throw new CloudRuntimeException("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + e.getMessage());
|
||||||
|
} catch (AgentUnavailableException e) {
|
||||||
|
throw new CloudRuntimeException("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DB
|
||||||
|
protected void processAnswer(final VMSnapshotVO vmSnapshot, UserVm userVm, final Answer as, Long hostId) {
|
||||||
|
try {
|
||||||
|
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<NoTransitionException>() {
|
||||||
|
@Override
|
||||||
|
public void doInTransactionWithoutResult(TransactionStatus status) throws NoTransitionException {
|
||||||
|
if (as instanceof CreateVMSnapshotAnswer) {
|
||||||
|
CreateVMSnapshotAnswer answer = (CreateVMSnapshotAnswer) as;
|
||||||
|
finalizeCreate(vmSnapshot, answer.getVolumeTOs());
|
||||||
|
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationSucceeded);
|
||||||
|
} else if (as instanceof RevertToVMSnapshotAnswer) {
|
||||||
|
RevertToVMSnapshotAnswer answer = (RevertToVMSnapshotAnswer) as;
|
||||||
|
finalizeRevert(vmSnapshot, answer.getVolumeTOs());
|
||||||
|
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationSucceeded);
|
||||||
|
} else if (as instanceof DeleteVMSnapshotAnswer) {
|
||||||
|
DeleteVMSnapshotAnswer answer = (DeleteVMSnapshotAnswer) as;
|
||||||
|
finalizeDelete(vmSnapshot, answer.getVolumeTOs());
|
||||||
|
vmSnapshotDao.remove(vmSnapshot.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
String errMsg = "Error while process answer: " + as.getClass() + " due to " + e.getMessage();
|
||||||
|
s_logger.error(errMsg, e);
|
||||||
|
throw new CloudRuntimeException(errMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finalizeDelete(VMSnapshotVO vmSnapshot, List<VolumeObjectTO> VolumeTOs) {
|
||||||
|
// update volumes path
|
||||||
|
updateVolumePath(VolumeTOs);
|
||||||
|
|
||||||
|
// update children's parent snapshots
|
||||||
|
List<VMSnapshotVO> children= vmSnapshotDao.listByParent(vmSnapshot.getId());
|
||||||
|
for (VMSnapshotVO child : children) {
|
||||||
|
child.setParent(vmSnapshot.getParent());
|
||||||
|
vmSnapshotDao.persist(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update current snapshot
|
||||||
|
VMSnapshotVO current = vmSnapshotDao.findCurrentSnapshotByVmId(vmSnapshot.getVmId());
|
||||||
|
if(current != null && current.getId() == vmSnapshot.getId() && vmSnapshot.getParent() != null){
|
||||||
|
VMSnapshotVO parent = vmSnapshotDao.findById(vmSnapshot.getParent());
|
||||||
|
parent.setCurrent(true);
|
||||||
|
vmSnapshotDao.persist(parent);
|
||||||
|
}
|
||||||
|
vmSnapshot.setCurrent(false);
|
||||||
|
vmSnapshotDao.persist(vmSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finalizeCreate(VMSnapshotVO vmSnapshot, List<VolumeObjectTO> VolumeTOs) {
|
||||||
|
// update volumes path
|
||||||
|
updateVolumePath(VolumeTOs);
|
||||||
|
|
||||||
|
vmSnapshot.setCurrent(true);
|
||||||
|
|
||||||
|
// change current snapshot
|
||||||
|
if (vmSnapshot.getParent() != null) {
|
||||||
|
VMSnapshotVO previousCurrent = vmSnapshotDao.findById(vmSnapshot.getParent());
|
||||||
|
previousCurrent.setCurrent(false);
|
||||||
|
vmSnapshotDao.persist(previousCurrent);
|
||||||
|
}
|
||||||
|
vmSnapshotDao.persist(vmSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void finalizeRevert(VMSnapshotVO vmSnapshot, List<VolumeObjectTO> volumeToList) {
|
||||||
|
// update volumes path
|
||||||
|
updateVolumePath(volumeToList);
|
||||||
|
|
||||||
|
// update current snapshot, current snapshot is the one reverted to
|
||||||
|
VMSnapshotVO previousCurrent = vmSnapshotDao.findCurrentSnapshotByVmId(vmSnapshot.getVmId());
|
||||||
|
if(previousCurrent != null){
|
||||||
|
previousCurrent.setCurrent(false);
|
||||||
|
vmSnapshotDao.persist(previousCurrent);
|
||||||
|
}
|
||||||
|
vmSnapshot.setCurrent(true);
|
||||||
|
vmSnapshotDao.persist(vmSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVolumePath(List<VolumeObjectTO> volumeTOs) {
|
||||||
|
for (VolumeObjectTO volume : volumeTOs) {
|
||||||
|
if (volume.getPath() != null) {
|
||||||
|
VolumeVO volumeVO = volumeDao.findById(volume.getId());
|
||||||
|
volumeVO.setPath(volume.getPath());
|
||||||
|
volumeVO.setVmSnapshotChainSize(volume.getSize());
|
||||||
|
volumeDao.persist(volumeVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void publishUsageEvent(String type, VMSnapshot vmSnapshot, UserVm userVm, VolumeObjectTO volumeTo){
|
||||||
|
VolumeVO volume = volumeDao.findById(volumeTo.getId());
|
||||||
|
Long diskOfferingId = volume.getDiskOfferingId();
|
||||||
|
Long offeringId = null;
|
||||||
|
if (diskOfferingId != null) {
|
||||||
|
DiskOfferingVO offering = diskOfferingDao.findById(diskOfferingId);
|
||||||
|
if (offering != null
|
||||||
|
&& (offering.getType() == DiskOfferingVO.Type.Disk)) {
|
||||||
|
offeringId = offering.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UsageEventUtils.publishUsageEvent(
|
||||||
|
type,
|
||||||
|
vmSnapshot.getAccountId(),
|
||||||
|
userVm.getDataCenterId(),
|
||||||
|
userVm.getId(),
|
||||||
|
vmSnapshot.getName(),
|
||||||
|
offeringId,
|
||||||
|
volume.getId(), // save volume's id into templateId field
|
||||||
|
volumeTo.getSize(),
|
||||||
|
VMSnapshot.class.getName(), vmSnapshot.getUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean revertVMSnapshot(VMSnapshot vmSnapshot) {
|
||||||
|
VMSnapshotVO vmSnapshotVO = (VMSnapshotVO)vmSnapshot;
|
||||||
|
UserVmVO userVm = userVmDao.findById(vmSnapshot.getVmId());
|
||||||
|
try {
|
||||||
|
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshotVO, VMSnapshot.Event.RevertRequested);
|
||||||
|
} catch (NoTransitionException e) {
|
||||||
|
throw new CloudRuntimeException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean result = false;
|
||||||
|
try {
|
||||||
|
VMSnapshotVO snapshot = vmSnapshotDao.findById(vmSnapshotVO.getId());
|
||||||
|
List<VolumeObjectTO> volumeTOs = vmSnapshotHelper.getVolumeTOList(userVm.getId());
|
||||||
|
String vmInstanceName = userVm.getInstanceName();
|
||||||
|
VMSnapshotTO parent = vmSnapshotHelper.getSnapshotWithParents(snapshot).getParent();
|
||||||
|
|
||||||
|
VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(), snapshot.getType(),
|
||||||
|
snapshot.getCreated().getTime(), snapshot.getDescription(), snapshot.getCurrent(), parent);
|
||||||
|
Long hostId = vmSnapshotHelper.pickRunningHost(vmSnapshot.getVmId());
|
||||||
|
GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId());
|
||||||
|
RevertToVMSnapshotCommand revertToSnapshotCommand = new RevertToVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs, guestOS.getDisplayName());
|
||||||
|
|
||||||
|
RevertToVMSnapshotAnswer answer = (RevertToVMSnapshotAnswer) agentMgr.send(hostId, revertToSnapshotCommand);
|
||||||
|
if (answer != null && answer.getResult()) {
|
||||||
|
processAnswer(vmSnapshotVO, userVm, answer, hostId);
|
||||||
|
result = true;
|
||||||
|
} else {
|
||||||
|
String errMsg = "Revert VM: " + userVm.getInstanceName() + " to snapshot: "+ vmSnapshotVO.getName() + " failed";
|
||||||
|
if(answer != null && answer.getDetails() != null)
|
||||||
|
errMsg = errMsg + " due to " + answer.getDetails();
|
||||||
|
s_logger.error(errMsg);
|
||||||
|
throw new CloudRuntimeException(errMsg);
|
||||||
|
}
|
||||||
|
} catch (OperationTimedoutException e) {
|
||||||
|
s_logger.debug("Failed to revert vm snapshot", e);
|
||||||
|
throw new CloudRuntimeException(e.getMessage());
|
||||||
|
} catch (AgentUnavailableException e) {
|
||||||
|
s_logger.debug("Failed to revert vm snapshot", e);
|
||||||
|
throw new CloudRuntimeException(e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (!result) {
|
||||||
|
try {
|
||||||
|
vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
|
||||||
|
} catch (NoTransitionException e1) {
|
||||||
|
s_logger.error("Cannot set vm snapshot state due to: " + e1.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(VMSnapshot vmSnapshot) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.cloudstack.storage.vmsnapshot;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.VMSnapshotTO;
|
||||||
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
import com.cloud.utils.fsm.NoTransitionException;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshot;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface VMSnapshotHelper {
|
||||||
|
boolean vmSnapshotStateTransitTo(VMSnapshot vsnp, VMSnapshot.Event event) throws NoTransitionException;
|
||||||
|
|
||||||
|
Long pickRunningHost(Long vmId);
|
||||||
|
|
||||||
|
List<VolumeObjectTO> getVolumeTOList(Long vmId);
|
||||||
|
|
||||||
|
VMSnapshotTO getSnapshotWithParents(VMSnapshotVO snapshot);
|
||||||
|
}
|
||||||
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.cloudstack.storage.vmsnapshot;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.VMSnapshotTO;
|
||||||
|
import com.cloud.agent.api.to.DataTO;
|
||||||
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.storage.StoragePool;
|
||||||
|
import com.cloud.storage.VolumeVO;
|
||||||
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.utils.fsm.NoTransitionException;
|
||||||
|
import com.cloud.utils.fsm.StateMachine2;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshot;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||||
|
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class VMSnapshotHelperImpl implements VMSnapshotHelper {
|
||||||
|
@Inject
|
||||||
|
VMSnapshotDao _vmSnapshotDao;
|
||||||
|
@Inject
|
||||||
|
UserVmDao userVmDao;
|
||||||
|
@Inject
|
||||||
|
HostDao hostDao;
|
||||||
|
@Inject
|
||||||
|
VolumeDao volumeDao;
|
||||||
|
@Inject
|
||||||
|
PrimaryDataStoreDao primaryDataStoreDao;
|
||||||
|
@Inject
|
||||||
|
VolumeDataFactory volumeDataFactory;
|
||||||
|
|
||||||
|
StateMachine2<VMSnapshot.State, VMSnapshot.Event, VMSnapshot> _vmSnapshottateMachine ;
|
||||||
|
public VMSnapshotHelperImpl() {
|
||||||
|
_vmSnapshottateMachine = VMSnapshot.State.getStateMachine();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean vmSnapshotStateTransitTo(VMSnapshot vsnp, VMSnapshot.Event event) throws NoTransitionException {
|
||||||
|
return _vmSnapshottateMachine.transitTo(vsnp, event, null, _vmSnapshotDao);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long pickRunningHost(Long vmId) {
|
||||||
|
UserVmVO vm = userVmDao.findById(vmId);
|
||||||
|
// use VM's host if VM is running
|
||||||
|
if(vm.getState() == VirtualMachine.State.Running)
|
||||||
|
return vm.getHostId();
|
||||||
|
|
||||||
|
// check if lastHostId is available
|
||||||
|
if(vm.getLastHostId() != null){
|
||||||
|
HostVO lastHost = hostDao.findById(vm.getLastHostId());
|
||||||
|
if(lastHost.getStatus() == com.cloud.host.Status.Up && !lastHost.isInMaintenanceStates())
|
||||||
|
return lastHost.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<VolumeVO> listVolumes = volumeDao.findByInstance(vmId);
|
||||||
|
if (listVolumes == null || listVolumes.size() == 0) {
|
||||||
|
throw new InvalidParameterValueException("vmInstance has no volumes");
|
||||||
|
}
|
||||||
|
VolumeVO volume = listVolumes.get(0);
|
||||||
|
Long poolId = volume.getPoolId();
|
||||||
|
if (poolId == null) {
|
||||||
|
throw new InvalidParameterValueException("pool id is not found");
|
||||||
|
}
|
||||||
|
StoragePoolVO storagePool = primaryDataStoreDao.findById(poolId);
|
||||||
|
if (storagePool == null) {
|
||||||
|
throw new InvalidParameterValueException("storage pool is not found");
|
||||||
|
}
|
||||||
|
List<HostVO> listHost = hostDao.listAllUpAndEnabledNonHAHosts(Host.Type.Routing, storagePool.getClusterId(), storagePool.getPodId(),
|
||||||
|
storagePool.getDataCenterId(), null);
|
||||||
|
if (listHost == null || listHost.size() == 0) {
|
||||||
|
throw new InvalidParameterValueException("no host in up state is found");
|
||||||
|
}
|
||||||
|
return listHost.get(0).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<VolumeObjectTO> getVolumeTOList(Long vmId) {
|
||||||
|
List<VolumeObjectTO> volumeTOs = new ArrayList<VolumeObjectTO>();
|
||||||
|
List<VolumeVO> volumeVos = volumeDao.findByInstance(vmId);
|
||||||
|
VolumeInfo volumeInfo = null;
|
||||||
|
for (VolumeVO volume : volumeVos) {
|
||||||
|
volumeInfo = volumeDataFactory.getVolume(volume.getId());
|
||||||
|
|
||||||
|
volumeTOs.add((VolumeObjectTO)volumeInfo.getTO());
|
||||||
|
}
|
||||||
|
return volumeTOs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private VMSnapshotTO convert2VMSnapshotTO(VMSnapshotVO vo) {
|
||||||
|
return new VMSnapshotTO(vo.getId(), vo.getName(), vo.getType(), vo.getCreated().getTime(), vo.getDescription(),
|
||||||
|
vo.getCurrent(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VMSnapshotTO getSnapshotWithParents(VMSnapshotVO snapshot) {
|
||||||
|
Map<Long, VMSnapshotVO> snapshotMap = new HashMap<Long, VMSnapshotVO>();
|
||||||
|
List<VMSnapshotVO> allSnapshots = _vmSnapshotDao.findByVm(snapshot.getVmId());
|
||||||
|
for (VMSnapshotVO vmSnapshotVO : allSnapshots) {
|
||||||
|
snapshotMap.put(vmSnapshotVO.getId(), vmSnapshotVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMSnapshotTO currentTO = convert2VMSnapshotTO(snapshot);
|
||||||
|
VMSnapshotTO result = currentTO;
|
||||||
|
VMSnapshotVO current = snapshot;
|
||||||
|
while (current.getParent() != null) {
|
||||||
|
VMSnapshotVO parent = snapshotMap.get(current.getParent());
|
||||||
|
currentTO.setParent(convert2VMSnapshotTO(parent));
|
||||||
|
current = snapshotMap.get(current.getParent());
|
||||||
|
currentTO = currentTO.getParent();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
256
engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java
Normal file
256
engine/storage/snapshot/test/src/VMSnapshotStrategyTest.java
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package src;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotStrategy;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
import org.apache.cloudstack.storage.vmsnapshot.DefaultVMSnapshotStrategy;
|
||||||
|
import org.apache.cloudstack.storage.vmsnapshot.VMSnapshotHelper;
|
||||||
|
import org.apache.cloudstack.test.utils.SpringUtils;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.FilterType;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
|
|
||||||
|
import com.cloud.agent.AgentManager;
|
||||||
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.CreateVMSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.DeleteVMSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.RevertToVMSnapshotAnswer;
|
||||||
|
import com.cloud.agent.api.VMSnapshotTO;
|
||||||
|
import com.cloud.exception.AgentUnavailableException;
|
||||||
|
import com.cloud.exception.OperationTimedoutException;
|
||||||
|
import com.cloud.storage.GuestOSVO;
|
||||||
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
|
import com.cloud.storage.dao.GuestOSDao;
|
||||||
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
|
import com.cloud.utils.component.ComponentContext;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.utils.net.NetUtils;
|
||||||
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshot;
|
||||||
|
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||||
|
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
|
||||||
|
public class VMSnapshotStrategyTest extends TestCase {
|
||||||
|
@Inject
|
||||||
|
VMSnapshotStrategy vmSnapshotStrategy;
|
||||||
|
@Inject
|
||||||
|
VMSnapshotHelper vmSnapshotHelper;
|
||||||
|
@Inject UserVmDao userVmDao;
|
||||||
|
@Inject
|
||||||
|
GuestOSDao guestOSDao;
|
||||||
|
@Inject
|
||||||
|
AgentManager agentMgr;
|
||||||
|
@Inject
|
||||||
|
VMSnapshotDao vmSnapshotDao;
|
||||||
|
@Override
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
ComponentContext.initComponentsLifeCycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateVMSnapshot() throws AgentUnavailableException, OperationTimedoutException {
|
||||||
|
Long hostId = 1L;
|
||||||
|
Long vmId = 1L;
|
||||||
|
Long guestOsId = 1L;
|
||||||
|
List<VolumeObjectTO> volumeObjectTOs = new ArrayList<VolumeObjectTO>();
|
||||||
|
VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class);
|
||||||
|
UserVmVO userVmVO = Mockito.mock(UserVmVO.class);
|
||||||
|
Mockito.when(userVmVO.getGuestOSId()).thenReturn(guestOsId);
|
||||||
|
Mockito.when(vmSnapshot.getVmId()).thenReturn(vmId);
|
||||||
|
Mockito.when(vmSnapshotHelper.pickRunningHost(Mockito.anyLong())).thenReturn(hostId);
|
||||||
|
Mockito.when(vmSnapshotHelper.getVolumeTOList(Mockito.anyLong())).thenReturn(volumeObjectTOs);
|
||||||
|
Mockito.when(userVmDao.findById(Mockito.anyLong())).thenReturn(userVmVO);
|
||||||
|
GuestOSVO guestOSVO = Mockito.mock(GuestOSVO.class);
|
||||||
|
Mockito.when(guestOSDao.findById(Mockito.anyLong())).thenReturn(guestOSVO);
|
||||||
|
Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(null);
|
||||||
|
Exception e = null;
|
||||||
|
try {
|
||||||
|
vmSnapshotStrategy.takeVMSnapshot(vmSnapshot);
|
||||||
|
} catch (CloudRuntimeException e1) {
|
||||||
|
e = e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(e);
|
||||||
|
CreateVMSnapshotAnswer answer = Mockito.mock(CreateVMSnapshotAnswer.class);
|
||||||
|
Mockito.when(answer.getResult()).thenReturn(true);
|
||||||
|
Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(answer);
|
||||||
|
Mockito.when(vmSnapshotDao.findById(Mockito.anyLong())).thenReturn(vmSnapshot);
|
||||||
|
VMSnapshot snapshot = null;
|
||||||
|
snapshot = vmSnapshotStrategy.takeVMSnapshot(vmSnapshot);
|
||||||
|
assertNotNull(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRevertSnapshot() throws AgentUnavailableException, OperationTimedoutException {
|
||||||
|
Long hostId = 1L;
|
||||||
|
Long vmId = 1L;
|
||||||
|
Long guestOsId = 1L;
|
||||||
|
List<VolumeObjectTO> volumeObjectTOs = new ArrayList<VolumeObjectTO>();
|
||||||
|
VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class);
|
||||||
|
UserVmVO userVmVO = Mockito.mock(UserVmVO.class);
|
||||||
|
Mockito.when(userVmVO.getGuestOSId()).thenReturn(guestOsId);
|
||||||
|
Mockito.when(vmSnapshot.getVmId()).thenReturn(vmId);
|
||||||
|
Mockito.when(vmSnapshotHelper.pickRunningHost(Mockito.anyLong())).thenReturn(hostId);
|
||||||
|
Mockito.when(vmSnapshotHelper.getVolumeTOList(Mockito.anyLong())).thenReturn(volumeObjectTOs);
|
||||||
|
Mockito.when(userVmDao.findById(Mockito.anyLong())).thenReturn(userVmVO);
|
||||||
|
GuestOSVO guestOSVO = Mockito.mock(GuestOSVO.class);
|
||||||
|
Mockito.when(guestOSDao.findById(Mockito.anyLong())).thenReturn(guestOSVO);
|
||||||
|
VMSnapshotTO vmSnapshotTO = Mockito.mock(VMSnapshotTO.class);
|
||||||
|
Mockito.when(vmSnapshotHelper.getSnapshotWithParents(Mockito.any(VMSnapshotVO.class))).thenReturn(vmSnapshotTO);
|
||||||
|
Mockito.when(vmSnapshotDao.findById(Mockito.anyLong())).thenReturn(vmSnapshot);
|
||||||
|
Mockito.when(vmSnapshot.getId()).thenReturn(1L);
|
||||||
|
Mockito.when(vmSnapshot.getCreated()).thenReturn(new Date());
|
||||||
|
Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(null);
|
||||||
|
Exception e = null;
|
||||||
|
try {
|
||||||
|
vmSnapshotStrategy.revertVMSnapshot(vmSnapshot);
|
||||||
|
} catch (CloudRuntimeException e1) {
|
||||||
|
e = e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(e);
|
||||||
|
|
||||||
|
RevertToVMSnapshotAnswer answer = Mockito.mock(RevertToVMSnapshotAnswer.class);
|
||||||
|
Mockito.when(answer.getResult()).thenReturn(Boolean.TRUE);
|
||||||
|
Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(answer);
|
||||||
|
boolean result = vmSnapshotStrategy.revertVMSnapshot(vmSnapshot);
|
||||||
|
assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteVMSnapshot() throws AgentUnavailableException, OperationTimedoutException {
|
||||||
|
Long hostId = 1L;
|
||||||
|
Long vmId = 1L;
|
||||||
|
Long guestOsId = 1L;
|
||||||
|
List<VolumeObjectTO> volumeObjectTOs = new ArrayList<VolumeObjectTO>();
|
||||||
|
VMSnapshotVO vmSnapshot = Mockito.mock(VMSnapshotVO.class);
|
||||||
|
UserVmVO userVmVO = Mockito.mock(UserVmVO.class);
|
||||||
|
Mockito.when(userVmVO.getGuestOSId()).thenReturn(guestOsId);
|
||||||
|
Mockito.when(vmSnapshot.getVmId()).thenReturn(vmId);
|
||||||
|
Mockito.when(vmSnapshotHelper.pickRunningHost(Mockito.anyLong())).thenReturn(hostId);
|
||||||
|
Mockito.when(vmSnapshotHelper.getVolumeTOList(Mockito.anyLong())).thenReturn(volumeObjectTOs);
|
||||||
|
Mockito.when(userVmDao.findById(Mockito.anyLong())).thenReturn(userVmVO);
|
||||||
|
GuestOSVO guestOSVO = Mockito.mock(GuestOSVO.class);
|
||||||
|
Mockito.when(guestOSDao.findById(Mockito.anyLong())).thenReturn(guestOSVO);
|
||||||
|
VMSnapshotTO vmSnapshotTO = Mockito.mock(VMSnapshotTO.class);
|
||||||
|
Mockito.when(vmSnapshotHelper.getSnapshotWithParents(Mockito.any(VMSnapshotVO.class))).thenReturn(vmSnapshotTO);
|
||||||
|
Mockito.when(vmSnapshotDao.findById(Mockito.anyLong())).thenReturn(vmSnapshot);
|
||||||
|
Mockito.when(vmSnapshot.getId()).thenReturn(1L);
|
||||||
|
Mockito.when(vmSnapshot.getCreated()).thenReturn(new Date());
|
||||||
|
Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(null);
|
||||||
|
|
||||||
|
Exception e = null;
|
||||||
|
try {
|
||||||
|
vmSnapshotStrategy.deleteVMSnapshot(vmSnapshot);
|
||||||
|
} catch (CloudRuntimeException e1) {
|
||||||
|
e = e1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(e);
|
||||||
|
|
||||||
|
DeleteVMSnapshotAnswer answer = Mockito.mock(DeleteVMSnapshotAnswer.class);
|
||||||
|
Mockito.when(answer.getResult()).thenReturn(true);
|
||||||
|
Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(Command.class))).thenReturn(answer);
|
||||||
|
|
||||||
|
boolean result = vmSnapshotStrategy.deleteVMSnapshot(vmSnapshot);
|
||||||
|
assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan(basePackageClasses = {NetUtils.class, DefaultVMSnapshotStrategy.class}, includeFilters = {@ComponentScan.Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false)
|
||||||
|
public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration {
|
||||||
|
|
||||||
|
public static class Library implements TypeFilter {
|
||||||
|
@Override
|
||||||
|
public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException {
|
||||||
|
mdr.getClassMetadata().getClassName();
|
||||||
|
ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class);
|
||||||
|
return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public VMSnapshotHelper vmSnapshotHelper() {
|
||||||
|
return Mockito.mock(VMSnapshotHelper.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public GuestOSDao guestOSDao() {
|
||||||
|
return Mockito.mock(GuestOSDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserVmDao userVmDao() {
|
||||||
|
return Mockito.mock(UserVmDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public VMSnapshotDao vmSnapshotDao() {
|
||||||
|
return Mockito.mock(VMSnapshotDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConfigurationDao configurationDao() {
|
||||||
|
return Mockito.mock(ConfigurationDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AgentManager agentManager() {
|
||||||
|
return Mockito.mock(AgentManager.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public VolumeDao volumeDao() {
|
||||||
|
return Mockito.mock(VolumeDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DiskOfferingDao diskOfferingDao() {
|
||||||
|
return Mockito.mock(DiskOfferingDao.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,51 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cloudstack.storage.volume;
|
package org.apache.cloudstack.storage.volume;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
|
||||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
|
||||||
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
|
|
||||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
|
||||||
import org.apache.cloudstack.framework.async.AsyncRpcContext;
|
|
||||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
|
||||||
import org.apache.cloudstack.storage.command.CommandResult;
|
|
||||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
|
||||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
|
||||||
import org.apache.cloudstack.storage.datastore.DataObjectManager;
|
|
||||||
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
|
|
||||||
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
|
|
||||||
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
|
|
||||||
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
|
|
||||||
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
|
||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.storage.ListVolumeAnswer;
|
import com.cloud.agent.api.storage.ListVolumeAnswer;
|
||||||
import com.cloud.agent.api.storage.ListVolumeCommand;
|
import com.cloud.agent.api.storage.ListVolumeCommand;
|
||||||
@ -94,6 +49,46 @@ import com.cloud.utils.NumbersUtil;
|
|||||||
import com.cloud.utils.db.DB;
|
import com.cloud.utils.db.DB;
|
||||||
import com.cloud.utils.db.GlobalLock;
|
import com.cloud.utils.db.GlobalLock;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
||||||
|
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||||
|
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
|
||||||
|
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||||
|
import org.apache.cloudstack.framework.async.AsyncRpcContext;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.storage.command.CommandResult;
|
||||||
|
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||||
|
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||||
|
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
|
||||||
|
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class VolumeServiceImpl implements VolumeService {
|
public class VolumeServiceImpl implements VolumeService {
|
||||||
@ -103,10 +98,6 @@ public class VolumeServiceImpl implements VolumeService {
|
|||||||
@Inject
|
@Inject
|
||||||
PrimaryDataStoreProviderManager dataStoreMgr;
|
PrimaryDataStoreProviderManager dataStoreMgr;
|
||||||
@Inject
|
@Inject
|
||||||
ObjectInDataStoreManager objectInDataStoreMgr;
|
|
||||||
@Inject
|
|
||||||
DataObjectManager dataObjectMgr;
|
|
||||||
@Inject
|
|
||||||
DataMotionService motionSrv;
|
DataMotionService motionSrv;
|
||||||
@Inject
|
@Inject
|
||||||
VolumeDataFactory volFactory;
|
VolumeDataFactory volFactory;
|
||||||
|
|||||||
@ -16,39 +16,6 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.hypervisor.vmware.manager;
|
package com.cloud.hypervisor.vmware.manager;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.rmi.RemoteException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import com.vmware.vim25.FileInfo;
|
|
||||||
import com.vmware.vim25.FileQueryFlags;
|
|
||||||
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
|
||||||
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
|
||||||
import com.vmware.vim25.ManagedObjectReference;
|
|
||||||
import com.vmware.vim25.TaskInfo;
|
|
||||||
import com.vmware.vim25.VirtualDeviceConfigSpec;
|
|
||||||
import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
|
|
||||||
import com.vmware.vim25.VirtualDisk;
|
|
||||||
import com.vmware.vim25.VirtualLsiLogicController;
|
|
||||||
import com.vmware.vim25.VirtualMachineConfigSpec;
|
|
||||||
import com.vmware.vim25.VirtualMachineFileInfo;
|
|
||||||
import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
|
|
||||||
import com.vmware.vim25.VirtualSCSISharing;
|
|
||||||
|
|
||||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
|
||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.BackupSnapshotAnswer;
|
import com.cloud.agent.api.BackupSnapshotAnswer;
|
||||||
import com.cloud.agent.api.BackupSnapshotCommand;
|
import com.cloud.agent.api.BackupSnapshotCommand;
|
||||||
@ -73,7 +40,6 @@ import com.cloud.agent.api.to.DataStoreTO;
|
|||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
import com.cloud.agent.api.to.NfsTO;
|
import com.cloud.agent.api.to.NfsTO;
|
||||||
import com.cloud.agent.api.to.StorageFilerTO;
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
|
||||||
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
|
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
|
||||||
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
import com.cloud.hypervisor.vmware.mo.DatacenterMO;
|
||||||
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
import com.cloud.hypervisor.vmware.mo.DatastoreMO;
|
||||||
@ -97,6 +63,29 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||||||
import com.cloud.utils.script.Script;
|
import com.cloud.utils.script.Script;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
import com.cloud.vm.snapshot.VMSnapshot;
|
import com.cloud.vm.snapshot.VMSnapshot;
|
||||||
|
import com.vmware.vim25.FileInfo;
|
||||||
|
import com.vmware.vim25.FileQueryFlags;
|
||||||
|
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
|
||||||
|
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
|
||||||
|
import com.vmware.vim25.ManagedObjectReference;
|
||||||
|
import com.vmware.vim25.TaskInfo;
|
||||||
|
import com.vmware.vim25.VirtualDisk;
|
||||||
|
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||||
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
||||||
@Override
|
@Override
|
||||||
@ -1280,7 +1269,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateVMSnapshotAnswer execute(VmwareHostService hostService, CreateVMSnapshotCommand cmd) {
|
public CreateVMSnapshotAnswer execute(VmwareHostService hostService, CreateVMSnapshotCommand cmd) {
|
||||||
List<VolumeTO> volumeTOs = cmd.getVolumeTOs();
|
List<VolumeObjectTO> volumeTOs = cmd.getVolumeTOs();
|
||||||
String vmName = cmd.getVmName();
|
String vmName = cmd.getVmName();
|
||||||
String vmSnapshotName = cmd.getTarget().getSnapshotName();
|
String vmSnapshotName = cmd.getTarget().getSnapshotName();
|
||||||
String vmSnapshotDesc = cmd.getTarget().getDescription();
|
String vmSnapshotDesc = cmd.getTarget().getDescription();
|
||||||
@ -1330,19 +1319,20 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
mapNewDisk.put(baseName, vmdkName);
|
mapNewDisk.put(baseName, vmdkName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (VolumeTO volumeTO : volumeTOs) {
|
for (VolumeObjectTO volumeTO : volumeTOs) {
|
||||||
String baseName = extractSnapshotBaseFileName(volumeTO.getPath());
|
String baseName = extractSnapshotBaseFileName(volumeTO.getPath());
|
||||||
String newPath = mapNewDisk.get(baseName);
|
String newPath = mapNewDisk.get(baseName);
|
||||||
// get volume's chain size for this VM snapshot, exclude current volume vdisk
|
// get volume's chain size for this VM snapshot, exclude current volume vdisk
|
||||||
|
DataStoreTO store = volumeTO.getDataStore();
|
||||||
long size = getVMSnapshotChainSize(context,hyperHost,baseName + "*.vmdk",
|
long size = getVMSnapshotChainSize(context,hyperHost,baseName + "*.vmdk",
|
||||||
volumeTO.getPoolUuid(), newPath);
|
store.getUuid(), newPath);
|
||||||
|
|
||||||
if(volumeTO.getType()== Volume.Type.ROOT){
|
if(volumeTO.getVolumeType()== Volume.Type.ROOT){
|
||||||
// add memory snapshot size
|
// add memory snapshot size
|
||||||
size = size + getVMSnapshotChainSize(context,hyperHost,cmd.getVmName()+"*.vmsn",volumeTO.getPoolUuid(),null);
|
size = size + getVMSnapshotChainSize(context,hyperHost,cmd.getVmName()+"*.vmsn",store.getUuid(),null);
|
||||||
}
|
}
|
||||||
|
|
||||||
volumeTO.setChainSize(size);
|
volumeTO.setSize(size);
|
||||||
volumeTO.setPath(newPath);
|
volumeTO.setPath(newPath);
|
||||||
}
|
}
|
||||||
return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), volumeTOs);
|
return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), volumeTOs);
|
||||||
@ -1362,7 +1352,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeleteVMSnapshotAnswer execute(VmwareHostService hostService, DeleteVMSnapshotCommand cmd) {
|
public DeleteVMSnapshotAnswer execute(VmwareHostService hostService, DeleteVMSnapshotCommand cmd) {
|
||||||
List<VolumeTO> listVolumeTo = cmd.getVolumeTOs();
|
List<VolumeObjectTO> listVolumeTo = cmd.getVolumeTOs();
|
||||||
VirtualMachineMO vmMo = null;
|
VirtualMachineMO vmMo = null;
|
||||||
VmwareContext context = hostService.getServiceContext(cmd);
|
VmwareContext context = hostService.getServiceContext(cmd);
|
||||||
Map<String, String> mapNewDisk = new HashMap<String, String>();
|
Map<String, String> mapNewDisk = new HashMap<String, String>();
|
||||||
@ -1403,16 +1393,17 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
mapNewDisk.put(baseName, vmdkName);
|
mapNewDisk.put(baseName, vmdkName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (VolumeTO volumeTo : listVolumeTo) {
|
for (VolumeObjectTO volumeTo : listVolumeTo) {
|
||||||
String baseName = extractSnapshotBaseFileName(volumeTo.getPath());
|
String baseName = extractSnapshotBaseFileName(volumeTo.getPath());
|
||||||
String newPath = mapNewDisk.get(baseName);
|
String newPath = mapNewDisk.get(baseName);
|
||||||
|
DataStoreTO store = volumeTo.getDataStore();
|
||||||
long size = getVMSnapshotChainSize(context,hyperHost,
|
long size = getVMSnapshotChainSize(context,hyperHost,
|
||||||
baseName + "*.vmdk", volumeTo.getPoolUuid(), newPath);
|
baseName + "*.vmdk", store.getUuid(), newPath);
|
||||||
if(volumeTo.getType()== Volume.Type.ROOT){
|
if(volumeTo.getVolumeType()== Volume.Type.ROOT){
|
||||||
// add memory snapshot size
|
// add memory snapshot size
|
||||||
size = size + getVMSnapshotChainSize(context,hyperHost,cmd.getVmName()+"*.vmsn",volumeTo.getPoolUuid(),null);
|
size = size + getVMSnapshotChainSize(context,hyperHost,cmd.getVmName()+"*.vmsn",volumeTo.getUuid(),null);
|
||||||
}
|
}
|
||||||
volumeTo.setChainSize(size);
|
volumeTo.setSize(size);
|
||||||
volumeTo.setPath(newPath);
|
volumeTo.setPath(newPath);
|
||||||
}
|
}
|
||||||
return new DeleteVMSnapshotAnswer(cmd, listVolumeTo);
|
return new DeleteVMSnapshotAnswer(cmd, listVolumeTo);
|
||||||
@ -1429,7 +1420,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
String snapshotName = cmd.getTarget().getSnapshotName();
|
String snapshotName = cmd.getTarget().getSnapshotName();
|
||||||
String vmName = cmd.getVmName();
|
String vmName = cmd.getVmName();
|
||||||
Boolean snapshotMemory = cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory;
|
Boolean snapshotMemory = cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory;
|
||||||
List<VolumeTO> listVolumeTo = cmd.getVolumeTOs();
|
List<VolumeObjectTO> listVolumeTo = cmd.getVolumeTOs();
|
||||||
VirtualMachine.State vmState = VirtualMachine.State.Running;
|
VirtualMachine.State vmState = VirtualMachine.State.Running;
|
||||||
VirtualMachineMO vmMo = null;
|
VirtualMachineMO vmMo = null;
|
||||||
VmwareContext context = hostService.getServiceContext(cmd);
|
VmwareContext context = hostService.getServiceContext(cmd);
|
||||||
@ -1483,7 +1474,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String key = null;
|
String key = null;
|
||||||
for (VolumeTO volumeTo : listVolumeTo) {
|
for (VolumeObjectTO volumeTo : listVolumeTo) {
|
||||||
String parentUUID = volumeTo.getPath();
|
String parentUUID = volumeTo.getPath();
|
||||||
String[] s = parentUUID.split("-");
|
String[] s = parentUUID.split("-");
|
||||||
key = s[0];
|
key = s[0];
|
||||||
|
|||||||
@ -735,7 +735,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
|
|
||||||
private Answer execute(RevertToVMSnapshotCommand cmd) {
|
private Answer execute(RevertToVMSnapshotCommand cmd) {
|
||||||
String vmName = cmd.getVmName();
|
String vmName = cmd.getVmName();
|
||||||
List<VolumeTO> listVolumeTo = cmd.getVolumeTOs();
|
List<VolumeObjectTO> listVolumeTo = cmd.getVolumeTOs();
|
||||||
VMSnapshot.Type vmSnapshotType = cmd.getTarget().getType();
|
VMSnapshot.Type vmSnapshotType = cmd.getTarget().getType();
|
||||||
Boolean snapshotMemory = vmSnapshotType == VMSnapshot.Type.DiskAndMemory;
|
Boolean snapshotMemory = vmSnapshotType == VMSnapshot.Type.DiskAndMemory;
|
||||||
Connection conn = getConnection();
|
Connection conn = getConnection();
|
||||||
@ -787,7 +787,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// after revert, VM's volumes path have been changed, need to report to manager
|
// after revert, VM's volumes path have been changed, need to report to manager
|
||||||
for (VolumeTO volumeTo : listVolumeTo) {
|
for (VolumeObjectTO volumeTo : listVolumeTo) {
|
||||||
Long deviceId = volumeTo.getDeviceId();
|
Long deviceId = volumeTo.getDeviceId();
|
||||||
VDI vdi = vdiMap.get(deviceId.toString());
|
VDI vdi = vdiMap.get(deviceId.toString());
|
||||||
volumeTo.setPath(vdi.getUuid(conn));
|
volumeTo.setPath(vdi.getUuid(conn));
|
||||||
@ -6675,7 +6675,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getVMSnapshotChainSize(Connection conn, VolumeTO volumeTo, String vmName)
|
private long getVMSnapshotChainSize(Connection conn, VolumeObjectTO volumeTo, String vmName)
|
||||||
throws BadServerResponse, XenAPIException, XmlRpcException {
|
throws BadServerResponse, XenAPIException, XmlRpcException {
|
||||||
Set<VDI> allvolumeVDIs = VDI.getByNameLabel(conn, volumeTo.getName());
|
Set<VDI> allvolumeVDIs = VDI.getByNameLabel(conn, volumeTo.getName());
|
||||||
long size = 0;
|
long size = 0;
|
||||||
@ -6699,7 +6699,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (volumeTo.getType() == Volume.Type.ROOT) {
|
if (volumeTo.getVolumeType() == Volume.Type.ROOT) {
|
||||||
Map<VM, VM.Record> allVMs = VM.getAllRecords(conn);
|
Map<VM, VM.Record> allVMs = VM.getAllRecords(conn);
|
||||||
// add size of memory snapshot vdi
|
// add size of memory snapshot vdi
|
||||||
if (allVMs.size() > 0) {
|
if (allVMs.size() > 0) {
|
||||||
@ -6732,7 +6732,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
protected Answer execute(final CreateVMSnapshotCommand cmd) {
|
protected Answer execute(final CreateVMSnapshotCommand cmd) {
|
||||||
String vmName = cmd.getVmName();
|
String vmName = cmd.getVmName();
|
||||||
String vmSnapshotName = cmd.getTarget().getSnapshotName();
|
String vmSnapshotName = cmd.getTarget().getSnapshotName();
|
||||||
List<VolumeTO> listVolumeTo = cmd.getVolumeTOs();
|
List<VolumeObjectTO> listVolumeTo = cmd.getVolumeTOs();
|
||||||
VirtualMachine.State vmState = cmd.getVmState();
|
VirtualMachine.State vmState = cmd.getVmState();
|
||||||
String guestOSType = cmd.getGuestOSType();
|
String guestOSType = cmd.getGuestOSType();
|
||||||
|
|
||||||
@ -6812,9 +6812,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
|
|
||||||
}
|
}
|
||||||
// calculate used capacity for this VM snapshot
|
// calculate used capacity for this VM snapshot
|
||||||
for (VolumeTO volumeTo : cmd.getVolumeTOs()){
|
for (VolumeObjectTO volumeTo : cmd.getVolumeTOs()){
|
||||||
long size = getVMSnapshotChainSize(conn,volumeTo,cmd.getVmName());
|
long size = getVMSnapshotChainSize(conn,volumeTo,cmd.getVmName());
|
||||||
volumeTo.setChainSize(size);
|
volumeTo.setSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
@ -6863,7 +6863,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private VM createWorkingVM(Connection conn, String vmName,
|
private VM createWorkingVM(Connection conn, String vmName,
|
||||||
String guestOSType, List<VolumeTO> listVolumeTo)
|
String guestOSType, List<VolumeObjectTO> listVolumeTo)
|
||||||
throws BadServerResponse, VmBadPowerState, SrFull,
|
throws BadServerResponse, VmBadPowerState, SrFull,
|
||||||
OperationNotAllowed, XenAPIException, XmlRpcException {
|
OperationNotAllowed, XenAPIException, XmlRpcException {
|
||||||
String guestOsTypeName = getGuestOsType(guestOSType, false);
|
String guestOsTypeName = getGuestOsType(guestOSType, false);
|
||||||
@ -6877,8 +6877,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
VM template = getVM(conn, guestOsTypeName);
|
VM template = getVM(conn, guestOsTypeName);
|
||||||
VM vm = template.createClone(conn, vmName);
|
VM vm = template.createClone(conn, vmName);
|
||||||
vm.setIsATemplate(conn, false);
|
vm.setIsATemplate(conn, false);
|
||||||
Map<VDI, VolumeTO> vdiMap = new HashMap<VDI, VolumeTO>();
|
Map<VDI, VolumeObjectTO> vdiMap = new HashMap<VDI, VolumeObjectTO>();
|
||||||
for (VolumeTO volume : listVolumeTo) {
|
for (VolumeObjectTO volume : listVolumeTo) {
|
||||||
String vdiUuid = volume.getPath();
|
String vdiUuid = volume.getPath();
|
||||||
try {
|
try {
|
||||||
VDI vdi = VDI.getByUuid(conn, vdiUuid);
|
VDI vdi = VDI.getByUuid(conn, vdiUuid);
|
||||||
@ -6889,11 +6889,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (VDI vdi : vdiMap.keySet()) {
|
for (VDI vdi : vdiMap.keySet()) {
|
||||||
VolumeTO volumeTO = vdiMap.get(vdi);
|
VolumeObjectTO volumeTO = vdiMap.get(vdi);
|
||||||
VBD.Record vbdr = new VBD.Record();
|
VBD.Record vbdr = new VBD.Record();
|
||||||
vbdr.VM = vm;
|
vbdr.VM = vm;
|
||||||
vbdr.VDI = vdi;
|
vbdr.VDI = vdi;
|
||||||
if (volumeTO.getType() == Volume.Type.ROOT) {
|
if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
|
||||||
vbdr.bootable = true;
|
vbdr.bootable = true;
|
||||||
vbdr.unpluggable = false;
|
vbdr.unpluggable = false;
|
||||||
} else {
|
} else {
|
||||||
@ -6940,9 +6940,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
|||||||
|
|
||||||
}
|
}
|
||||||
// re-calculate used capacify for this VM snapshot
|
// re-calculate used capacify for this VM snapshot
|
||||||
for (VolumeTO volumeTo : cmd.getVolumeTOs()){
|
for (VolumeObjectTO volumeTo : cmd.getVolumeTOs()){
|
||||||
long size = getVMSnapshotChainSize(conn,volumeTo,cmd.getVmName());
|
long size = getVMSnapshotChainSize(conn,volumeTo,cmd.getVmName());
|
||||||
volumeTo.setChainSize(size);
|
volumeTo.setSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
|
return new DeleteVMSnapshotAnswer(cmd, cmd.getVolumeTOs());
|
||||||
|
|||||||
@ -337,8 +337,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
return snapshot;
|
return snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Snapshot backupSnapshot(Long snapshotId) {
|
public Snapshot backupSnapshot(Long snapshotId) {
|
||||||
SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Image);
|
SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Image);
|
||||||
@ -349,93 +347,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
return snapshotSrv.backupSnapshot(snapshot);
|
return snapshotSrv.backupSnapshot(snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
@Override
|
|
||||||
public void downloadSnapshotsFromSwift(SnapshotVO ss) {
|
|
||||||
|
|
||||||
long volumeId = ss.getVolumeId();
|
|
||||||
VolumeVO volume = _volsDao.findById(volumeId);
|
|
||||||
Long dcId = volume.getDataCenterId();
|
|
||||||
Long accountId = volume.getAccountId();
|
|
||||||
DataStore secStore = this.dataStoreMgr.getImageStore(dcId);
|
|
||||||
|
|
||||||
Long swiftId = ss.getSwiftId();
|
|
||||||
SwiftTO swift = _swiftMgr.getSwiftTO(swiftId);
|
|
||||||
SnapshotVO tss = ss;
|
|
||||||
List<String> BackupUuids = new ArrayList<String>(30);
|
|
||||||
while (true) {
|
|
||||||
BackupUuids.add(0, tss.getBackupSnapshotId());
|
|
||||||
if (tss.getPrevSnapshotId() == 0)
|
|
||||||
break;
|
|
||||||
Long id = tss.getPrevSnapshotId();
|
|
||||||
tss = _snapshotDao.findById(id);
|
|
||||||
assert tss != null : " can not find snapshot " + id;
|
|
||||||
}
|
|
||||||
String parent = null;
|
|
||||||
try {
|
|
||||||
for (String backupUuid : BackupUuids) {
|
|
||||||
DownloadSnapshotFromSwiftCommand cmd = new DownloadSnapshotFromSwiftCommand(swift, secondaryStoragePoolUrl, dcId, accountId, volumeId, parent, backupUuid, _backupsnapshotwait);
|
|
||||||
Answer answer = _agentMgr.sendToSSVM(dcId, cmd);
|
|
||||||
if ((answer == null) || !answer.getResult()) {
|
|
||||||
throw new CloudRuntimeException("downloadSnapshotsFromSwift failed ");
|
|
||||||
}
|
|
||||||
parent = backupUuid;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CloudRuntimeException("downloadSnapshotsFromSwift failed due to " + e.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> determineBackupUuids(final SnapshotVO snapshot) {
|
|
||||||
|
|
||||||
final List<String> backupUuids = new ArrayList<String>();
|
|
||||||
backupUuids.add(0, snapshot.getBackupSnapshotId());
|
|
||||||
|
|
||||||
SnapshotVO tempSnapshot = snapshot;
|
|
||||||
while (tempSnapshot.getPrevSnapshotId() != 0) {
|
|
||||||
tempSnapshot = _snapshotDao.findById(tempSnapshot
|
|
||||||
.getPrevSnapshotId());
|
|
||||||
backupUuids.add(0, tempSnapshot.getBackupSnapshotId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Collections.unmodifiableList(backupUuids);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void downloadSnapshotsFromS3(final SnapshotVO snapshot) {
|
|
||||||
|
|
||||||
final VolumeVO volume = _volsDao.findById(snapshot.getVolumeId());
|
|
||||||
final Long zoneId = volume.getDataCenterId();
|
|
||||||
final DataStore secStore = this.dataStoreMgr.getImageStore(zoneId);
|
|
||||||
|
|
||||||
final S3TO s3 = _s3Mgr.getS3TO(snapshot.getS3Id());
|
|
||||||
final List<String> backupUuids = determineBackupUuids(snapshot);
|
|
||||||
|
|
||||||
try {
|
|
||||||
String parent = null;
|
|
||||||
for (final String backupUuid : backupUuids) {
|
|
||||||
final DownloadSnapshotFromS3Command cmd = new DownloadSnapshotFromS3Command(
|
|
||||||
s3, parent, secStore.getUri(), zoneId,
|
|
||||||
volume.getAccountId(), volume.getId(), backupUuid,
|
|
||||||
_backupsnapshotwait);
|
|
||||||
final Answer answer = _agentMgr.sendToSSVM(zoneId, cmd);
|
|
||||||
if ((answer == null) || !answer.getResult()) {
|
|
||||||
throw new CloudRuntimeException(String.format(
|
|
||||||
"S3 snapshot download failed due to %1$s.",
|
|
||||||
answer != null ? answer.getDetails()
|
|
||||||
: "unspecified error"));
|
|
||||||
}
|
|
||||||
parent = backupUuid;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new CloudRuntimeException(
|
|
||||||
"Snapshot download from S3 failed due to " + e.toString(),
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SnapshotVO getParentSnapshot(VolumeInfo volume) {
|
public SnapshotVO getParentSnapshot(VolumeInfo volume) {
|
||||||
long preId = _snapshotDao.getLastSnapshot(volume.getId(), DataStoreRole.Primary);
|
long preId = _snapshotDao.getLastSnapshot(volume.getId(), DataStoreRole.Primary);
|
||||||
@ -534,7 +445,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSecondaryStorageURL(SnapshotVO snapshot) {
|
public String getSecondaryStorageURL(SnapshotVO snapshot) {
|
||||||
SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Image);
|
SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Image);
|
||||||
@ -660,7 +570,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
return new Pair<List<? extends Snapshot>, Integer>(result.first(), result.second());
|
return new Pair<List<? extends Snapshot>, Integer>(result.first(), result.second());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean deleteSnapshotDirsForAccount(long accountId) {
|
public boolean deleteSnapshotDirsForAccount(long accountId) {
|
||||||
|
|
||||||
@ -925,8 +834,6 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private boolean hostSupportSnapsthotForVolume(HostVO host, VolumeInfo volume) {
|
private boolean hostSupportSnapsthotForVolume(HostVO host, VolumeInfo volume) {
|
||||||
if (host.getHypervisorType() != HypervisorType.KVM) {
|
if (host.getHypervisorType() != HypervisorType.KVM) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -47,56 +47,43 @@ import com.cloud.agent.api.RevertToVMSnapshotAnswer;
|
|||||||
import com.cloud.agent.api.RevertToVMSnapshotCommand;
|
import com.cloud.agent.api.RevertToVMSnapshotCommand;
|
||||||
import com.cloud.agent.api.VMSnapshotTO;
|
import com.cloud.agent.api.VMSnapshotTO;
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
import com.cloud.agent.api.to.VolumeTO;
|
||||||
|
|
||||||
import com.cloud.event.ActionEvent;
|
import com.cloud.event.ActionEvent;
|
||||||
import com.cloud.event.EventTypes;
|
import com.cloud.event.EventTypes;
|
||||||
import com.cloud.event.UsageEventUtils;
|
|
||||||
import com.cloud.exception.AgentUnavailableException;
|
|
||||||
import com.cloud.exception.ConcurrentOperationException;
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
import com.cloud.exception.InsufficientCapacityException;
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
import com.cloud.exception.InvalidParameterValueException;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
import com.cloud.exception.OperationTimedoutException;
|
|
||||||
import com.cloud.exception.ResourceAllocationException;
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.host.Host;
|
|
||||||
import com.cloud.host.HostVO;
|
|
||||||
import com.cloud.host.dao.HostDao;
|
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.hypervisor.HypervisorGuruManager;
|
|
||||||
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
|
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
|
||||||
import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
||||||
import com.cloud.service.dao.ServiceOfferingDao;
|
|
||||||
import com.cloud.storage.DiskOfferingVO;
|
|
||||||
import com.cloud.storage.GuestOSVO;
|
|
||||||
import com.cloud.storage.Snapshot;
|
import com.cloud.storage.Snapshot;
|
||||||
import com.cloud.storage.SnapshotVO;
|
import com.cloud.storage.SnapshotVO;
|
||||||
import com.cloud.storage.StoragePool;
|
|
||||||
import com.cloud.storage.VolumeVO;
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.dao.DiskOfferingDao;
|
|
||||||
import com.cloud.storage.dao.GuestOSDao;
|
import com.cloud.storage.dao.GuestOSDao;
|
||||||
import com.cloud.storage.dao.SnapshotDao;
|
import com.cloud.storage.dao.SnapshotDao;
|
||||||
import com.cloud.storage.dao.VolumeDao;
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
import com.cloud.user.Account;
|
import com.cloud.user.Account;
|
||||||
import com.cloud.user.AccountManager;
|
import com.cloud.user.AccountManager;
|
||||||
import com.cloud.user.dao.AccountDao;
|
import com.cloud.user.dao.AccountDao;
|
||||||
import com.cloud.user.dao.UserDao;
|
|
||||||
import com.cloud.uservm.UserVm;
|
import com.cloud.uservm.UserVm;
|
||||||
import com.cloud.utils.DateUtil;
|
import com.cloud.utils.DateUtil;
|
||||||
import com.cloud.utils.NumbersUtil;
|
import com.cloud.utils.NumbersUtil;
|
||||||
import com.cloud.utils.Ternary;
|
import com.cloud.utils.Ternary;
|
||||||
import com.cloud.utils.component.ManagerBase;
|
import com.cloud.utils.component.ManagerBase;
|
||||||
import com.cloud.utils.db.DB;
|
|
||||||
import com.cloud.utils.db.Filter;
|
import com.cloud.utils.db.Filter;
|
||||||
import com.cloud.utils.db.SearchBuilder;
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
import com.cloud.utils.db.SearchCriteria;
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
|
||||||
import com.cloud.utils.db.Transaction;
|
import com.cloud.utils.db.Transaction;
|
||||||
import com.cloud.utils.db.TransactionCallback;
|
import com.cloud.utils.db.TransactionCallback;
|
||||||
import com.cloud.utils.db.TransactionCallbackNoReturn;
|
import com.cloud.utils.db.TransactionCallbackNoReturn;
|
||||||
import com.cloud.utils.db.TransactionCallbackWithException;
|
import com.cloud.utils.db.TransactionCallbackWithException;
|
||||||
import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
|
import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
|
||||||
import com.cloud.utils.db.TransactionStatus;
|
import com.cloud.utils.db.TransactionStatus;
|
||||||
|
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.utils.fsm.NoTransitionException;
|
|
||||||
import com.cloud.utils.fsm.StateMachine2;
|
|
||||||
import com.cloud.vm.UserVmVO;
|
import com.cloud.vm.UserVmVO;
|
||||||
import com.cloud.vm.VMInstanceVO;
|
import com.cloud.vm.VMInstanceVO;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
@ -104,8 +91,22 @@ import com.cloud.vm.VirtualMachine.State;
|
|||||||
import com.cloud.vm.VirtualMachineManager;
|
import com.cloud.vm.VirtualMachineManager;
|
||||||
import com.cloud.vm.VirtualMachineProfile;
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
import com.cloud.vm.dao.UserVmDao;
|
import com.cloud.vm.dao.UserVmDao;
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
|
||||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||||
|
import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd;
|
||||||
|
import org.apache.cloudstack.context.CallContext;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotStrategy;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.naming.ConfigurationException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Local(value = { VMSnapshotManager.class, VMSnapshotService.class })
|
@Local(value = { VMSnapshotManager.class, VMSnapshotService.class })
|
||||||
@ -115,25 +116,27 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
@Inject VMSnapshotDao _vmSnapshotDao;
|
@Inject VMSnapshotDao _vmSnapshotDao;
|
||||||
@Inject VolumeDao _volumeDao;
|
@Inject VolumeDao _volumeDao;
|
||||||
@Inject AccountDao _accountDao;
|
@Inject AccountDao _accountDao;
|
||||||
@Inject VMInstanceDao _vmInstanceDao;
|
|
||||||
@Inject UserVmDao _userVMDao;
|
@Inject UserVmDao _userVMDao;
|
||||||
@Inject HostDao _hostDao;
|
|
||||||
@Inject UserDao _userDao;
|
|
||||||
@Inject AgentManager _agentMgr;
|
|
||||||
@Inject HypervisorGuruManager _hvGuruMgr;
|
|
||||||
@Inject AccountManager _accountMgr;
|
@Inject AccountManager _accountMgr;
|
||||||
@Inject GuestOSDao _guestOSDao;
|
@Inject GuestOSDao _guestOSDao;
|
||||||
@Inject PrimaryDataStoreDao _storagePoolDao;
|
|
||||||
@Inject SnapshotDao _snapshotDao;
|
@Inject SnapshotDao _snapshotDao;
|
||||||
@Inject VirtualMachineManager _itMgr;
|
@Inject VirtualMachineManager _itMgr;
|
||||||
@Inject DataStoreManager dataStoreMgr;
|
|
||||||
@Inject ConfigurationDao _configDao;
|
@Inject ConfigurationDao _configDao;
|
||||||
@Inject HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
|
@Inject HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
|
||||||
@Inject DiskOfferingDao _diskOfferingDao;
|
@Inject List<VMSnapshotStrategy> vmSnapshotStrategies;
|
||||||
@Inject ServiceOfferingDao _serviceOfferingDao;
|
|
||||||
|
public List<VMSnapshotStrategy> getVmSnapshotStrategies() {
|
||||||
|
return vmSnapshotStrategies;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public void setVmSnapshotStrategies(List<VMSnapshotStrategy> vmSnapshotStrategies) {
|
||||||
|
this.vmSnapshotStrategies = vmSnapshotStrategies;
|
||||||
|
}
|
||||||
|
|
||||||
int _vmSnapshotMax;
|
int _vmSnapshotMax;
|
||||||
int _wait;
|
int _wait;
|
||||||
StateMachine2<VMSnapshot.State, VMSnapshot.Event, VMSnapshot> _vmSnapshottateMachine ;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||||
@ -148,7 +151,6 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
String value = _configDao.getValue("vmsnapshot.create.wait");
|
String value = _configDao.getValue("vmsnapshot.create.wait");
|
||||||
_wait = NumbersUtil.parseInt(value, 1800);
|
_wait = NumbersUtil.parseInt(value, 1800);
|
||||||
|
|
||||||
_vmSnapshottateMachine = VMSnapshot.State.getStateMachine();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,6 +342,22 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VMSnapshotStrategy findVMSnapshotStrategy(VMSnapshot vmSnapshot) {
|
||||||
|
VMSnapshotStrategy snapshotStrategy = null;
|
||||||
|
for(VMSnapshotStrategy strategy : vmSnapshotStrategies) {
|
||||||
|
if (strategy.canHandle(vmSnapshot)) {
|
||||||
|
snapshotStrategy = strategy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshotStrategy == null) {
|
||||||
|
throw new CloudRuntimeException("can't find vm snapshot strategy for vmsnapshot: " + vmSnapshot.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return snapshotStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ActionEvent(eventType = EventTypes.EVENT_VM_SNAPSHOT_CREATE, eventDescription = "creating VM snapshot", async = true)
|
@ActionEvent(eventType = EventTypes.EVENT_VM_SNAPSHOT_CREATE, eventDescription = "creating VM snapshot", async = true)
|
||||||
public VMSnapshot creatVMSnapshot(Long vmId, Long vmSnapshotId) {
|
public VMSnapshot creatVMSnapshot(Long vmId, Long vmSnapshotId) {
|
||||||
@ -351,240 +369,20 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
if(vmSnapshot == null){
|
if(vmSnapshot == null){
|
||||||
throw new CloudRuntimeException("VM snapshot id: " + vmSnapshotId + " can not be found");
|
throw new CloudRuntimeException("VM snapshot id: " + vmSnapshotId + " can not be found");
|
||||||
}
|
}
|
||||||
Long hostId = pickRunningHost(vmId);
|
|
||||||
try {
|
try {
|
||||||
vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.CreateRequested);
|
VMSnapshotStrategy strategy = findVMSnapshotStrategy(vmSnapshot);
|
||||||
} catch (NoTransitionException e) {
|
VMSnapshot snapshot = strategy.takeVMSnapshot(vmSnapshot);
|
||||||
throw new CloudRuntimeException(e.getMessage());
|
return snapshot;
|
||||||
}
|
|
||||||
return createVmSnapshotInternal(userVm, vmSnapshot, hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected VMSnapshot createVmSnapshotInternal(UserVmVO userVm, VMSnapshotVO vmSnapshot, Long hostId) {
|
|
||||||
CreateVMSnapshotAnswer answer = null;
|
|
||||||
try {
|
|
||||||
GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId());
|
|
||||||
|
|
||||||
// prepare snapshotVolumeTos
|
|
||||||
List<VolumeTO> volumeTOs = getVolumeTOList(userVm.getId());
|
|
||||||
|
|
||||||
// prepare target snapshotTO and its parent snapshot (current snapshot)
|
|
||||||
VMSnapshotTO current = null;
|
|
||||||
VMSnapshotVO currentSnapshot = _vmSnapshotDao.findCurrentSnapshotByVmId(userVm.getId());
|
|
||||||
if (currentSnapshot != null)
|
|
||||||
current = getSnapshotWithParents(currentSnapshot);
|
|
||||||
VMSnapshotTO target = new VMSnapshotTO(vmSnapshot.getId(), vmSnapshot.getName(), vmSnapshot.getType(), null, vmSnapshot.getDescription(), false,
|
|
||||||
current);
|
|
||||||
if (current == null)
|
|
||||||
vmSnapshot.setParent(null);
|
|
||||||
else
|
|
||||||
vmSnapshot.setParent(current.getId());
|
|
||||||
|
|
||||||
CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(userVm.getInstanceName(),target ,volumeTOs, guestOS.getDisplayName(),userVm.getState());
|
|
||||||
ccmd.setWait(_wait);
|
|
||||||
|
|
||||||
answer = (CreateVMSnapshotAnswer) sendToPool(hostId, ccmd);
|
|
||||||
if (answer != null && answer.getResult()) {
|
|
||||||
processAnswer(vmSnapshot, userVm, answer, hostId);
|
|
||||||
s_logger.debug("Create vm snapshot " + vmSnapshot.getName() + " succeeded for vm: " + userVm.getInstanceName());
|
|
||||||
}else{
|
|
||||||
|
|
||||||
String errMsg = "Creating VM snapshot: " + vmSnapshot.getName() + " failed";
|
|
||||||
if(answer != null && answer.getDetails() != null)
|
|
||||||
errMsg = errMsg + " due to " + answer.getDetails();
|
|
||||||
s_logger.error(errMsg);
|
|
||||||
vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
|
|
||||||
throw new CloudRuntimeException(errMsg);
|
|
||||||
}
|
|
||||||
return vmSnapshot;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if(e instanceof AgentUnavailableException){
|
s_logger.debug("Failed to create vm snapshot: " + vmSnapshotId ,e);
|
||||||
try {
|
return null;
|
||||||
vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
|
|
||||||
} catch (NoTransitionException e1) {
|
|
||||||
s_logger.error("Cannot set vm snapshot state due to: " + e1.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String msg = e.getMessage();
|
|
||||||
s_logger.error("Create vm snapshot " + vmSnapshot.getName() + " failed for vm: " + userVm.getInstanceName() + " due to " + msg);
|
|
||||||
throw new CloudRuntimeException(msg);
|
|
||||||
} finally{
|
|
||||||
if(vmSnapshot.getState() == VMSnapshot.State.Allocated){
|
|
||||||
s_logger.warn("Create vm snapshot " + vmSnapshot.getName() + " failed for vm: " + userVm.getInstanceName());
|
|
||||||
_vmSnapshotDao.remove(vmSnapshot.getId());
|
|
||||||
}
|
|
||||||
if(vmSnapshot.getState() == VMSnapshot.State.Ready && answer != null){
|
|
||||||
for (VolumeTO volumeTo : answer.getVolumeTOs()){
|
|
||||||
publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_CREATE,vmSnapshot,userVm,volumeTo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publishUsageEvent(String type, VMSnapshot vmSnapshot, UserVm userVm, VolumeTO volumeTo){
|
|
||||||
VolumeVO volume = _volumeDao.findById(volumeTo.getId());
|
|
||||||
Long diskOfferingId = volume.getDiskOfferingId();
|
|
||||||
Long offeringId = null;
|
|
||||||
if (diskOfferingId != null) {
|
|
||||||
DiskOfferingVO offering = _diskOfferingDao.findById(diskOfferingId);
|
|
||||||
if (offering != null
|
|
||||||
&& (offering.getType() == DiskOfferingVO.Type.Disk)) {
|
|
||||||
offeringId = offering.getId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UsageEventUtils.publishUsageEvent(
|
|
||||||
type,
|
|
||||||
vmSnapshot.getAccountId(),
|
|
||||||
userVm.getDataCenterId(),
|
|
||||||
userVm.getId(),
|
|
||||||
vmSnapshot.getName(),
|
|
||||||
offeringId,
|
|
||||||
volume.getId(), // save volume's id into templateId field
|
|
||||||
volumeTo.getChainSize(),
|
|
||||||
VMSnapshot.class.getName(), vmSnapshot.getUuid());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<VolumeTO> getVolumeTOList(Long vmId) {
|
|
||||||
List<VolumeTO> volumeTOs = new ArrayList<VolumeTO>();
|
|
||||||
List<VolumeVO> volumeVos = _volumeDao.findByInstance(vmId);
|
|
||||||
|
|
||||||
for (VolumeVO volume : volumeVos) {
|
|
||||||
StoragePool pool = (StoragePool)dataStoreMgr.getPrimaryDataStore(volume.getPoolId());
|
|
||||||
VolumeTO volumeTO = new VolumeTO(volume, pool);
|
|
||||||
volumeTOs.add(volumeTO);
|
|
||||||
}
|
|
||||||
return volumeTOs;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get snapshot and its parents recursively
|
|
||||||
private VMSnapshotTO getSnapshotWithParents(VMSnapshotVO snapshot) {
|
|
||||||
Map<Long, VMSnapshotVO> snapshotMap = new HashMap<Long, VMSnapshotVO>();
|
|
||||||
List<VMSnapshotVO> allSnapshots = _vmSnapshotDao.findByVm(snapshot.getVmId());
|
|
||||||
for (VMSnapshotVO vmSnapshotVO : allSnapshots) {
|
|
||||||
snapshotMap.put(vmSnapshotVO.getId(), vmSnapshotVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
VMSnapshotTO currentTO = convert2VMSnapshotTO(snapshot);
|
|
||||||
VMSnapshotTO result = currentTO;
|
|
||||||
VMSnapshotVO current = snapshot;
|
|
||||||
while (current.getParent() != null) {
|
|
||||||
VMSnapshotVO parent = snapshotMap.get(current.getParent());
|
|
||||||
currentTO.setParent(convert2VMSnapshotTO(parent));
|
|
||||||
current = snapshotMap.get(current.getParent());
|
|
||||||
currentTO = currentTO.getParent();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private VMSnapshotTO convert2VMSnapshotTO(VMSnapshotVO vo) {
|
|
||||||
return new VMSnapshotTO(vo.getId(), vo.getName(), vo.getType(), vo.getCreated().getTime(), vo.getDescription(),
|
|
||||||
vo.getCurrent(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean vmSnapshotStateTransitTo(VMSnapshotVO vsnp, VMSnapshot.Event event) throws NoTransitionException {
|
|
||||||
return _vmSnapshottateMachine.transitTo(vsnp, event, null, _vmSnapshotDao);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DB
|
|
||||||
protected void processAnswer(final VMSnapshotVO vmSnapshot, UserVmVO userVm, final Answer as, Long hostId) {
|
|
||||||
try {
|
|
||||||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<NoTransitionException>() {
|
|
||||||
@Override
|
|
||||||
public void doInTransactionWithoutResult(TransactionStatus status) throws NoTransitionException {
|
|
||||||
if (as instanceof CreateVMSnapshotAnswer) {
|
|
||||||
CreateVMSnapshotAnswer answer = (CreateVMSnapshotAnswer) as;
|
|
||||||
finalizeCreate(vmSnapshot, answer.getVolumeTOs());
|
|
||||||
vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationSucceeded);
|
|
||||||
} else if (as instanceof RevertToVMSnapshotAnswer) {
|
|
||||||
RevertToVMSnapshotAnswer answer = (RevertToVMSnapshotAnswer) as;
|
|
||||||
finalizeRevert(vmSnapshot, answer.getVolumeTOs());
|
|
||||||
vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationSucceeded);
|
|
||||||
} else if (as instanceof DeleteVMSnapshotAnswer) {
|
|
||||||
DeleteVMSnapshotAnswer answer = (DeleteVMSnapshotAnswer) as;
|
|
||||||
finalizeDelete(vmSnapshot, answer.getVolumeTOs());
|
|
||||||
_vmSnapshotDao.remove(vmSnapshot.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
String errMsg = "Error while process answer: " + as.getClass() + " due to " + e.getMessage();
|
|
||||||
s_logger.error(errMsg, e);
|
|
||||||
throw new CloudRuntimeException(errMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void finalizeDelete(VMSnapshotVO vmSnapshot, List<VolumeTO> VolumeTOs) {
|
|
||||||
// update volumes path
|
|
||||||
updateVolumePath(VolumeTOs);
|
|
||||||
|
|
||||||
// update children's parent snapshots
|
|
||||||
List<VMSnapshotVO> children= _vmSnapshotDao.listByParent(vmSnapshot.getId());
|
|
||||||
for (VMSnapshotVO child : children) {
|
|
||||||
child.setParent(vmSnapshot.getParent());
|
|
||||||
_vmSnapshotDao.persist(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update current snapshot
|
|
||||||
VMSnapshotVO current = _vmSnapshotDao.findCurrentSnapshotByVmId(vmSnapshot.getVmId());
|
|
||||||
if(current != null && current.getId() == vmSnapshot.getId() && vmSnapshot.getParent() != null){
|
|
||||||
VMSnapshotVO parent = _vmSnapshotDao.findById(vmSnapshot.getParent());
|
|
||||||
parent.setCurrent(true);
|
|
||||||
_vmSnapshotDao.persist(parent);
|
|
||||||
}
|
|
||||||
vmSnapshot.setCurrent(false);
|
|
||||||
_vmSnapshotDao.persist(vmSnapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void finalizeCreate(VMSnapshotVO vmSnapshot, List<VolumeTO> VolumeTOs) {
|
|
||||||
// update volumes path
|
|
||||||
updateVolumePath(VolumeTOs);
|
|
||||||
|
|
||||||
vmSnapshot.setCurrent(true);
|
|
||||||
|
|
||||||
// change current snapshot
|
|
||||||
if (vmSnapshot.getParent() != null) {
|
|
||||||
VMSnapshotVO previousCurrent = _vmSnapshotDao.findById(vmSnapshot.getParent());
|
|
||||||
previousCurrent.setCurrent(false);
|
|
||||||
_vmSnapshotDao.persist(previousCurrent);
|
|
||||||
}
|
|
||||||
_vmSnapshotDao.persist(vmSnapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void finalizeRevert(VMSnapshotVO vmSnapshot, List<VolumeTO> volumeToList) {
|
|
||||||
// update volumes path
|
|
||||||
updateVolumePath(volumeToList);
|
|
||||||
|
|
||||||
// update current snapshot, current snapshot is the one reverted to
|
|
||||||
VMSnapshotVO previousCurrent = _vmSnapshotDao.findCurrentSnapshotByVmId(vmSnapshot.getVmId());
|
|
||||||
if(previousCurrent != null){
|
|
||||||
previousCurrent.setCurrent(false);
|
|
||||||
_vmSnapshotDao.persist(previousCurrent);
|
|
||||||
}
|
|
||||||
vmSnapshot.setCurrent(true);
|
|
||||||
_vmSnapshotDao.persist(vmSnapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateVolumePath(List<VolumeTO> volumeTOs) {
|
|
||||||
for (VolumeTO volume : volumeTOs) {
|
|
||||||
if (volume.getPath() != null) {
|
|
||||||
VolumeVO volumeVO = _volumeDao.findById(volume.getId());
|
|
||||||
volumeVO.setPath(volume.getPath());
|
|
||||||
volumeVO.setVmSnapshotChainSize(volume.getChainSize());
|
|
||||||
_volumeDao.persist(volumeVO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public VMSnapshotManagerImpl() {
|
public VMSnapshotManagerImpl() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Answer sendToPool(Long hostId, Command cmd) throws AgentUnavailableException, OperationTimedoutException {
|
|
||||||
long targetHostId = _hvGuruMgr.getGuruProcessedCommandTargetHost(hostId, cmd);
|
|
||||||
Answer answer = _agentMgr.send(targetHostId, cmd);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasActiveVMSnapshotTasks(Long vmId){
|
public boolean hasActiveVMSnapshotTasks(Long vmId){
|
||||||
List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(vmId,
|
List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(vmId,
|
||||||
@ -620,50 +418,14 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
|
|
||||||
if(vmSnapshot.getState() == VMSnapshot.State.Allocated){
|
if(vmSnapshot.getState() == VMSnapshot.State.Allocated){
|
||||||
return _vmSnapshotDao.remove(vmSnapshot.getId());
|
return _vmSnapshotDao.remove(vmSnapshot.getId());
|
||||||
}else{
|
} else{
|
||||||
return deleteSnapshotInternal(vmSnapshot);
|
try {
|
||||||
}
|
VMSnapshotStrategy strategy = findVMSnapshotStrategy(vmSnapshot);
|
||||||
}
|
return strategy.deleteVMSnapshot(vmSnapshot);
|
||||||
|
} catch (Exception e) {
|
||||||
@DB
|
s_logger.debug("Failed to delete vm snapshot: " + vmSnapshotId, e);
|
||||||
protected boolean deleteSnapshotInternal(VMSnapshotVO vmSnapshot) {
|
|
||||||
UserVmVO userVm = _userVMDao.findById(vmSnapshot.getVmId());
|
|
||||||
DeleteVMSnapshotAnswer answer = null;
|
|
||||||
try {
|
|
||||||
vmSnapshotStateTransitTo(vmSnapshot,VMSnapshot.Event.ExpungeRequested);
|
|
||||||
Long hostId = pickRunningHost(vmSnapshot.getVmId());
|
|
||||||
|
|
||||||
// prepare snapshotVolumeTos
|
|
||||||
List<VolumeTO> volumeTOs = getVolumeTOList(vmSnapshot.getVmId());
|
|
||||||
|
|
||||||
// prepare DeleteVMSnapshotCommand
|
|
||||||
String vmInstanceName = userVm.getInstanceName();
|
|
||||||
VMSnapshotTO parent = getSnapshotWithParents(vmSnapshot).getParent();
|
|
||||||
VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(vmSnapshot.getId(), vmSnapshot.getName(), vmSnapshot.getType(),
|
|
||||||
vmSnapshot.getCreated().getTime(), vmSnapshot.getDescription(), vmSnapshot.getCurrent(), parent);
|
|
||||||
GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId());
|
|
||||||
DeleteVMSnapshotCommand deleteSnapshotCommand = new DeleteVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs,guestOS.getDisplayName());
|
|
||||||
|
|
||||||
answer = (DeleteVMSnapshotAnswer) sendToPool(hostId, deleteSnapshotCommand);
|
|
||||||
|
|
||||||
if (answer != null && answer.getResult()) {
|
|
||||||
processAnswer(vmSnapshot, userVm, answer, hostId);
|
|
||||||
s_logger.debug("Delete VM snapshot " + vmSnapshot.getName() + " succeeded for vm: " + userVm.getInstanceName());
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
s_logger.error("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + answer.getDetails());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
String msg = "Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + e.getMessage();
|
|
||||||
s_logger.error(msg , e);
|
|
||||||
throw new CloudRuntimeException(e.getMessage());
|
|
||||||
} finally{
|
|
||||||
if(answer != null && answer.getResult()){
|
|
||||||
for (VolumeTO volumeTo : answer.getVolumeTOs()){
|
|
||||||
publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_DELETE,vmSnapshot,userVm,volumeTo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,108 +491,29 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
throw new CloudRuntimeException(e.getMessage());
|
throw new CloudRuntimeException(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hostId = pickRunningHost(userVm.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hostId == null)
|
|
||||||
throw new CloudRuntimeException("Can not find any host to revert snapshot " + vmSnapshotVo.getName());
|
|
||||||
|
|
||||||
// check if there are other active VM snapshot tasks
|
// check if there are other active VM snapshot tasks
|
||||||
if (hasActiveVMSnapshotTasks(userVm.getId())) {
|
if (hasActiveVMSnapshotTasks(userVm.getId())) {
|
||||||
throw new InvalidParameterValueException("There is other active vm snapshot tasks on the instance, please try again later");
|
throw new InvalidParameterValueException("There is other active vm snapshot tasks on the instance, please try again later");
|
||||||
}
|
}
|
||||||
|
|
||||||
userVm = _userVMDao.findById(userVm.getId());
|
|
||||||
try {
|
|
||||||
vmSnapshotStateTransitTo(vmSnapshotVo, VMSnapshot.Event.RevertRequested);
|
|
||||||
} catch (NoTransitionException e) {
|
|
||||||
throw new CloudRuntimeException(e.getMessage());
|
|
||||||
}
|
|
||||||
return revertInternal(userVm, vmSnapshotVo, hostId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private UserVm revertInternal(UserVmVO userVm, VMSnapshotVO vmSnapshotVo, Long hostId) {
|
|
||||||
try {
|
try {
|
||||||
VMSnapshotVO snapshot = _vmSnapshotDao.findById(vmSnapshotVo.getId());
|
VMSnapshotStrategy strategy = findVMSnapshotStrategy(vmSnapshotVo);
|
||||||
// prepare RevertToSnapshotCommand
|
strategy.revertVMSnapshot(vmSnapshotVo);
|
||||||
List<VolumeTO> volumeTOs = getVolumeTOList(userVm.getId());
|
return userVm;
|
||||||
String vmInstanceName = userVm.getInstanceName();
|
|
||||||
VMSnapshotTO parent = getSnapshotWithParents(snapshot).getParent();
|
|
||||||
VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(), snapshot.getType(),
|
|
||||||
snapshot.getCreated().getTime(), snapshot.getDescription(), snapshot.getCurrent(), parent);
|
|
||||||
|
|
||||||
GuestOSVO guestOS = _guestOSDao.findById(userVm.getGuestOSId());
|
|
||||||
RevertToVMSnapshotCommand revertToSnapshotCommand = new RevertToVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs, guestOS.getDisplayName());
|
|
||||||
|
|
||||||
RevertToVMSnapshotAnswer answer = (RevertToVMSnapshotAnswer) sendToPool(hostId, revertToSnapshotCommand);
|
|
||||||
if (answer != null && answer.getResult()) {
|
|
||||||
processAnswer(vmSnapshotVo, userVm, answer, hostId);
|
|
||||||
s_logger.debug("RevertTo " + vmSnapshotVo.getName() + " succeeded for vm: " + userVm.getInstanceName());
|
|
||||||
} else {
|
|
||||||
String errMsg = "Revert VM: " + userVm.getInstanceName() + " to snapshot: "+ vmSnapshotVo.getName() + " failed";
|
|
||||||
if(answer != null && answer.getDetails() != null)
|
|
||||||
errMsg = errMsg + " due to " + answer.getDetails();
|
|
||||||
s_logger.error(errMsg);
|
|
||||||
// agent report revert operation fails
|
|
||||||
vmSnapshotStateTransitTo(vmSnapshotVo, VMSnapshot.Event.OperationFailed);
|
|
||||||
throw new CloudRuntimeException(errMsg);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if(e instanceof AgentUnavailableException){
|
s_logger.debug("Failed to revert vmsnapshot: " + vmSnapshotId, e);
|
||||||
try {
|
return null;
|
||||||
vmSnapshotStateTransitTo(vmSnapshotVo, VMSnapshot.Event.OperationFailed);
|
|
||||||
} catch (NoTransitionException e1) {
|
|
||||||
s_logger.error("Cannot set vm snapshot state due to: " + e1.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// for other exceptions, do not change VM snapshot state, leave it for snapshotSync
|
|
||||||
String errMsg = "revert vm: " + userVm.getInstanceName() + " to snapshot " + vmSnapshotVo.getName() + " failed due to " + e.getMessage();
|
|
||||||
s_logger.error(errMsg);
|
|
||||||
throw new CloudRuntimeException(e.getMessage());
|
|
||||||
}
|
}
|
||||||
return userVm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VMSnapshot getVMSnapshotById(Long id) {
|
public VMSnapshot getVMSnapshotById(Long id) {
|
||||||
VMSnapshotVO vmSnapshot = _vmSnapshotDao.findById(id);
|
VMSnapshotVO vmSnapshot = _vmSnapshotDao.findById(id);
|
||||||
return vmSnapshot;
|
return vmSnapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Long pickRunningHost(Long vmId) {
|
|
||||||
UserVmVO vm = _userVMDao.findById(vmId);
|
|
||||||
// use VM's host if VM is running
|
|
||||||
if(vm.getState() == State.Running)
|
|
||||||
return vm.getHostId();
|
|
||||||
|
|
||||||
// check if lastHostId is available
|
|
||||||
if(vm.getLastHostId() != null){
|
|
||||||
HostVO lastHost = _hostDao.findById(vm.getLastHostId());
|
|
||||||
if(lastHost.getStatus() == com.cloud.host.Status.Up && !lastHost.isInMaintenanceStates())
|
|
||||||
return lastHost.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<VolumeVO> listVolumes = _volumeDao.findByInstance(vmId);
|
|
||||||
if (listVolumes == null || listVolumes.size() == 0) {
|
|
||||||
throw new InvalidParameterValueException("vmInstance has no volumes");
|
|
||||||
}
|
|
||||||
VolumeVO volume = listVolumes.get(0);
|
|
||||||
Long poolId = volume.getPoolId();
|
|
||||||
if (poolId == null) {
|
|
||||||
throw new InvalidParameterValueException("pool id is not found");
|
|
||||||
}
|
|
||||||
StoragePoolVO storagePool = _storagePoolDao.findById(poolId);
|
|
||||||
if (storagePool == null) {
|
|
||||||
throw new InvalidParameterValueException("storage pool is not found");
|
|
||||||
}
|
|
||||||
List<HostVO> listHost = _hostDao.listAllUpAndEnabledNonHAHosts(Host.Type.Routing, storagePool.getClusterId(), storagePool.getPodId(),
|
|
||||||
storagePool.getDataCenterId(), null);
|
|
||||||
if (listHost == null || listHost.size() == 0) {
|
|
||||||
throw new InvalidParameterValueException("no host in up state is found");
|
|
||||||
}
|
|
||||||
return listHost.get(0).getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VirtualMachine getVMBySnapshotId(Long id) {
|
public VirtualMachine getVMBySnapshotId(Long id) {
|
||||||
@ -854,7 +537,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
VMSnapshotVO target = _vmSnapshotDao.findById(snapshot.getId());
|
VMSnapshotVO target = _vmSnapshotDao.findById(snapshot.getId());
|
||||||
if(type != null && target.getType() != type)
|
if(type != null && target.getType() != type)
|
||||||
continue;
|
continue;
|
||||||
if (!deleteSnapshotInternal(target)) {
|
VMSnapshotStrategy strategy = findVMSnapshotStrategy(target);
|
||||||
|
if (!strategy.deleteVMSnapshot(target)) {
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -872,12 +556,13 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
|
|||||||
|
|
||||||
List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Reverting, VMSnapshot.State.Creating);
|
List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Reverting, VMSnapshot.State.Creating);
|
||||||
for (VMSnapshotVO vmSnapshotVO : vmSnapshotsInExpungingStates) {
|
for (VMSnapshotVO vmSnapshotVO : vmSnapshotsInExpungingStates) {
|
||||||
|
VMSnapshotStrategy strategy = findVMSnapshotStrategy(vmSnapshotVO);
|
||||||
if(vmSnapshotVO.getState() == VMSnapshot.State.Expunging){
|
if(vmSnapshotVO.getState() == VMSnapshot.State.Expunging){
|
||||||
return deleteSnapshotInternal(vmSnapshotVO);
|
return strategy.deleteVMSnapshot(vmSnapshotVO);
|
||||||
}else if(vmSnapshotVO.getState() == VMSnapshot.State.Creating){
|
}else if(vmSnapshotVO.getState() == VMSnapshot.State.Creating){
|
||||||
return createVmSnapshotInternal(userVm, vmSnapshotVO, hostId) != null;
|
return strategy.takeVMSnapshot(vmSnapshotVO) != null;
|
||||||
}else if(vmSnapshotVO.getState() == VMSnapshot.State.Reverting){
|
}else if(vmSnapshotVO.getState() == VMSnapshot.State.Reverting){
|
||||||
return revertInternal(userVm, vmSnapshotVO, hostId) != null;
|
return strategy.revertVMSnapshot(vmSnapshotVO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
|
|||||||
@ -192,13 +192,6 @@ public class VMSnapshotManagerTest {
|
|||||||
when(vmMock.getState()).thenReturn(State.Running);
|
when(vmMock.getState()).thenReturn(State.Running);
|
||||||
_vmSnapshotMgr.allocVMSnapshot(TEST_VM_ID,"","",true);
|
_vmSnapshotMgr.allocVMSnapshot(TEST_VM_ID,"","",true);
|
||||||
|
|
||||||
when(_vmSnapshotDao.findCurrentSnapshotByVmId(anyLong())).thenReturn(null);
|
|
||||||
doReturn(new ArrayList<VolumeTO>()).when(_vmSnapshotMgr).getVolumeTOList(anyLong());
|
|
||||||
doReturn(new CreateVMSnapshotAnswer(null,true,"")).when(_vmSnapshotMgr).sendToPool(anyLong(), any(CreateVMSnapshotCommand.class));
|
|
||||||
doNothing().when(_vmSnapshotMgr).processAnswer(any(VMSnapshotVO.class),
|
|
||||||
any(UserVmVO.class), any(Answer.class), anyLong());
|
|
||||||
doReturn(true).when(_vmSnapshotMgr).vmSnapshotStateTransitTo(any(VMSnapshotVO.class),any(VMSnapshot.Event.class));
|
|
||||||
_vmSnapshotMgr.createVmSnapshotInternal(vmMock, mock(VMSnapshotVO.class), 5L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,15 @@ ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_state_update_count` INT DEFA
|
|||||||
ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_host` bigint unsigned;
|
ALTER TABLE `cloud`.`vm_instance` ADD COLUMN `power_host` bigint unsigned;
|
||||||
ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__power_host` FOREIGN KEY (`power_host`) REFERENCES `cloud`.`host`(`id`);
|
ALTER TABLE `cloud`.`vm_instance` ADD CONSTRAINT `fk_vm_instance__power_host` FOREIGN KEY (`power_host`) REFERENCES `cloud`.`host`(`id`);
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `cloud`.`vm_snapshot_details`;
|
||||||
|
CREATE TABLE `cloud`.`vm_snapshot_details` (
|
||||||
|
`id` bigint unsigned UNIQUE NOT NULL,
|
||||||
|
`vm_snapshot_id` bigint unsigned NOT NULL,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
CREATE TABLE `cloud`.`vm_work_job` (
|
CREATE TABLE `cloud`.`vm_work_job` (
|
||||||
`id` bigint unsigned UNIQUE NOT NULL,
|
`id` bigint unsigned UNIQUE NOT NULL,
|
||||||
`step` char(32) NOT NULL COMMENT 'state',
|
`step` char(32) NOT NULL COMMENT 'state',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user