Finally, get async api call works for storage subsystem

This commit is contained in:
Edison Su 2012-12-17 18:12:46 -08:00
parent 716a5673d0
commit aefb657c41
32 changed files with 314 additions and 94 deletions

View File

@ -16,17 +16,19 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.cloudstack.storage.scope; package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
public class ClusterScope implements Scope { public class ClusterScope implements Scope {
private ScopeType type = ScopeType.CLUSTER; private ScopeType type = ScopeType.CLUSTER;
private long clusterId; private long clusterId;
private long podId;
private long zoneId;
public ClusterScope(long clusterId) { public ClusterScope(long clusterId, long podId, long zoneId) {
this.clusterId = clusterId; this.clusterId = clusterId;
this.podId = podId;
this.zoneId = zoneId;
} }
@Override @Override
@ -39,4 +41,12 @@ public class ClusterScope implements Scope {
return this.clusterId; return this.clusterId;
} }
public long getPodId() {
return this.podId;
}
public long getZoneId() {
return this.zoneId;
}
} }

View File

@ -16,10 +16,8 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.cloudstack.storage.scope; package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
public class HostScope implements Scope { public class HostScope implements Scope {
private ScopeType type = ScopeType.HOST; private ScopeType type = ScopeType.HOST;

View File

@ -19,13 +19,12 @@
package org.apache.cloudstack.engine.subsystem.api.storage; package org.apache.cloudstack.engine.subsystem.api.storage;
import java.util.List;
import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType;
import org.apache.cloudstack.storage.EndPoint;
import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Volume;
public interface PrimaryDataStoreInfo { public interface PrimaryDataStoreInfo {
public boolean isHypervisorSupported(HypervisorType hypervisor); public boolean isHypervisorSupported(HypervisorType hypervisor);
@ -33,10 +32,10 @@ public interface PrimaryDataStoreInfo {
public boolean isVolumeDiskTypeSupported(VolumeDiskType diskType); public boolean isVolumeDiskTypeSupported(VolumeDiskType diskType);
public long getCapacity(); public long getCapacity();
public long getAvailableCapacity(); public long getAvailableCapacity();
public List<EndPoint> getEndPoints();
public long getId(); public long getId();
public String getUuid(); public String getUuid();
public State getManagedState(); public Volume.State getManagedState();
public String getName(); public String getName();
public String getType(); public String getType();
public PrimaryDataStoreLifeCycle getLifeCycle(); public PrimaryDataStoreLifeCycle getLifeCycle();

View File

@ -23,7 +23,7 @@ import java.util.Map;
public interface PrimaryDataStoreLifeCycle { public interface PrimaryDataStoreLifeCycle {
public boolean initialize(Map<String, String> dsInfos); public boolean initialize(Map<String, String> dsInfos);
public boolean attach(Scope scope); public boolean attachCluster(ClusterScope scope);
public boolean dettach(); public boolean dettach();

View File

@ -16,10 +16,8 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.cloudstack.storage.scope; package org.apache.cloudstack.engine.subsystem.api.storage;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
public class ZoneScope implements Scope { public class ZoneScope implements Scope {
private ScopeType type = ScopeType.ZONE; private ScopeType type = ScopeType.ZONE;

View File

@ -18,7 +18,6 @@
*/ */
package org.apache.cloudstack.storage.image.motion; package org.apache.cloudstack.storage.image.motion;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCallbackHandler; import org.apache.cloudstack.framework.async.AsyncCallbackHandler;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@ -26,12 +25,11 @@ import org.apache.cloudstack.storage.EndPoint;
import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorage; import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorage;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer; import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.cloud.agent.api.Answer;
@Component @Component
public class DefaultImageMotionStrategy implements ImageMotionStrategy { public class DefaultImageMotionStrategy implements ImageMotionStrategy {
@ -43,7 +41,7 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy {
@Override @Override
public EndPoint getEndPoint(TemplateOnPrimaryDataStoreInfo templateStore) { public EndPoint getEndPoint(TemplateOnPrimaryDataStoreInfo templateStore) {
PrimaryDataStoreInfo pdi = templateStore.getPrimaryDataStore(); PrimaryDataStore pdi = templateStore.getPrimaryDataStore();
return pdi.getEndPoints().get(0); return pdi.getEndPoints().get(0);
} }
@ -59,7 +57,7 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy {
public void copyTemplateAsync(TemplateOnPrimaryDataStoreInfo templateStore, EndPoint ep, AsyncCompletionCallback<CommandResult> callback) { public void copyTemplateAsync(TemplateOnPrimaryDataStoreInfo templateStore, EndPoint ep, AsyncCompletionCallback<CommandResult> callback) {
ImageOnPrimayDataStoreTO imageTo = new ImageOnPrimayDataStoreTO(templateStore); ImageOnPrimayDataStoreTO imageTo = new ImageOnPrimayDataStoreTO(templateStore);
CopyTemplateToPrimaryStorage copyCommand = new CopyTemplateToPrimaryStorage(imageTo); CopyTemplateToPrimaryStorage copyCommand = new CopyTemplateToPrimaryStorage(imageTo);
AsyncCallbackDispatcher<Answer> caller = new AsyncCallbackDispatcher<Answer>(this).setParentCallback(callback) AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this).setParentCallback(callback)
.setOperationName("defaultImageStrategy.copytemplate.callback") .setOperationName("defaultImageStrategy.copytemplate.callback")
.setContextParam("templateStore", templateStore); .setContextParam("templateStore", templateStore);
ep.sendMessageAsync(copyCommand, caller); ep.sendMessageAsync(copyCommand, caller);
@ -71,11 +69,13 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy {
CopyTemplateToPrimaryStorageAnswer answer = callback.getResult(); CopyTemplateToPrimaryStorageAnswer answer = callback.getResult();
CommandResult result = new CommandResult(); CommandResult result = new CommandResult();
if (!answer.getResult()) {
result.setSucess(answer.getResult()); result.setSucess(answer.getResult());
result.setResult(answer.getDetails()); result.setResult(answer.getDetails());
if (answer.getResult()) { } else {
TemplateOnPrimaryDataStoreInfo templateStore = callback.getContextParam("templateStore"); TemplateOnPrimaryDataStoreInfo templateStore = callback.getContextParam("templateStore");
templateStore.setPath(answer.getPath()); templateStore.setPath(answer.getPath());
result.setSucess(true);
} }
parentCall.complete(result); parentCall.complete(result);

View File

@ -99,7 +99,7 @@ public class ImageMotionServiceImpl implements ImageMotionService {
} }
@AsyncCallbackHandler(operationName="imagemotionService.copytemplate.callback") @AsyncCallbackHandler(operationName="imagemotionService.copytemplate.callback")
public void copyTemplateAsyncCallback(AsyncCallbackDispatcher callback) { public void copyTemplateAsyncCallback( AsyncCallbackDispatcher callback) {
AsyncCallbackDispatcher parentCaller = callback.getParentCallback(); AsyncCallbackDispatcher parentCaller = callback.getParentCallback();
parentCaller.complete(callback.getResult()); parentCaller.complete(callback.getResult());
} }

View File

@ -1,5 +1,6 @@
package org.apache.cloudstack.storage.test; package org.apache.cloudstack.storage.test;
import org.apache.cloudstack.storage.HostEndpointRpcServer;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -20,6 +21,11 @@ public class ChildTestConfiguration extends TestConfiguration {
public AgentManager agentMgr() { public AgentManager agentMgr() {
return new DirectAgentManagerSimpleImpl(); return new DirectAgentManagerSimpleImpl();
} }
@Bean
public HostEndpointRpcServer rpcServer() {
return new MockHypervsiorHostEndPointRpcServer();
}
/* @Override /* @Override
@Bean @Bean
public PrimaryDataStoreDao primaryDataStoreDao() { public PrimaryDataStoreDao primaryDataStoreDao() {

View File

@ -0,0 +1,69 @@
/*
* 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.test;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.HostEndpointRpcServer;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorage;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer;
import org.apache.cloudstack.storage.command.CreateVolumeAnswer;
import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
public class MockHypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
private ScheduledExecutorService executor;
public MockHypervsiorHostEndPointRpcServer() {
executor = Executors.newScheduledThreadPool(10);
}
protected class MockRpcCallBack implements Runnable {
private final Command cmd;
private final AsyncCompletionCallback<Answer> callback;
public MockRpcCallBack(Command cmd, final AsyncCompletionCallback<Answer> callback) {
this.cmd = cmd;
this.callback = callback;
}
@Override
public void run() {
try {
Answer answer = new Answer(cmd, false, "unknown command");
if (cmd instanceof CopyTemplateToPrimaryStorage) {
answer = new CopyTemplateToPrimaryStorageAnswer(cmd, UUID.randomUUID().toString());
} else if (cmd instanceof CreateVolumeFromBaseImageCommand) {
answer = new CreateVolumeAnswer(cmd, UUID.randomUUID().toString());
}
callback.complete(answer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) {
executor.schedule(new MockRpcCallBack(command, callback), 10, TimeUnit.SECONDS);
}
}

View File

@ -1,7 +1,5 @@
package org.apache.cloudstack.storage.test; package org.apache.cloudstack.storage.test;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -14,8 +12,4 @@ public class TestConfiguration {
public HostDao hostDao() { public HostDao hostDao() {
return new HostDaoImpl(); return new HostDaoImpl();
} }
@Bean
public PrimaryDataStoreDao primaryDataStoreDao() {
return new PrimaryDataStoreDaoImpl();
}
} }

View File

@ -34,9 +34,11 @@ import javax.naming.ConfigurationException;
import org.apache.cloudstack.engine.cloud.entity.api.TemplateEntity; import org.apache.cloudstack.engine.cloud.entity.api.TemplateEntity;
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.QCOW2; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.QCOW2;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VHD; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VHD;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VMDK; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VMDK;
@ -131,6 +133,7 @@ public class volumeServiceTest {
AgentManager agentMgr; AgentManager agentMgr;
Long dcId; Long dcId;
Long clusterId; Long clusterId;
Long podId;
@Before @Before
public void setUp() { public void setUp() {
//create data center //create data center
@ -142,6 +145,7 @@ public class volumeServiceTest {
HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "192.168.56.1", "192.168.56.0/24", 8, "test"); HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), dc.getId(), "192.168.56.1", "192.168.56.0/24", 8, "test");
pod = podDao.persist(pod); pod = podDao.persist(pod);
podId = pod.getId();
//create xen cluster //create xen cluster
ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster");
cluster.setHypervisorType(HypervisorType.XenServer.toString()); cluster.setHypervisorType(HypervisorType.XenServer.toString());
@ -168,9 +172,9 @@ public class volumeServiceTest {
results.add(host); results.add(host);
Mockito.when(hostDao.listAll()).thenReturn(results); Mockito.when(hostDao.listAll()).thenReturn(results);
Mockito.when(hostDao.findHypervisorHostInCluster(Mockito.anyLong())).thenReturn(results); Mockito.when(hostDao.findHypervisorHostInCluster(Mockito.anyLong())).thenReturn(results);
CreateVolumeAnswer createVolumeFromImageAnswer = new CreateVolumeAnswer(UUID.randomUUID().toString()); //CreateVolumeAnswer createVolumeFromImageAnswer = new CreateVolumeAnswer(UUID.randomUUID().toString());
try { /*try {
Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(CreateVolumeFromBaseImageCommand.class))).thenReturn(createVolumeFromImageAnswer); Mockito.when(agentMgr.send(Mockito.anyLong(), Mockito.any(CreateVolumeFromBaseImageCommand.class))).thenReturn(createVolumeFromImageAnswer);
} catch (AgentUnavailableException e) { } catch (AgentUnavailableException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
@ -178,7 +182,7 @@ public class volumeServiceTest {
} catch (OperationTimedoutException e) { } catch (OperationTimedoutException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }*/
//Mockito.when(primaryStoreDao.findById(Mockito.anyLong())).thenReturn(primaryStore); //Mockito.when(primaryStoreDao.findById(Mockito.anyLong())).thenReturn(primaryStore);
@ -238,6 +242,9 @@ public class volumeServiceTest {
params.put("clusterId", clusterId.toString()); params.put("clusterId", clusterId.toString());
params.put("name", "my primary data store"); params.put("name", "my primary data store");
PrimaryDataStoreInfo primaryDataStoreInfo = provider.registerDataStore(params); PrimaryDataStoreInfo primaryDataStoreInfo = provider.registerDataStore(params);
PrimaryDataStoreLifeCycle lc = primaryDataStoreInfo.getLifeCycle();
ClusterScope scope = new ClusterScope(clusterId, podId, dcId);
lc.attachCluster(scope);
return primaryDataStoreInfo; return primaryDataStoreInfo;
} catch (ConfigurationException e) { } catch (ConfigurationException e) {
return null; return null;

View File

@ -39,4 +39,30 @@
<bean class="org.apache.cloudstack.storage.test.ChildTestConfiguration" /> <bean class="org.apache.cloudstack.storage.test.ChildTestConfiguration" />
<bean id="onwireRegistry" class="org.apache.cloudstack.framework.serializer.OnwireClassRegistry"
init-method="scan" >
<property name="packages">
<list>
<value>org.apache.cloudstack.framework</value>
</list>
</property>
</bean>
<bean id="messageSerializer" class="org.apache.cloudstack.framework.serializer.JsonMessageSerializer">
<property name="onwireClassRegistry" ref="onwireRegistry" />
</bean>
<bean id="transportProvider" class="org.apache.cloudstack.framework.server.ServerTransportProvider" init-method="initialize">
<property name="workerPoolSize" value="5" />
<property name="nodeId" value="Node1" />
<property name="messageSerializer" ref="messageSerializer" />
</bean>
<bean id="rpcProvider" class="org.apache.cloudstack.framework.rpc.RpcProviderImpl" init-method="initialize">
<constructor-arg ref="transportProvider" />
<property name="messageSerializer" ref="messageSerializer" />
</bean>
<bean id="eventBus" class = "org.apache.cloudstack.framework.eventbus.EventBusBase" />
</beans> </beans>

View File

@ -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.storage;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
public interface HostEndpointRpcServer {
void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback);
}

View File

@ -38,7 +38,7 @@ public class HypervisorHostEndPoint implements EndPoint {
@Inject @Inject
AgentManager agentMgr; AgentManager agentMgr;
@Inject @Inject
HypervsiorHostEndPointRpcServer rpcServer; HostEndpointRpcServer rpcServer;
public HypervisorHostEndPoint(long hostId, String hostAddress) { public HypervisorHostEndPoint(long hostId, String hostAddress) {
this.hostId = hostId; this.hostId = hostId;

View File

@ -31,13 +31,16 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
@Component @Component
public class HypervsiorHostEndPointRpcServer { public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
@Inject
private RpcProvider _rpcProvider; private RpcProvider _rpcProvider;
public HypervsiorHostEndPointRpcServer() { @Inject
public HypervsiorHostEndPointRpcServer(RpcProvider rpcProvider) {
_rpcProvider = rpcProvider;
_rpcProvider.registerRpcServiceEndpoint(RpcServiceDispatcher.getDispatcher(this)); _rpcProvider.registerRpcServiceEndpoint(RpcServiceDispatcher.getDispatcher(this));
} }
@Override
public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) { public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) {
_rpcProvider.newCall(host).addCallbackListener(new RpcCallbackListener<Answer>() { _rpcProvider.newCall(host).addCallbackListener(new RpcCallbackListener<Answer>() {
@Override @Override

View File

@ -1,11 +1,13 @@
package org.apache.cloudstack.storage.command; package org.apache.cloudstack.storage.command;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
public class CopyTemplateToPrimaryStorageAnswer extends Answer { public class CopyTemplateToPrimaryStorageAnswer extends Answer {
private final String path; private final String path;
public CopyTemplateToPrimaryStorageAnswer(String path) { public CopyTemplateToPrimaryStorageAnswer(Command cmd, String path) {
super(cmd);
this.path = path; this.path = path;
} }

View File

@ -19,6 +19,7 @@
package org.apache.cloudstack.storage.command; package org.apache.cloudstack.storage.command;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
public class CreateVolumeAnswer extends Answer { public class CreateVolumeAnswer extends Answer {
private String volumeUuid; private String volumeUuid;
@ -27,7 +28,8 @@ public class CreateVolumeAnswer extends Answer {
super(); super();
} }
public CreateVolumeAnswer(String volumeUuid) { public CreateVolumeAnswer(Command cmd, String volumeUuid) {
super(cmd);
this.volumeUuid = volumeUuid; this.volumeUuid = volumeUuid;
} }

View File

@ -18,7 +18,7 @@
*/ */
package org.apache.cloudstack.storage.volume; package org.apache.cloudstack.storage.volume;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.image.TemplateInfo; import org.apache.cloudstack.storage.image.TemplateInfo;
public interface TemplateOnPrimaryDataStoreInfo { public interface TemplateOnPrimaryDataStoreInfo {
@ -26,7 +26,7 @@ public interface TemplateOnPrimaryDataStoreInfo {
public void setPath(String path); public void setPath(String path);
public PrimaryDataStoreInfo getPrimaryDataStore(); public PrimaryDataStore getPrimaryDataStore();
public TemplateInfo getTemplate(); public TemplateInfo getTemplate();
} }

View File

@ -30,10 +30,14 @@ import org.apache.cloudstack.engine.datacenter.entity.api.StorageEntity;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType;
import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCallbackHandler;
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreEntityImpl; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreEntityImpl;
import org.apache.cloudstack.storage.image.TemplateEntityImpl; import org.apache.cloudstack.storage.image.TemplateEntityImpl;
import org.apache.cloudstack.storage.image.TemplateInfo; import org.apache.cloudstack.storage.image.TemplateInfo;
import com.cloud.utils.exception.CloudRuntimeException;
public class VolumeEntityImpl implements VolumeEntity { public class VolumeEntityImpl implements VolumeEntity {
private VolumeInfo volumeInfo; private VolumeInfo volumeInfo;
private final VolumeService vs; private final VolumeService vs;
@ -192,8 +196,25 @@ public class VolumeEntityImpl implements VolumeEntity {
@Override @Override
public boolean createVolumeFromTemplate(long dataStoreId, VolumeDiskType diskType, TemplateEntity template) { public boolean createVolumeFromTemplate(long dataStoreId, VolumeDiskType diskType, TemplateEntity template) {
TemplateInfo ti = ((TemplateEntityImpl)template).getTemplateInfo(); TemplateInfo ti = ((TemplateEntityImpl)template).getTemplateInfo();
volumeInfo = vs.createVolumeFromTemplate(volumeInfo, dataStoreId, diskType, ti);
AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this)
.setOperationName("volumeEntity.createVolumeFromTemplateAsyncCallback");
vs.createVolumeFromTemplateAsync(volumeInfo, dataStoreId, diskType, ti, caller);
try {
synchronized (volumeInfo) {
volumeInfo.wait();
}
} catch (InterruptedException e) {
throw new CloudRuntimeException("wait volume info failed", e);
}
return true; return true;
} }
@AsyncCallbackHandler(operationName="volumeEntity.createVolumeFromTemplateAsyncCallback")
public void createVolumeFromTemplateAsyncCallback(AsyncCallbackDispatcher callback) {
synchronized (volumeInfo) {
volumeInfo.notify();
}
}
} }

View File

@ -165,6 +165,7 @@ public class TemplatePrimaryDataStoreVO implements StateObject<TemplateOnPrimary
this.poolId = poolId; this.poolId = poolId;
this.templateId = templateId; this.templateId = templateId;
this.downloadState = Status.NOT_DOWNLOADED; this.downloadState = Status.NOT_DOWNLOADED;
this.state = TemplateOnPrimaryDataStoreStateMachine.State.Allocated;
this.markedForGC = false; this.markedForGC = false;
} }

View File

@ -5,16 +5,18 @@ import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCallbackHandler;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.EndPoint; import org.apache.cloudstack.storage.EndPoint;
import org.apache.cloudstack.storage.HypervisorHostEndPoint; import org.apache.cloudstack.storage.HypervisorHostEndPoint;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreVO;
import org.apache.cloudstack.storage.datastore.driver.DefaultPrimaryDataStoreDriverImpl;
import org.apache.cloudstack.storage.datastore.driver.PrimaryDataStoreDriver; import org.apache.cloudstack.storage.datastore.driver.PrimaryDataStoreDriver;
import org.apache.cloudstack.storage.image.TemplateInfo; import org.apache.cloudstack.storage.image.TemplateInfo;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo;
@ -28,6 +30,7 @@ import org.apache.log4j.Logger;
import com.cloud.host.HostVO; import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Volume;
import com.cloud.utils.component.ComponentInject; import com.cloud.utils.component.ComponentInject;
import edu.emory.mathcs.backport.java.util.Collections; import edu.emory.mathcs.backport.java.util.Collections;
@ -185,10 +188,27 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore {
public VolumeInfo createVoluemFromBaseImage(VolumeInfo volume, TemplateOnPrimaryDataStoreInfo template) { public VolumeInfo createVoluemFromBaseImage(VolumeInfo volume, TemplateOnPrimaryDataStoreInfo template) {
VolumeObject vo = (VolumeObject) volume; VolumeObject vo = (VolumeObject) volume;
vo.setVolumeDiskType(template.getTemplate().getDiskType()); vo.setVolumeDiskType(template.getTemplate().getDiskType());
this.driver.createVolumeFromBaseImage(vo, template); //this.driver.createVolumeFromBaseImage(vo, template);
return volume; return volume;
} }
@Override
public void createVoluemFromBaseImageAsync(VolumeInfo volume, TemplateOnPrimaryDataStoreInfo templateStore, AsyncCompletionCallback<CommandResult> callback) {
VolumeObject vo = (VolumeObject) volume;
vo.setVolumeDiskType(templateStore.getTemplate().getDiskType());
AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this)
.setParentCallback(callback)
.setOperationName("primarydatastore.createvolumefrombaseImage");
this.driver.createVolumeFromBaseImageAsync(vo, templateStore, caller);
}
@AsyncCallbackHandler(operationName="primarydatastore.createvolumefrombaseImage")
public void createVoluemFromBaseImageAsyncCallback(AsyncCallbackDispatcher callback) {
AsyncCallbackDispatcher parent = callback.getParentCallback();
CommandResult result = callback.getResult();
parent.complete(result);
}
@Override @Override
public boolean installTemplate(TemplateOnPrimaryDataStoreInfo template) { public boolean installTemplate(TemplateOnPrimaryDataStoreInfo template) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
@ -202,7 +222,7 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore {
} }
@Override @Override
public State getManagedState() { public Volume.State getManagedState() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
@ -228,4 +248,6 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore {
public PrimaryDataStoreProvider getProvider() { public PrimaryDataStoreProvider getProvider() {
return this.provider; return this.provider;
} }
} }

View File

@ -4,7 +4,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCallbackHandler;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.EndPoint; import org.apache.cloudstack.storage.EndPoint;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CreateVolumeAnswer; import org.apache.cloudstack.storage.command.CreateVolumeAnswer;
import org.apache.cloudstack.storage.command.CreateVolumeCommand; import org.apache.cloudstack.storage.command.CreateVolumeCommand;
import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand; import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand;
@ -100,17 +104,38 @@ public class DefaultPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
} }
@Override @Override
public boolean createVolumeFromBaseImage(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template) { public void createVolumeFromBaseImageAsync(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template, AsyncCompletionCallback<CommandResult> callback) {
VolumeTO vol = new VolumeTO(volume); VolumeTO vol = new VolumeTO(volume);
ImageOnPrimayDataStoreTO image = new ImageOnPrimayDataStoreTO(template); ImageOnPrimayDataStoreTO image = new ImageOnPrimayDataStoreTO(template);
CreateVolumeFromBaseImageCommand cmd = new CreateVolumeFromBaseImageCommand(vol, image); CreateVolumeFromBaseImageCommand cmd = new CreateVolumeFromBaseImageCommand(vol, image);
List<EndPoint> endPoints = template.getPrimaryDataStore().getEndPoints(); List<EndPoint> endPoints = template.getPrimaryDataStore().getEndPoints();
EndPoint ep = endPoints.get(0);
Answer answer = sendOutCommand(cmd, endPoints); AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this)
.setParentCallback(callback)
.setOperationName("primarydatastoredriver.createvolumefrombaseImage")
.setContextParam("volume", volume);
ep.sendMessageAsync(cmd, caller);
CreateVolumeAnswer volAnswer = (CreateVolumeAnswer) answer;
volume.setPath(volAnswer.getVolumeUuid()); }
return true;
@AsyncCallbackHandler(operationName="primarydatastoredriver.createvolumefrombaseImage")
public void createVolumeFromBaseImageAsyncCallback(AsyncCallbackDispatcher callback) {
CreateVolumeAnswer answer = (CreateVolumeAnswer)callback.getResult();
CommandResult result = new CommandResult();
if (answer == null || answer.getDetails() != null) {
result.setSucess(false);
if (answer != null) {
result.setResult(answer.getDetails());
}
} else {
result.setSucess(true);
VolumeObject volume = callback.getContextParam("volume");
volume.setPath(answer.getVolumeUuid());
}
AsyncCallbackDispatcher parentCall = callback.getParentCallback();
parentCall.complete(result);
} }
@Override @Override
@ -142,4 +167,6 @@ public class DefaultPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
} }

View File

@ -2,7 +2,9 @@ package org.apache.cloudstack.storage.datastore.driver;
import java.util.Map; import java.util.Map;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.EndPoint; import org.apache.cloudstack.storage.EndPoint;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore; import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo;
import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.cloudstack.storage.volume.VolumeObject;
@ -10,7 +12,7 @@ import org.apache.cloudstack.storage.volume.VolumeObject;
public interface PrimaryDataStoreDriver { public interface PrimaryDataStoreDriver {
boolean createVolume(VolumeObject vol); boolean createVolume(VolumeObject vol);
boolean createVolumeFromBaseImage(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template); void createVolumeFromBaseImageAsync(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template, AsyncCompletionCallback<CommandResult> callback);
boolean deleteVolume(VolumeObject vo); boolean deleteVolume(VolumeObject vo);

View File

@ -18,23 +18,14 @@
*/ */
package org.apache.cloudstack.storage.datastore.lifecycle; package org.apache.cloudstack.storage.datastore.lifecycle;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map; import java.util.Map;
import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
import org.apache.cloudstack.storage.datastore.DataStoreStatus; import org.apache.cloudstack.storage.datastore.DataStoreStatus;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreProviderDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreVO;
import org.springframework.stereotype.Component;
public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle { public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
protected PrimaryDataStoreInfo dataStore; protected PrimaryDataStoreInfo dataStore;
@ -58,8 +49,12 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
} }
@Override @Override
public boolean attach(Scope scope) { public boolean attachCluster(ClusterScope scope) {
//if (scope.getScopeType() == ScopeType.CLUSTER) PrimaryDataStoreVO dataStore = dataStoreDao.findById(this.dataStore.getId());
dataStore.setDataCenterId(scope.getZoneId());
dataStore.setPodId(scope.getPodId());
dataStore.setClusterId(scope.getScopeId());
dataStoreDao.update(this.dataStore.getId(), dataStore);
return false; return false;
} }

View File

@ -18,7 +18,7 @@
*/ */
package org.apache.cloudstack.storage.volume; package org.apache.cloudstack.storage.volume;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.image.TemplateInfo; import org.apache.cloudstack.storage.image.TemplateInfo;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.Event; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.Event;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State;
@ -31,14 +31,14 @@ import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.fsm.StateMachine2;
public class TemplateOnPrimaryDataStoreObject implements TemplateOnPrimaryDataStoreInfo { public class TemplateOnPrimaryDataStoreObject implements TemplateOnPrimaryDataStoreInfo {
protected PrimaryDataStoreInfo dataStore; protected PrimaryDataStore dataStore;
protected TemplateInfo template; protected TemplateInfo template;
protected TemplatePrimaryDataStoreVO vo; protected TemplatePrimaryDataStoreVO vo;
protected TemplatePrimaryDataStoreDao templateStoreDao; protected TemplatePrimaryDataStoreDao templateStoreDao;
protected TemplatePrimaryDataStoreManager mgr; protected TemplatePrimaryDataStoreManager mgr;
protected StateMachine2<State, Event, TemplatePrimaryDataStoreVO> stateMachine; protected StateMachine2<State, Event, TemplatePrimaryDataStoreVO> stateMachine;
public TemplateOnPrimaryDataStoreObject(PrimaryDataStoreInfo primaryDataStore, TemplateInfo template, TemplatePrimaryDataStoreVO vo, public TemplateOnPrimaryDataStoreObject(PrimaryDataStore primaryDataStore, TemplateInfo template, TemplatePrimaryDataStoreVO vo,
TemplatePrimaryDataStoreDao templateStoreDao, TemplatePrimaryDataStoreManager mgr) { TemplatePrimaryDataStoreDao templateStoreDao, TemplatePrimaryDataStoreManager mgr) {
this.dataStore = primaryDataStore; this.dataStore = primaryDataStore;
this.template = template; this.template = template;
@ -59,7 +59,7 @@ public class TemplateOnPrimaryDataStoreObject implements TemplateOnPrimaryDataSt
} }
@Override @Override
public PrimaryDataStoreInfo getPrimaryDataStore() { public PrimaryDataStore getPrimaryDataStore() {
return this.dataStore; return this.dataStore;
} }
@ -77,7 +77,7 @@ public class TemplateOnPrimaryDataStoreObject implements TemplateOnPrimaryDataSt
try { try {
this.stateMachine.transitTo(vo, event, null, templateStoreDao); this.stateMachine.transitTo(vo, event, null, templateStoreDao);
} catch (NoTransitionException e) { } catch (NoTransitionException e) {
throw new CloudRuntimeException(e.toString()); throw new CloudRuntimeException("Failed change state", e);
} }
} }
} }

View File

@ -18,7 +18,7 @@
*/ */
package org.apache.cloudstack.storage.volume; package org.apache.cloudstack.storage.volume;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.image.TemplateInfo; import org.apache.cloudstack.storage.image.TemplateInfo;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.Event; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.Event;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State;
@ -27,9 +27,9 @@ import org.apache.cloudstack.storage.volume.db.TemplatePrimaryDataStoreVO;
import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.fsm.StateMachine2;
public interface TemplatePrimaryDataStoreManager { public interface TemplatePrimaryDataStoreManager {
public TemplateOnPrimaryDataStoreInfo createTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStoreInfo dataStore); public TemplateOnPrimaryDataStoreInfo createTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStore dataStore);
public TemplateOnPrimaryDataStoreInfo findTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStoreInfo dataStore); public TemplateOnPrimaryDataStoreInfo findTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStore dataStore);
public StateMachine2<State, Event, TemplatePrimaryDataStoreVO> getStateMachine(); public StateMachine2<State, Event, TemplatePrimaryDataStoreVO> getStateMachine();
} }

View File

@ -21,6 +21,7 @@ package org.apache.cloudstack.storage.volume;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.image.TemplateInfo; import org.apache.cloudstack.storage.image.TemplateInfo;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.Event; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.Event;
import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State;
@ -79,7 +80,7 @@ public class TemplatePrimaryDataStoreManagerImpl implements TemplatePrimaryDataS
return templateStoreVO; return templateStoreVO;
} }
@Override @Override
public TemplateOnPrimaryDataStoreObject createTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStoreInfo dataStore) { public TemplateOnPrimaryDataStoreObject createTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStore dataStore) {
TemplatePrimaryDataStoreVO templateStoreVO = null; TemplatePrimaryDataStoreVO templateStoreVO = null;
boolean freshNewTemplate = false; boolean freshNewTemplate = false;
templateStoreVO = templateStoreDao.findByTemplateIdAndPoolId(template.getId(), dataStore.getId()); templateStoreVO = templateStoreDao.findByTemplateIdAndPoolId(template.getId(), dataStore.getId());
@ -106,7 +107,7 @@ public class TemplatePrimaryDataStoreManagerImpl implements TemplatePrimaryDataS
} }
@Override @Override
public TemplateOnPrimaryDataStoreObject findTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStoreInfo dataStore) { public TemplateOnPrimaryDataStoreObject findTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStore dataStore) {
SearchCriteriaService<TemplatePrimaryDataStoreVO, TemplatePrimaryDataStoreVO> sc = SearchCriteria2.create(TemplatePrimaryDataStoreVO.class); SearchCriteriaService<TemplatePrimaryDataStoreVO, TemplatePrimaryDataStoreVO> sc = SearchCriteria2.create(TemplatePrimaryDataStoreVO.class);
sc.addAnd(sc.getEntity().getTemplateId(), Op.EQ, template.getId()); sc.addAnd(sc.getEntity().getTemplateId(), Op.EQ, template.getId());
sc.addAnd(sc.getEntity().getPoolId(), Op.EQ, dataStore.getId()); sc.addAnd(sc.getEntity().getPoolId(), Op.EQ, dataStore.getId());

View File

@ -19,6 +19,7 @@ import org.apache.log4j.Logger;
import com.cloud.storage.Volume; import com.cloud.storage.Volume;
import com.cloud.storage.Volume.State; import com.cloud.storage.Volume.State;
import com.cloud.utils.component.ComponentInject; import com.cloud.utils.component.ComponentInject;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.fsm.StateMachine2;

View File

@ -20,11 +20,9 @@ package org.apache.cloudstack.storage.volume;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.cloudstack.engine.cloud.entity.api.TemplateEntity;
import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskType;
import org.apache.cloudstack.engine.subsystem.api.storage.type.BaseImage;
import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCallbackHandler; import org.apache.cloudstack.framework.async.AsyncCallbackHandler;
@ -33,15 +31,12 @@ import org.apache.cloudstack.storage.EndPoint;
import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.datastore.PrimaryDataStore; import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
import org.apache.cloudstack.storage.datastore.manager.PrimaryDataStoreManager; import org.apache.cloudstack.storage.datastore.manager.PrimaryDataStoreManager;
import org.apache.cloudstack.storage.image.TemplateEntityImpl;
import org.apache.cloudstack.storage.image.TemplateInfo; import org.apache.cloudstack.storage.image.TemplateInfo;
import org.apache.cloudstack.storage.image.motion.ImageMotionService; import org.apache.cloudstack.storage.image.motion.ImageMotionService;
import org.apache.cloudstack.storage.volume.db.VolumeDao; import org.apache.cloudstack.storage.volume.db.VolumeDao;
import org.apache.cloudstack.storage.volume.db.VolumeVO; import org.apache.cloudstack.storage.volume.db.VolumeVO;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.Volume; import com.cloud.storage.Volume;
import com.cloud.utils.db.DB; import com.cloud.utils.db.DB;
@ -136,7 +131,8 @@ public class VolumeServiceImpl implements VolumeService {
return null; return null;
} }
protected void createBaseImageAsync(PrimaryDataStore dataStore, TemplateInfo template, AsyncCompletionCallback<TemplateOnPrimaryDataStoreObject> callback) { @DB
protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCompletionCallback<VolumeInfo> callback) {
TemplateOnPrimaryDataStoreObject templateOnPrimaryStoreObj = (TemplateOnPrimaryDataStoreObject) templatePrimaryStoreMgr.createTemplateOnPrimaryDataStore(template, dataStore); TemplateOnPrimaryDataStoreObject templateOnPrimaryStoreObj = (TemplateOnPrimaryDataStoreObject) templatePrimaryStoreMgr.createTemplateOnPrimaryDataStore(template, dataStore);
templateOnPrimaryStoreObj.stateTransit(TemplateOnPrimaryDataStoreStateMachine.Event.CreateRequested); templateOnPrimaryStoreObj.stateTransit(TemplateOnPrimaryDataStoreStateMachine.Event.CreateRequested);
templateOnPrimaryStoreObj.updateStatus(Status.CREATING); templateOnPrimaryStoreObj.updateStatus(Status.CREATING);
@ -154,11 +150,14 @@ public class VolumeServiceImpl implements VolumeService {
AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this) AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this)
.setParentCallback(callback) .setParentCallback(callback)
.setOperationName("volumeservice.createbaseimage.callback") .setOperationName("volumeservice.createbaseimage.callback")
.setContextParam("volume", volume)
.setContextParam("primary", dataStore)
.setContextParam("templateOnPrimary", templateOnPrimaryStoreObj); .setContextParam("templateOnPrimary", templateOnPrimaryStoreObj);
imageMotion.copyTemplateAsync(templateOnPrimaryStoreObj, caller); imageMotion.copyTemplateAsync(templateOnPrimaryStoreObj, caller);
} }
@DB
@AsyncCallbackHandler(operationName="volumeservice.createbaseimage.callback") @AsyncCallbackHandler(operationName="volumeservice.createbaseimage.callback")
public void createBaseImageCallback(AsyncCallbackDispatcher callback) { public void createBaseImageCallback(AsyncCallbackDispatcher callback) {
CommandResult result = callback.getResult(); CommandResult result = callback.getResult();
@ -172,8 +171,8 @@ public class VolumeServiceImpl implements VolumeService {
} }
AsyncCallbackDispatcher parentCaller = callback.getParentCallback(); AsyncCallbackDispatcher parentCaller = callback.getParentCallback();
VolumeInfo volume = parentCaller.getContextParam("volume"); VolumeInfo volume = callback.getContextParam("volume");
PrimaryDataStore pd = parentCaller.getContextParam("primary"); PrimaryDataStore pd = callback.getContextParam("primary");
AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this) AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this)
.setParentCallback(parentCaller) .setParentCallback(parentCaller)
.setOperationName("volumeservice.createvolumefrombaseimage.callback"); .setOperationName("volumeservice.createvolumefrombaseimage.callback");
@ -181,6 +180,7 @@ public class VolumeServiceImpl implements VolumeService {
createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, pd, caller); createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, pd, caller);
} }
@DB
protected void createVolumeFromBaseImageAsync(VolumeInfo volume, TemplateOnPrimaryDataStoreInfo templateOnPrimaryStore, PrimaryDataStore pd, AsyncCompletionCallback<VolumeObject> callback) { protected void createVolumeFromBaseImageAsync(VolumeInfo volume, TemplateOnPrimaryDataStoreInfo templateOnPrimaryStore, PrimaryDataStore pd, AsyncCompletionCallback<VolumeObject> callback) {
VolumeObject vo = (VolumeObject) volume; VolumeObject vo = (VolumeObject) volume;
try { try {
@ -198,6 +198,7 @@ public class VolumeServiceImpl implements VolumeService {
pd.createVoluemFromBaseImageAsync(volume, templateOnPrimaryStore, caller); pd.createVoluemFromBaseImageAsync(volume, templateOnPrimaryStore, caller);
} }
@DB
@AsyncCallbackHandler(operationName="volumeservice.createVolumeFromBaseImageCallback") @AsyncCallbackHandler(operationName="volumeservice.createVolumeFromBaseImageCallback")
public void createVolumeFromBaseImageCallback(AsyncCallbackDispatcher callback) { public void createVolumeFromBaseImageCallback(AsyncCallbackDispatcher callback) {
VolumeObject vo = callback.getContextParam("volume"); VolumeObject vo = callback.getContextParam("volume");
@ -212,6 +213,7 @@ public class VolumeServiceImpl implements VolumeService {
parentCall.complete(vo); parentCall.complete(vo);
} }
@DB
@AsyncCallbackHandler(operationName="volumeservice.createvolumefrombaseimage.callback") @AsyncCallbackHandler(operationName="volumeservice.createvolumefrombaseimage.callback")
public void createVolumeFromBaseImageAsyncCallback(AsyncCallbackDispatcher callback) { public void createVolumeFromBaseImageAsyncCallback(AsyncCallbackDispatcher callback) {
AsyncCallbackDispatcher parentCall = callback.getParentCallback(); AsyncCallbackDispatcher parentCall = callback.getParentCallback();
@ -219,16 +221,13 @@ public class VolumeServiceImpl implements VolumeService {
parentCall.complete(vo); parentCall.complete(vo);
} }
@DB
@Override @Override
public void createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType, TemplateInfo template, AsyncCompletionCallback<VolumeInfo> callback) { public void createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType, TemplateInfo template, AsyncCompletionCallback<VolumeInfo> callback) {
PrimaryDataStore pd = dataStoreMgr.getPrimaryDataStore(dataStoreId); PrimaryDataStore pd = dataStoreMgr.getPrimaryDataStore(dataStoreId);
TemplateOnPrimaryDataStoreInfo templateOnPrimaryStore = pd.getTemplate(template); TemplateOnPrimaryDataStoreInfo templateOnPrimaryStore = pd.getTemplate(template);
if (templateOnPrimaryStore == null) { if (templateOnPrimaryStore == null) {
AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this).setParentCallback(callback) createBaseImageAsync(volume, pd, template, callback);
.setOperationName("volumeservice.createbaseimage.callback")
.setContextParam("volume", volume)
.setContextParam("primary", pd);
createBaseImageAsync(pd, template, caller);
return; return;
} }

View File

@ -18,7 +18,9 @@
*/ */
package org.apache.cloudstack.storage.volume.test; package org.apache.cloudstack.storage.volume.test;
import org.apache.cloudstack.storage.HostEndpointRpcServer;
import org.apache.cloudstack.storage.image.motion.ImageMotionService; import org.apache.cloudstack.storage.image.motion.ImageMotionService;
import org.apache.cloudstack.storage.test.MockHypervsiorHostEndPointRpcServer;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -38,4 +40,9 @@ public class TestConfiguration {
public ClusterDao clusterDao() { public ClusterDao clusterDao() {
return Mockito.mock(ClusterDaoImpl.class); return Mockito.mock(ClusterDaoImpl.class);
} }
@Bean
public HostEndpointRpcServer rpcServer() {
return new MockHypervsiorHostEndPointRpcServer();
}
} }

View File

@ -104,7 +104,7 @@ public class AsyncCallbackDispatcher implements AsyncCompletionCallback {
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new RuntimeException("IllegalAccessException when invoking RPC callback for command: " + callback.getOperationName()); throw new RuntimeException("IllegalAccessException when invoking RPC callback for command: " + callback.getOperationName());
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
throw new RuntimeException("InvocationTargetException when invoking RPC callback for command: " + callback.getOperationName()); throw new RuntimeException("InvocationTargetException when invoking RPC callback for command: " + callback.getOperationName(), e);
} }
return true; return true;

View File

@ -19,6 +19,8 @@ alter table vm_template add image_data_store_id bigint unsigned;
alter table storage_pool add storage_provider_id bigint unsigned; alter table storage_pool add storage_provider_id bigint unsigned;
alter table storage_pool add configurator_key varchar(255); alter table storage_pool add configurator_key varchar(255);
alter table storage_pool modify id bigint unsigned AUTO_INCREMENT UNIQUE NOT NULL; alter table storage_pool modify id bigint unsigned AUTO_INCREMENT UNIQUE NOT NULL;
alter table template_spool_ref add state varchar(255);
alter table template_spool_ref add update_count bigint unsigned;
alter table volumes add disk_type varchar(255); alter table volumes add disk_type varchar(255);
alter table volumes drop foreign key `fk_volumes__account_id`; alter table volumes drop foreign key `fk_volumes__account_id`;
CREATE TABLE `cloud`.`primary_data_store_provider` ( CREATE TABLE `cloud`.`primary_data_store_provider` (