From aefb657c412c86482814ae0f378b9f315e041bb1 Mon Sep 17 00:00:00 2001 From: Edison Su Date: Mon, 17 Dec 2012 18:12:46 -0800 Subject: [PATCH] Finally, get async api call works for storage subsystem --- .../subsystem/api/storage}/ClusterScope.java | 18 +++-- .../subsystem/api/storage}/HostScope.java | 4 +- .../api/storage/PrimaryDataStoreInfo.java | 11 ++- .../storage/PrimaryDataStoreLifeCycle.java | 2 +- .../subsystem/api/storage}/ZoneScope.java | 4 +- .../motion/DefaultImageMotionStrategy.java | 18 ++--- .../image/motion/ImageMotionServiceImpl.java | 2 +- .../storage/test/ChildTestConfiguration.java | 6 ++ .../MockHypervsiorHostEndPointRpcServer.java | 69 +++++++++++++++++++ .../storage/test/TestConfiguration.java | 6 -- .../storage/test/volumeServiceTest.java | 13 +++- .../test/resource/storageContext.xml | 26 +++++++ .../storage/HostEndpointRpcServer.java | 28 ++++++++ .../storage/HypervisorHostEndPoint.java | 2 +- .../HypervsiorHostEndPointRpcServer.java | 9 ++- .../CopyTemplateToPrimaryStorageAnswer.java | 4 +- .../storage/command/CreateVolumeAnswer.java | 4 +- .../TemplateOnPrimaryDataStoreInfo.java | 4 +- .../storage/volume/VolumeEntityImpl.java | 23 ++++++- .../volume/db/TemplatePrimaryDataStoreVO.java | 1 + .../datastore/DefaultPrimaryDataStore.java | 30 ++++++-- .../DefaultPrimaryDataStoreDriverImpl.java | 43 +++++++++--- .../driver/PrimaryDataStoreDriver.java | 4 +- .../DefaultPrimaryDataStoreLifeCycleImpl.java | 19 ++--- .../TemplateOnPrimaryDataStoreObject.java | 10 +-- .../TemplatePrimaryDataStoreManager.java | 6 +- .../TemplatePrimaryDataStoreManagerImpl.java | 5 +- .../storage/volume/VolumeObject.java | 1 + .../storage/volume/VolumeServiceImpl.java | 25 ++++--- .../volume/test/TestConfiguration.java | 7 ++ .../async/AsyncCallbackDispatcher.java | 2 +- setup/db/4.1-new-db-schema.sql | 2 + 32 files changed, 314 insertions(+), 94 deletions(-) rename engine/{storage/src/org/apache/cloudstack/storage/scope => api/src/org/apache/cloudstack/engine/subsystem/api/storage}/ClusterScope.java (75%) rename engine/{storage/src/org/apache/cloudstack/storage/scope => api/src/org/apache/cloudstack/engine/subsystem/api/storage}/HostScope.java (86%) rename engine/{storage/src/org/apache/cloudstack/storage/scope => api/src/org/apache/cloudstack/engine/subsystem/api/storage}/ZoneScope.java (86%) create mode 100644 engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java create mode 100644 engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java diff --git a/engine/storage/src/org/apache/cloudstack/storage/scope/ClusterScope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java similarity index 75% rename from engine/storage/src/org/apache/cloudstack/storage/scope/ClusterScope.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java index dad2f509bc4..50d5444233b 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/scope/ClusterScope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ClusterScope.java @@ -16,17 +16,19 @@ * specific language governing permissions and limitations * 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 { private ScopeType type = ScopeType.CLUSTER; 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.podId = podId; + this.zoneId = zoneId; } @Override @@ -38,5 +40,13 @@ public class ClusterScope implements Scope { public long getScopeId() { return this.clusterId; } + + public long getPodId() { + return this.podId; + } + + public long getZoneId() { + return this.zoneId; + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/scope/HostScope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java similarity index 86% rename from engine/storage/src/org/apache/cloudstack/storage/scope/HostScope.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java index a36c98e8375..da36e439376 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/scope/HostScope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/HostScope.java @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * 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 { private ScopeType type = ScopeType.HOST; diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java index e53b6a27481..f75662659ce 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java @@ -19,13 +19,12 @@ 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.storage.EndPoint; + + import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.Volume; public interface PrimaryDataStoreInfo { public boolean isHypervisorSupported(HypervisorType hypervisor); @@ -33,10 +32,10 @@ public interface PrimaryDataStoreInfo { public boolean isVolumeDiskTypeSupported(VolumeDiskType diskType); public long getCapacity(); public long getAvailableCapacity(); - public List getEndPoints(); + public long getId(); public String getUuid(); - public State getManagedState(); + public Volume.State getManagedState(); public String getName(); public String getType(); public PrimaryDataStoreLifeCycle getLifeCycle(); diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java index 3f457c9c28a..afdf085e532 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreLifeCycle.java @@ -23,7 +23,7 @@ import java.util.Map; public interface PrimaryDataStoreLifeCycle { public boolean initialize(Map dsInfos); - public boolean attach(Scope scope); + public boolean attachCluster(ClusterScope scope); public boolean dettach(); diff --git a/engine/storage/src/org/apache/cloudstack/storage/scope/ZoneScope.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java similarity index 86% rename from engine/storage/src/org/apache/cloudstack/storage/scope/ZoneScope.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java index 23a0ddbb5b3..7f211f4f9e9 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/scope/ZoneScope.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ZoneScope.java @@ -16,10 +16,8 @@ * specific language governing permissions and limitations * 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 { private ScopeType type = ScopeType.ZONE; diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java index be541b51300..8ebe8fdb017 100644 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java +++ b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java @@ -18,7 +18,6 @@ */ 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.AsyncCallbackHandler; 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.CopyTemplateToPrimaryStorage; 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.volume.TemplateOnPrimaryDataStoreInfo; import org.springframework.stereotype.Component; -import com.cloud.agent.api.Answer; - @Component public class DefaultImageMotionStrategy implements ImageMotionStrategy { @@ -43,7 +41,7 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy { @Override public EndPoint getEndPoint(TemplateOnPrimaryDataStoreInfo templateStore) { - PrimaryDataStoreInfo pdi = templateStore.getPrimaryDataStore(); + PrimaryDataStore pdi = templateStore.getPrimaryDataStore(); return pdi.getEndPoints().get(0); } @@ -59,7 +57,7 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy { public void copyTemplateAsync(TemplateOnPrimaryDataStoreInfo templateStore, EndPoint ep, AsyncCompletionCallback callback) { ImageOnPrimayDataStoreTO imageTo = new ImageOnPrimayDataStoreTO(templateStore); CopyTemplateToPrimaryStorage copyCommand = new CopyTemplateToPrimaryStorage(imageTo); - AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this).setParentCallback(callback) + AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this).setParentCallback(callback) .setOperationName("defaultImageStrategy.copytemplate.callback") .setContextParam("templateStore", templateStore); ep.sendMessageAsync(copyCommand, caller); @@ -71,13 +69,15 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy { CopyTemplateToPrimaryStorageAnswer answer = callback.getResult(); CommandResult result = new CommandResult(); - result.setSucess(answer.getResult()); - result.setResult(answer.getDetails()); - if (answer.getResult()) { + if (!answer.getResult()) { + result.setSucess(answer.getResult()); + result.setResult(answer.getDetails()); + } else { TemplateOnPrimaryDataStoreInfo templateStore = callback.getContextParam("templateStore"); templateStore.setPath(answer.getPath()); + result.setSucess(true); } - + parentCall.complete(result); } diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionServiceImpl.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionServiceImpl.java index 85baba6f614..45929e44f0c 100644 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionServiceImpl.java +++ b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/ImageMotionServiceImpl.java @@ -99,7 +99,7 @@ public class ImageMotionServiceImpl implements ImageMotionService { } @AsyncCallbackHandler(operationName="imagemotionService.copytemplate.callback") - public void copyTemplateAsyncCallback(AsyncCallbackDispatcher callback) { + public void copyTemplateAsyncCallback( AsyncCallbackDispatcher callback) { AsyncCallbackDispatcher parentCaller = callback.getParentCallback(); parentCaller.complete(callback.getResult()); } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java index aa9abe3a671..27a8513e1c5 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java @@ -1,5 +1,6 @@ package org.apache.cloudstack.storage.test; +import org.apache.cloudstack.storage.HostEndpointRpcServer; import org.mockito.Mockito; import org.springframework.context.annotation.Bean; @@ -20,6 +21,11 @@ public class ChildTestConfiguration extends TestConfiguration { public AgentManager agentMgr() { return new DirectAgentManagerSimpleImpl(); } + + @Bean + public HostEndpointRpcServer rpcServer() { + return new MockHypervsiorHostEndPointRpcServer(); + } /* @Override @Bean public PrimaryDataStoreDao primaryDataStoreDao() { diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java new file mode 100644 index 00000000000..6142c3e13d0 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java @@ -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 callback; + public MockRpcCallBack(Command cmd, final AsyncCompletionCallback 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 callback) { + executor.schedule(new MockRpcCallBack(command, callback), 10, TimeUnit.SECONDS); + } +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestConfiguration.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestConfiguration.java index 42cd8fb5f59..de7944ce8ac 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestConfiguration.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TestConfiguration.java @@ -1,7 +1,5 @@ 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.Configuration; @@ -14,8 +12,4 @@ public class TestConfiguration { public HostDao hostDao() { return new HostDaoImpl(); } - @Bean - public PrimaryDataStoreDao primaryDataStoreDao() { - return new PrimaryDataStoreDaoImpl(); - } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java index e34f07749df..59a7554e98e 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java @@ -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.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.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.disktype.QCOW2; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VHD; import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VMDK; @@ -131,6 +133,7 @@ public class volumeServiceTest { AgentManager agentMgr; Long dcId; Long clusterId; + Long podId; @Before public void setUp() { //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"); pod = podDao.persist(pod); + podId = pod.getId(); //create xen cluster ClusterVO cluster = new ClusterVO(dc.getId(), pod.getId(), "devcloud cluster"); cluster.setHypervisorType(HypervisorType.XenServer.toString()); @@ -168,9 +172,9 @@ public class volumeServiceTest { results.add(host); Mockito.when(hostDao.listAll()).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); } catch (AgentUnavailableException e) { // TODO Auto-generated catch block @@ -178,7 +182,7 @@ public class volumeServiceTest { } catch (OperationTimedoutException e) { // TODO Auto-generated catch block e.printStackTrace(); - } + }*/ //Mockito.when(primaryStoreDao.findById(Mockito.anyLong())).thenReturn(primaryStore); @@ -238,6 +242,9 @@ public class volumeServiceTest { params.put("clusterId", clusterId.toString()); params.put("name", "my primary data store"); PrimaryDataStoreInfo primaryDataStoreInfo = provider.registerDataStore(params); + PrimaryDataStoreLifeCycle lc = primaryDataStoreInfo.getLifeCycle(); + ClusterScope scope = new ClusterScope(clusterId, podId, dcId); + lc.attachCluster(scope); return primaryDataStoreInfo; } catch (ConfigurationException e) { return null; diff --git a/engine/storage/integration-test/test/resource/storageContext.xml b/engine/storage/integration-test/test/resource/storageContext.xml index 86811c354b4..0b99ba14940 100644 --- a/engine/storage/integration-test/test/resource/storageContext.xml +++ b/engine/storage/integration-test/test/resource/storageContext.xml @@ -38,5 +38,31 @@ + + + + + org.apache.cloudstack.framework + + + + + + + + + + + + + + + + + + + + diff --git a/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java b/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java new file mode 100644 index 00000000000..25ebc7fa191 --- /dev/null +++ b/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java @@ -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 callback); +} diff --git a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java index 5b422590bd5..9e06b92b342 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java +++ b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java @@ -38,7 +38,7 @@ public class HypervisorHostEndPoint implements EndPoint { @Inject AgentManager agentMgr; @Inject - HypervsiorHostEndPointRpcServer rpcServer; + HostEndpointRpcServer rpcServer; public HypervisorHostEndPoint(long hostId, String hostAddress) { this.hostId = hostId; diff --git a/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java b/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java index c1b5760a4d4..de7b386a3ff 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java +++ b/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java @@ -31,13 +31,16 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; @Component -public class HypervsiorHostEndPointRpcServer { - @Inject +public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer { + private RpcProvider _rpcProvider; - public HypervsiorHostEndPointRpcServer() { + @Inject + public HypervsiorHostEndPointRpcServer(RpcProvider rpcProvider) { + _rpcProvider = rpcProvider; _rpcProvider.registerRpcServiceEndpoint(RpcServiceDispatcher.getDispatcher(this)); } + @Override public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback callback) { _rpcProvider.newCall(host).addCallbackListener(new RpcCallbackListener() { @Override diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CopyTemplateToPrimaryStorageAnswer.java b/engine/storage/src/org/apache/cloudstack/storage/command/CopyTemplateToPrimaryStorageAnswer.java index f67c102cdc6..773a3e4a07f 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CopyTemplateToPrimaryStorageAnswer.java +++ b/engine/storage/src/org/apache/cloudstack/storage/command/CopyTemplateToPrimaryStorageAnswer.java @@ -1,11 +1,13 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; public class CopyTemplateToPrimaryStorageAnswer extends Answer { private final String path; - public CopyTemplateToPrimaryStorageAnswer(String path) { + public CopyTemplateToPrimaryStorageAnswer(Command cmd, String path) { + super(cmd); this.path = path; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java index 49fa93e1ede..cfed00c60ab 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java +++ b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.storage.command; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; public class CreateVolumeAnswer extends Answer { private String volumeUuid; @@ -27,7 +28,8 @@ public class CreateVolumeAnswer extends Answer { super(); } - public CreateVolumeAnswer(String volumeUuid) { + public CreateVolumeAnswer(Command cmd, String volumeUuid) { + super(cmd); this.volumeUuid = volumeUuid; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreInfo.java b/engine/storage/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreInfo.java index b1bf403c4e3..368c33a32bf 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreInfo.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreInfo.java @@ -18,7 +18,7 @@ */ 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; public interface TemplateOnPrimaryDataStoreInfo { @@ -26,7 +26,7 @@ public interface TemplateOnPrimaryDataStoreInfo { public void setPath(String path); - public PrimaryDataStoreInfo getPrimaryDataStore(); + public PrimaryDataStore getPrimaryDataStore(); public TemplateInfo getTemplate(); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java index 0dfa43efec8..632542aba3c 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java @@ -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.disktype.VolumeDiskType; 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.image.TemplateEntityImpl; import org.apache.cloudstack.storage.image.TemplateInfo; +import com.cloud.utils.exception.CloudRuntimeException; + public class VolumeEntityImpl implements VolumeEntity { private VolumeInfo volumeInfo; private final VolumeService vs; @@ -192,8 +196,25 @@ public class VolumeEntityImpl implements VolumeEntity { @Override public boolean createVolumeFromTemplate(long dataStoreId, VolumeDiskType diskType, TemplateEntity template) { 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; } + + @AsyncCallbackHandler(operationName="volumeEntity.createVolumeFromTemplateAsyncCallback") + public void createVolumeFromTemplateAsyncCallback(AsyncCallbackDispatcher callback) { + synchronized (volumeInfo) { + volumeInfo.notify(); + } + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java index 522101f09fb..ffaa6f7f944 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/db/TemplatePrimaryDataStoreVO.java @@ -165,6 +165,7 @@ public class TemplatePrimaryDataStoreVO implements StateObject 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 public boolean installTemplate(TemplateOnPrimaryDataStoreInfo template) { @@ -202,7 +222,7 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { } @Override - public State getManagedState() { + public Volume.State getManagedState() { // TODO Auto-generated method stub return null; } @@ -228,4 +248,6 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { public PrimaryDataStoreProvider getProvider() { return this.provider; } + + } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java index 8588ca3bca6..a2506cad4f5 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java @@ -4,7 +4,11 @@ import java.util.List; import java.util.Map; 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.command.CommandResult; import org.apache.cloudstack.storage.command.CreateVolumeAnswer; import org.apache.cloudstack.storage.command.CreateVolumeCommand; import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand; @@ -98,19 +102,40 @@ public class DefaultPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver return answer; } - + @Override - public boolean createVolumeFromBaseImage(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template) { + public void createVolumeFromBaseImageAsync(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template, AsyncCompletionCallback callback) { VolumeTO vol = new VolumeTO(volume); ImageOnPrimayDataStoreTO image = new ImageOnPrimayDataStoreTO(template); CreateVolumeFromBaseImageCommand cmd = new CreateVolumeFromBaseImageCommand(vol, image); List endPoints = template.getPrimaryDataStore().getEndPoints(); - - Answer answer = sendOutCommand(cmd, endPoints); - - CreateVolumeAnswer volAnswer = (CreateVolumeAnswer) answer; - volume.setPath(volAnswer.getVolumeUuid()); - return true; + EndPoint ep = endPoints.get(0); + + AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this) + .setParentCallback(callback) + .setOperationName("primarydatastoredriver.createvolumefrombaseImage") + .setContextParam("volume", volume); + ep.sendMessageAsync(cmd, caller); + + + } + + @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 @@ -142,4 +167,6 @@ public class DefaultPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver // TODO Auto-generated method stub return false; } + + } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java index 0b25e9b35cf..04694aa888a 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java @@ -2,7 +2,9 @@ package org.apache.cloudstack.storage.datastore.driver; import java.util.Map; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; 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.volume.TemplateOnPrimaryDataStoreInfo; import org.apache.cloudstack.storage.volume.VolumeObject; @@ -10,7 +12,7 @@ import org.apache.cloudstack.storage.volume.VolumeObject; public interface PrimaryDataStoreDriver { boolean createVolume(VolumeObject vol); - boolean createVolumeFromBaseImage(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template); + void createVolumeFromBaseImageAsync(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template, AsyncCompletionCallback callback); boolean deleteVolume(VolumeObject vo); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java index 062c6252c12..dc304a113c0 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java @@ -18,23 +18,14 @@ */ package org.apache.cloudstack.storage.datastore.lifecycle; -import java.net.URI; -import java.net.URISyntaxException; 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.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.PrimaryDataStore; 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.springframework.stereotype.Component; public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle { protected PrimaryDataStoreInfo dataStore; @@ -58,8 +49,12 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif } @Override - public boolean attach(Scope scope) { - //if (scope.getScopeType() == ScopeType.CLUSTER) + public boolean attachCluster(ClusterScope scope) { + 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; } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreObject.java index 42d8e4ab03c..9d6452d1978 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateOnPrimaryDataStoreObject.java @@ -18,7 +18,7 @@ */ 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.volume.TemplateOnPrimaryDataStoreStateMachine.Event; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State; @@ -31,14 +31,14 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; public class TemplateOnPrimaryDataStoreObject implements TemplateOnPrimaryDataStoreInfo { - protected PrimaryDataStoreInfo dataStore; + protected PrimaryDataStore dataStore; protected TemplateInfo template; protected TemplatePrimaryDataStoreVO vo; protected TemplatePrimaryDataStoreDao templateStoreDao; protected TemplatePrimaryDataStoreManager mgr; protected StateMachine2 stateMachine; - public TemplateOnPrimaryDataStoreObject(PrimaryDataStoreInfo primaryDataStore, TemplateInfo template, TemplatePrimaryDataStoreVO vo, + public TemplateOnPrimaryDataStoreObject(PrimaryDataStore primaryDataStore, TemplateInfo template, TemplatePrimaryDataStoreVO vo, TemplatePrimaryDataStoreDao templateStoreDao, TemplatePrimaryDataStoreManager mgr) { this.dataStore = primaryDataStore; this.template = template; @@ -59,7 +59,7 @@ public class TemplateOnPrimaryDataStoreObject implements TemplateOnPrimaryDataSt } @Override - public PrimaryDataStoreInfo getPrimaryDataStore() { + public PrimaryDataStore getPrimaryDataStore() { return this.dataStore; } @@ -77,7 +77,7 @@ public class TemplateOnPrimaryDataStoreObject implements TemplateOnPrimaryDataSt try { this.stateMachine.transitTo(vo, event, null, templateStoreDao); } catch (NoTransitionException e) { - throw new CloudRuntimeException(e.toString()); + throw new CloudRuntimeException("Failed change state", e); } } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManager.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManager.java index 92703912c1f..4c08fee29e4 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManager.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManager.java @@ -18,7 +18,7 @@ */ 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.volume.TemplateOnPrimaryDataStoreStateMachine.Event; 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; 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 getStateMachine(); } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManagerImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManagerImpl.java index b197ba1bd24..d1cac977588 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManagerImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplatePrimaryDataStoreManagerImpl.java @@ -21,6 +21,7 @@ package org.apache.cloudstack.storage.volume; import javax.inject.Inject; 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.volume.TemplateOnPrimaryDataStoreStateMachine.Event; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreStateMachine.State; @@ -79,7 +80,7 @@ public class TemplatePrimaryDataStoreManagerImpl implements TemplatePrimaryDataS return templateStoreVO; } @Override - public TemplateOnPrimaryDataStoreObject createTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStoreInfo dataStore) { + public TemplateOnPrimaryDataStoreObject createTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStore dataStore) { TemplatePrimaryDataStoreVO templateStoreVO = null; boolean freshNewTemplate = false; templateStoreVO = templateStoreDao.findByTemplateIdAndPoolId(template.getId(), dataStore.getId()); @@ -106,7 +107,7 @@ public class TemplatePrimaryDataStoreManagerImpl implements TemplatePrimaryDataS } @Override - public TemplateOnPrimaryDataStoreObject findTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStoreInfo dataStore) { + public TemplateOnPrimaryDataStoreObject findTemplateOnPrimaryDataStore(TemplateInfo template, PrimaryDataStore dataStore) { SearchCriteriaService sc = SearchCriteria2.create(TemplatePrimaryDataStoreVO.class); sc.addAnd(sc.getEntity().getTemplateId(), Op.EQ, template.getId()); sc.addAnd(sc.getEntity().getPoolId(), Op.EQ, dataStore.getId()); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index 9a462d81fd3..38cc1593f50 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -19,6 +19,7 @@ import org.apache.log4j.Logger; import com.cloud.storage.Volume; import com.cloud.storage.Volume.State; import com.cloud.utils.component.ComponentInject; +import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index f119a59e84a..cd3414a5aaf 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -20,11 +20,9 @@ package org.apache.cloudstack.storage.volume; 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.subsystem.api.storage.VolumeInfo; 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.framework.async.AsyncCallbackDispatcher; 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.datastore.PrimaryDataStore; 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.motion.ImageMotionService; import org.apache.cloudstack.storage.volume.db.VolumeDao; import org.apache.cloudstack.storage.volume.db.VolumeVO; import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; - import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.Volume; import com.cloud.utils.db.DB; @@ -136,7 +131,8 @@ public class VolumeServiceImpl implements VolumeService { return null; } - protected void createBaseImageAsync(PrimaryDataStore dataStore, TemplateInfo template, AsyncCompletionCallback callback) { + @DB + protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCompletionCallback callback) { TemplateOnPrimaryDataStoreObject templateOnPrimaryStoreObj = (TemplateOnPrimaryDataStoreObject) templatePrimaryStoreMgr.createTemplateOnPrimaryDataStore(template, dataStore); templateOnPrimaryStoreObj.stateTransit(TemplateOnPrimaryDataStoreStateMachine.Event.CreateRequested); templateOnPrimaryStoreObj.updateStatus(Status.CREATING); @@ -154,11 +150,14 @@ public class VolumeServiceImpl implements VolumeService { AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this) .setParentCallback(callback) .setOperationName("volumeservice.createbaseimage.callback") + .setContextParam("volume", volume) + .setContextParam("primary", dataStore) .setContextParam("templateOnPrimary", templateOnPrimaryStoreObj); imageMotion.copyTemplateAsync(templateOnPrimaryStoreObj, caller); } + @DB @AsyncCallbackHandler(operationName="volumeservice.createbaseimage.callback") public void createBaseImageCallback(AsyncCallbackDispatcher callback) { CommandResult result = callback.getResult(); @@ -172,8 +171,8 @@ public class VolumeServiceImpl implements VolumeService { } AsyncCallbackDispatcher parentCaller = callback.getParentCallback(); - VolumeInfo volume = parentCaller.getContextParam("volume"); - PrimaryDataStore pd = parentCaller.getContextParam("primary"); + VolumeInfo volume = callback.getContextParam("volume"); + PrimaryDataStore pd = callback.getContextParam("primary"); AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this) .setParentCallback(parentCaller) .setOperationName("volumeservice.createvolumefrombaseimage.callback"); @@ -181,6 +180,7 @@ public class VolumeServiceImpl implements VolumeService { createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, pd, caller); } + @DB protected void createVolumeFromBaseImageAsync(VolumeInfo volume, TemplateOnPrimaryDataStoreInfo templateOnPrimaryStore, PrimaryDataStore pd, AsyncCompletionCallback callback) { VolumeObject vo = (VolumeObject) volume; try { @@ -198,6 +198,7 @@ public class VolumeServiceImpl implements VolumeService { pd.createVoluemFromBaseImageAsync(volume, templateOnPrimaryStore, caller); } + @DB @AsyncCallbackHandler(operationName="volumeservice.createVolumeFromBaseImageCallback") public void createVolumeFromBaseImageCallback(AsyncCallbackDispatcher callback) { VolumeObject vo = callback.getContextParam("volume"); @@ -212,6 +213,7 @@ public class VolumeServiceImpl implements VolumeService { parentCall.complete(vo); } + @DB @AsyncCallbackHandler(operationName="volumeservice.createvolumefrombaseimage.callback") public void createVolumeFromBaseImageAsyncCallback(AsyncCallbackDispatcher callback) { AsyncCallbackDispatcher parentCall = callback.getParentCallback(); @@ -219,16 +221,13 @@ public class VolumeServiceImpl implements VolumeService { parentCall.complete(vo); } + @DB @Override public void createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType, TemplateInfo template, AsyncCompletionCallback callback) { PrimaryDataStore pd = dataStoreMgr.getPrimaryDataStore(dataStoreId); TemplateOnPrimaryDataStoreInfo templateOnPrimaryStore = pd.getTemplate(template); if (templateOnPrimaryStore == null) { - AsyncCallbackDispatcher caller = new AsyncCallbackDispatcher(this).setParentCallback(callback) - .setOperationName("volumeservice.createbaseimage.callback") - .setContextParam("volume", volume) - .setContextParam("primary", pd); - createBaseImageAsync(pd, template, caller); + createBaseImageAsync(volume, pd, template, callback); return; } diff --git a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java index c755334730c..fff6eadb384 100644 --- a/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java +++ b/engine/storage/volume/test/org/apache/cloudstack/storage/volume/test/TestConfiguration.java @@ -18,7 +18,9 @@ */ 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.test.MockHypervsiorHostEndPointRpcServer; import org.mockito.Mockito; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -38,4 +40,9 @@ public class TestConfiguration { public ClusterDao clusterDao() { return Mockito.mock(ClusterDaoImpl.class); } + + @Bean + public HostEndpointRpcServer rpcServer() { + return new MockHypervsiorHostEndPointRpcServer(); + } } \ No newline at end of file diff --git a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java index 23c0b81a344..a02e130aa17 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java @@ -104,7 +104,7 @@ public class AsyncCallbackDispatcher implements AsyncCompletionCallback { } catch (IllegalAccessException e) { throw new RuntimeException("IllegalAccessException when invoking RPC callback for command: " + callback.getOperationName()); } 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; diff --git a/setup/db/4.1-new-db-schema.sql b/setup/db/4.1-new-db-schema.sql index a39cedc630c..4dfcc4bcb16 100644 --- a/setup/db/4.1-new-db-schema.sql +++ b/setup/db/4.1-new-db-schema.sql @@ -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 configurator_key varchar(255); 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 drop foreign key `fk_volumes__account_id`; CREATE TABLE `cloud`.`primary_data_store_provider` (