finaly, finish download template to primary storage

This commit is contained in:
Edison Su 2012-12-20 19:05:47 -08:00
parent 1d5019c3d0
commit ac88c16be6
16 changed files with 447 additions and 60 deletions

View File

@ -31,12 +31,14 @@ import com.cloud.agent.Listener;
import com.cloud.agent.StartupCommandProcessor; import com.cloud.agent.StartupCommandProcessor;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
import com.cloud.agent.api.SetupCommand;
import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.manager.AgentAttache; import com.cloud.agent.manager.AgentAttache;
import com.cloud.agent.manager.Commands; import com.cloud.agent.manager.Commands;
import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConnectionException; import com.cloud.exception.ConnectionException;
import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.HostEnvironment;
import com.cloud.host.HostVO; import com.cloud.host.HostVO;
import com.cloud.host.Status.Event; import com.cloud.host.Status.Event;
import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDao;
@ -100,6 +102,11 @@ public class DirectAgentManagerSimpleImpl implements AgentManager {
} catch (ConfigurationException e) { } catch (ConfigurationException e) {
logger.debug("Failed to load resource:" + e.toString()); logger.debug("Failed to load resource:" + e.toString());
} }
HostEnvironment env = new HostEnvironment();
SetupCommand cmd = new SetupCommand(env);
cmd.setNeedSetup(true);
resource.executeRequest(cmd);
} }
@Override @Override

View File

@ -69,7 +69,7 @@ public class DirectAgentTest {
private long dcId; private long dcId;
private long clusterId; private long clusterId;
private long hostId; private long hostId;
private String hostGuid = "759ee4c9-a15a-297b-67c6-ac267d8aa429"; private String hostGuid = "9d4c9db8-32f7-25c3-0435-eab4bf3adcea";
@Before @Before
public void setUp() { public void setUp() {
HostVO host = hostDao.findByGuid(hostGuid); HostVO host = hostDao.findByGuid(hostGuid);
@ -102,7 +102,7 @@ public class DirectAgentTest {
host.setName("devcloud xen host"); host.setName("devcloud xen host");
host.setType(Host.Type.Routing); host.setType(Host.Type.Routing);
host.setHypervisorType(HypervisorType.XenServer); host.setHypervisorType(HypervisorType.XenServer);
host.setPrivateIpAddress("192.168.56.2"); host.setPrivateIpAddress("192.168.56.10");
host.setDataCenterId(dc.getId()); host.setDataCenterId(dc.getId());
host.setVersion("6.0.1"); host.setVersion("6.0.1");
host.setAvailable(true); host.setAvailable(true);
@ -133,7 +133,7 @@ public class DirectAgentTest {
public void testDownloadTemplate() { public void testDownloadTemplate() {
ImageOnPrimayDataStoreTO image = Mockito.mock(ImageOnPrimayDataStoreTO.class); ImageOnPrimayDataStoreTO image = Mockito.mock(ImageOnPrimayDataStoreTO.class);
PrimaryDataStoreTO primaryStore = Mockito.mock(PrimaryDataStoreTO.class); PrimaryDataStoreTO primaryStore = Mockito.mock(PrimaryDataStoreTO.class);
Mockito.when(primaryStore.getUuid()).thenReturn("cd10cac1-4772-92e5-5da6-c2bc16b1ce1b"); Mockito.when(primaryStore.getUuid()).thenReturn("9f3f9262-3f77-09cc-2df7-0d8475676260");
Mockito.when(image.getPrimaryDataStore()).thenReturn(primaryStore); Mockito.when(image.getPrimaryDataStore()).thenReturn(primaryStore);
ImageDataStoreTO imageStore = Mockito.mock(ImageDataStoreTO.class); ImageDataStoreTO imageStore = Mockito.mock(ImageDataStoreTO.class);

View File

@ -0,0 +1,87 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cloudstack.storage.test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.HostEndpointRpcServer;
import org.apache.cloudstack.storage.HypervisorHostEndPoint;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
public class MockHostEndpointRpcServerDirectCallResource implements HostEndpointRpcServer {
private static final Logger s_logger = Logger.getLogger(MockHostEndpointRpcServerDirectCallResource.class);
private ScheduledExecutorService executor;
@Inject
AgentManager agentMgr;
public MockHostEndpointRpcServerDirectCallResource() {
executor = Executors.newScheduledThreadPool(10);
}
protected class MockRpcCallBack implements Runnable {
private final Command cmd;
private final long hostId;
private final AsyncCompletionCallback<Answer> callback;
public MockRpcCallBack(long hostId, Command cmd, final AsyncCompletionCallback<Answer> callback) {
this.cmd = cmd;
this.callback = callback;
this.hostId = hostId;
}
@Override
public void run() {
try {
Answer answer = agentMgr.send(hostId, cmd);
callback.complete(answer);
} catch (Exception e) {
s_logger.debug("send command failed:" + e.toString());
}
}
}
public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback<Answer> callback) {
executor.schedule(new MockRpcCallBack(host.getHostId(), command, callback), 10, TimeUnit.SECONDS);
}
@Override
public Answer sendCommand(HypervisorHostEndPoint host, Command command) {
Answer answer;
try {
answer = agentMgr.send(host.getHostId(), command);
return answer;
} catch (AgentUnavailableException e) {
return null;
} catch (OperationTimedoutException e) {
return null;
}
}
}

View File

@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.HostEndpointRpcServer; import org.apache.cloudstack.storage.HostEndpointRpcServer;
import org.apache.cloudstack.storage.HypervisorHostEndPoint;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageCmd; import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageCmd;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer; import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer;
import org.apache.cloudstack.storage.command.CreateVolumeAnswer; import org.apache.cloudstack.storage.command.CreateVolumeAnswer;
@ -63,7 +64,14 @@ public class MockHypervsiorHostEndPointRpcServer implements HostEndpointRpcServe
} }
} }
public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) {
public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback<Answer> callback) {
executor.schedule(new MockRpcCallBack(command, callback), 10, TimeUnit.SECONDS); executor.schedule(new MockRpcCallBack(command, callback), 10, TimeUnit.SECONDS);
} }
@Override
public Answer sendCommand(HypervisorHostEndPoint host, Command command) {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -158,7 +158,7 @@ public class volumeServiceTest {
HostVO host = new HostVO(UUID.randomUUID().toString()); HostVO host = new HostVO(UUID.randomUUID().toString());
host.setName("devcloud xen host"); host.setName("devcloud xen host");
host.setType(Host.Type.Routing); host.setType(Host.Type.Routing);
host.setPrivateIpAddress("192.168.56.2"); host.setPrivateIpAddress("192.168.56.10");
host.setDataCenterId(dc.getId()); host.setDataCenterId(dc.getId());
host.setVersion("6.0.1"); host.setVersion("6.0.1");
host.setAvailable(true); host.setAvailable(true);
@ -237,7 +237,7 @@ public class volumeServiceTest {
PrimaryDataStoreProvider provider = primaryDataStoreProviderMgr.getDataStoreProvider("default primary data store provider"); PrimaryDataStoreProvider provider = primaryDataStoreProviderMgr.getDataStoreProvider("default primary data store provider");
Map<String, String> params = new HashMap<String, String>(); Map<String, String> params = new HashMap<String, String>();
params.put("url", "nfs://test/test"); params.put("url", "nfs://localhost/primarynfs");
params.put("dcId", dcId.toString()); params.put("dcId", dcId.toString());
params.put("clusterId", clusterId.toString()); params.put("clusterId", clusterId.toString());
params.put("name", "my primary data store"); params.put("name", "my primary data store");

View File

@ -24,5 +24,6 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
public interface HostEndpointRpcServer { public interface HostEndpointRpcServer {
void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback); void sendCommandAsync(HypervisorHostEndPoint ep, final Command command, final AsyncCompletionCallback<Answer> callback);
Answer sendCommand(HypervisorHostEndPoint ep, final Command command);
} }

View File

@ -43,23 +43,21 @@ public class HypervisorHostEndPoint implements EndPoint {
this.hostAddress = hostAddress; this.hostAddress = hostAddress;
} }
public String getHostAddr() {
return this.hostAddress;
}
public long getHostId() {
return this.hostId;
}
@Override @Override
public Answer sendMessage(Command cmd) { public Answer sendMessage(Command cmd) {
Answer answer = null; return rpcServer.sendCommand(this, cmd);
try {
answer = agentMgr.send(hostId, cmd);
} catch (AgentUnavailableException e) {
s_logger.debug("Unable to send command:" + cmd + ", due to: " + e.toString());
} catch (OperationTimedoutException e) {
s_logger.debug("Unable to send command:" + cmd + ", due to: " + e.toString());
} catch (Exception e) {
s_logger.debug("Unable to send command:" + cmd + ", due to: " + e.toString());
}
return answer;
} }
@Override @Override
public void sendMessageAsync(Command cmd, AsyncCompletionCallback<Answer> callback) { public void sendMessageAsync(Command cmd, AsyncCompletionCallback<Answer> callback) {
rpcServer.sendCommandAsync(this.hostAddress, cmd, callback); rpcServer.sendCommandAsync(this, cmd, callback);
} }
} }

View File

@ -20,19 +20,23 @@ package org.apache.cloudstack.storage;
import javax.inject.Inject; import javax.inject.Inject;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.framework.async.AsyncRpcConext;
import org.apache.cloudstack.framework.rpc.RpcCallbackListener; import org.apache.cloudstack.framework.rpc.RpcCallbackListener;
import org.apache.cloudstack.framework.rpc.RpcException; import org.apache.cloudstack.framework.rpc.RpcException;
import org.apache.cloudstack.framework.rpc.RpcProvider; import org.apache.cloudstack.framework.rpc.RpcProvider;
import org.apache.cloudstack.framework.rpc.RpcServiceDispatcher; import org.apache.cloudstack.framework.rpc.RpcServiceDispatcher;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
import com.cloud.utils.exception.CloudRuntimeException;
@Component @Component
public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer { public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
private static final Logger s_logger = Logger.getLogger(HypervsiorHostEndPointRpcServer.class);
private RpcProvider _rpcProvider; private RpcProvider _rpcProvider;
@Inject @Inject
public HypervsiorHostEndPointRpcServer(RpcProvider rpcProvider) { public HypervsiorHostEndPointRpcServer(RpcProvider rpcProvider) {
@ -41,8 +45,8 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
} }
@Override @Override
public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) { public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback<Answer> callback) {
_rpcProvider.newCall(host).addCallbackListener(new RpcCallbackListener<Answer>() { _rpcProvider.newCall(host.getHostAddr()).addCallbackListener(new RpcCallbackListener<Answer>() {
@Override @Override
public void onSuccess(Answer result) { public void onSuccess(Answer result) {
callback.complete(result); callback.complete(result);
@ -55,4 +59,50 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
} }
}).apply(); }).apply();
} }
private class SendCommandContext<T> extends AsyncRpcConext<T> {
private T answer;
public SendCommandContext(AsyncCompletionCallback<T> callback) {
super(callback);
}
public void setAnswer(T answer) {
this.answer = answer;
}
public T getAnswer() {
return this.answer;
}
}
@Override
public Answer sendCommand(HypervisorHostEndPoint host, Command command) {
SendCommandContext<Answer> context = new SendCommandContext<Answer>(null);
AsyncCallbackDispatcher<HypervsiorHostEndPointRpcServer> caller = AsyncCallbackDispatcher.create(this);
caller.setCallback(caller.getTarget().sendCommandCallback(null, null))
.setContext(context);
this.sendCommandAsync(host, command, caller);
synchronized (context) {
try {
context.wait();
} catch (InterruptedException e) {
s_logger.debug(e.toString());
throw new CloudRuntimeException("wait on context is interrupted", e);
}
}
return context.getAnswer();
}
protected Object sendCommandCallback(AsyncCallbackDispatcher<HypervsiorHostEndPointRpcServer> callback, SendCommandContext<Answer> context) {
context.setAnswer((Answer)callback.getResult());
synchronized(context) {
context.notify();
}
return null;
}
} }

View File

@ -0,0 +1,55 @@
/*
* 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.command;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
public class AttachPrimaryDataStoreAnswer extends Answer {
private String uuid;
private long capacity;
private long avail;
public AttachPrimaryDataStoreAnswer(Command cmd) {
super(cmd);
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getUuid() {
return this.uuid;
}
public void setCapacity(long capacity) {
this.capacity = capacity;
}
public long getCapacity() {
return this.capacity;
}
public void setAvailable(long avail) {
this.avail = avail;
}
public long getAvailable() {
return this.avail;
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.command;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import com.cloud.agent.api.Command;
public class AttachPrimaryDataStoreCmd extends Command implements StorageSubSystemCommand {
private final PrimaryDataStoreTO dataStore;
public AttachPrimaryDataStoreCmd(PrimaryDataStoreInfo dataStore) {
this.dataStore = new PrimaryDataStoreTO(dataStore);
}
public PrimaryDataStoreTO getDataStore() {
return this.dataStore;
}
@Override
public boolean executeInSequence() {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -23,12 +23,15 @@ import java.util.Map;
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; 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.storage.EndPoint;
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
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.PrimaryDataStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreVO;
public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle { public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
protected PrimaryDataStoreInfo dataStore; protected PrimaryDataStore dataStore;
protected PrimaryDataStoreDao dataStoreDao; protected PrimaryDataStoreDao dataStoreDao;
public DefaultPrimaryDataStoreLifeCycleImpl(PrimaryDataStoreDao dataStoreDao) { public DefaultPrimaryDataStoreLifeCycleImpl(PrimaryDataStoreDao dataStoreDao) {
this.dataStoreDao = dataStoreDao; this.dataStoreDao = dataStoreDao;
@ -36,7 +39,7 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
@Override @Override
public void setDataStore(PrimaryDataStoreInfo dataStore) { public void setDataStore(PrimaryDataStoreInfo dataStore) {
this.dataStore = dataStore; this.dataStore = (PrimaryDataStore)dataStore;
} }
@Override @Override
@ -50,11 +53,18 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
@Override @Override
public boolean attachCluster(ClusterScope scope) { public boolean attachCluster(ClusterScope scope) {
PrimaryDataStoreVO dataStore = dataStoreDao.findById(this.dataStore.getId()); PrimaryDataStoreVO dataStoreVO = dataStoreDao.findById(this.dataStore.getId());
dataStore.setDataCenterId(scope.getZoneId()); dataStoreVO.setDataCenterId(scope.getZoneId());
dataStore.setPodId(scope.getPodId()); dataStoreVO.setPodId(scope.getPodId());
dataStore.setClusterId(scope.getScopeId()); dataStoreVO.setClusterId(scope.getScopeId());
dataStoreDao.update(this.dataStore.getId(), dataStore); dataStoreVO.setStatus(DataStoreStatus.Up);
dataStoreDao.update(dataStoreVO.getId(), dataStoreVO);
//send down createStoragePool command to all the hosts in the cluster
AttachPrimaryDataStoreCmd cmd = new AttachPrimaryDataStoreCmd(this.dataStore);
for (EndPoint ep : dataStore.getEndPoints()) {
ep.sendMessage(cmd);
}
return false; return false;
} }

View File

@ -5042,7 +5042,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
boolean add = cmd.getAdd(); boolean add = cmd.getAdd();
if( add ) { if( add ) {
try { try {
SR sr = getStorageRepository(conn, pool); SR sr = getStorageRepository(conn, pool.getUuid());
setupHeartbeatSr(conn, sr, false); setupHeartbeatSr(conn, sr, false);
long capacity = sr.getPhysicalSize(conn); long capacity = sr.getPhysicalSize(conn);
long available = capacity - sr.getPhysicalUtilisation(conn); long available = capacity - sr.getPhysicalUtilisation(conn);
@ -5065,7 +5065,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} }
} else { } else {
try { try {
SR sr = getStorageRepository(conn, pool); SR sr = getStorageRepository(conn, pool.getUuid());
String srUuid = sr.getUuid(conn); String srUuid = sr.getUuid(conn);
String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false"); String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false");
if (result == null || !result.split("#")[1].equals("0")) { if (result == null || !result.split("#")[1].equals("0")) {
@ -5330,7 +5330,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
Connection conn = getConnection(); Connection conn = getConnection();
StorageFilerTO poolTO = cmd.getPool(); StorageFilerTO poolTO = cmd.getPool();
try { try {
SR sr = getStorageRepository(conn, poolTO); SR sr = getStorageRepository(conn, poolTO.getUuid());
removeSR(conn, sr); removeSR(conn, sr);
Answer answer = new Answer(cmd, true, "success"); Answer answer = new Answer(cmd, true, "success");
return answer; return answer;
@ -5587,7 +5587,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
DiskProfile dskch = cmd.getDiskCharacteristics(); DiskProfile dskch = cmd.getDiskCharacteristics();
VDI vdi = null; VDI vdi = null;
try { try {
SR poolSr = getStorageRepository(conn, pool); SR poolSr = getStorageRepository(conn, pool.getUuid());
if (cmd.getTemplateUrl() != null) { if (cmd.getTemplateUrl() != null) {
VDI tmpltvdi = null; VDI tmpltvdi = null;
@ -5973,7 +5973,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
String remoteVolumesMountPath = uri.getHost() + ":" + uri.getPath() + "/volumes/"; String remoteVolumesMountPath = uri.getHost() + ":" + uri.getPath() + "/volumes/";
String volumeFolder = String.valueOf(cmd.getVolumeId()) + "/"; String volumeFolder = String.valueOf(cmd.getVolumeId()) + "/";
String mountpoint = remoteVolumesMountPath + volumeFolder; String mountpoint = remoteVolumesMountPath + volumeFolder;
SR primaryStoragePool = getStorageRepository(conn, poolTO); SR primaryStoragePool = getStorageRepository(conn, poolTO.getUuid());
String srUuid = primaryStoragePool.getUuid(conn); String srUuid = primaryStoragePool.getUuid(conn);
if (toSecondaryStorage) { if (toSecondaryStorage) {
// Create the volume folder // Create the volume folder
@ -6685,30 +6685,30 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} }
} }
protected SR getStorageRepository(Connection conn, StorageFilerTO pool) { protected SR getStorageRepository(Connection conn, String uuid) {
Set<SR> srs; Set<SR> srs;
try { try {
srs = SR.getByNameLabel(conn, pool.getUuid()); srs = SR.getByNameLabel(conn, uuid);
} catch (XenAPIException e) { } catch (XenAPIException e) {
throw new CloudRuntimeException("Unable to get SR " + pool.getUuid() + " due to " + e.toString(), e); throw new CloudRuntimeException("Unable to get SR " + uuid + " due to " + e.toString(), e);
} catch (Exception e) { } catch (Exception e) {
throw new CloudRuntimeException("Unable to get SR " + pool.getUuid() + " due to " + e.getMessage(), e); throw new CloudRuntimeException("Unable to get SR " + uuid + " due to " + e.getMessage(), e);
} }
if (srs.size() > 1) { if (srs.size() > 1) {
throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + pool.getUuid()); throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + uuid);
} else if (srs.size() == 1) { } else if (srs.size() == 1) {
SR sr = srs.iterator().next(); SR sr = srs.iterator().next();
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("SR retrieved for " + pool.getId()); s_logger.debug("SR retrieved for " + uuid);
} }
if (checkSR(conn, sr)) { if (checkSR(conn, sr)) {
return sr; return sr;
} }
throw new CloudRuntimeException("SR check failed for storage pool: " + pool.getUuid() + "on host:" + _host.uuid); throw new CloudRuntimeException("SR check failed for storage pool: " + uuid + "on host:" + _host.uuid);
} else { } else {
throw new CloudRuntimeException("Can not see storage pool: " + pool.getUuid() + " from on host:" + _host.uuid); throw new CloudRuntimeException("Can not see storage pool: " + uuid + " from on host:" + _host.uuid);
} }
} }

View File

@ -28,6 +28,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageCmd; import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageCmd;
import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer; import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer;
import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
@ -51,7 +53,10 @@ import org.apache.xmlrpc.XmlRpcException;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.xensource.xenapi.Connection; import com.xensource.xenapi.Connection;
import com.xensource.xenapi.PBD; import com.xensource.xenapi.PBD;
@ -72,11 +77,25 @@ public class XenServerStorageResource {
public Answer handleStorageCommands(StorageSubSystemCommand command) { public Answer handleStorageCommands(StorageSubSystemCommand command) {
if (command instanceof CopyTemplateToPrimaryStorageCmd) { if (command instanceof CopyTemplateToPrimaryStorageCmd) {
return this.execute((CopyTemplateToPrimaryStorageCmd)command); return this.execute((CopyTemplateToPrimaryStorageCmd)command);
} else if (command instanceof AttachPrimaryDataStoreCmd) {
return this.execute((AttachPrimaryDataStoreCmd)command);
} }
return new Answer((Command)command, false, "not implemented yet"); return new Answer((Command)command, false, "not implemented yet");
} }
private long getTemplateSize(String url) { private long getTemplateSize(Connection conn, String url) {
String size = hypervisorResource.callHostPlugin(conn, "storagePlugin", "getTemplateSize", "srcUrl", url);
if (size == "" || size == null) {
throw new CloudRuntimeException("Can't get template size");
}
try {
return Long.parseLong(size);
} catch (NumberFormatException e) {
throw new CloudRuntimeException("Failed to get template lenght", e);
}
/*
HttpHead method = new HttpHead(url); HttpHead method = new HttpHead(url);
DefaultHttpClient client = new DefaultHttpClient(); DefaultHttpClient client = new DefaultHttpClient();
try { try {
@ -93,7 +112,7 @@ public class XenServerStorageResource {
throw new CloudRuntimeException("Failed to get template lenght", e); throw new CloudRuntimeException("Failed to get template lenght", e);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new CloudRuntimeException("Failed to get template lenght", e); throw new CloudRuntimeException("Failed to get template lenght", e);
} }*/
} }
private void downloadHttpToLocalFile(String destFilePath, String url) { private void downloadHttpToLocalFile(String destFilePath, String url) {
@ -143,17 +162,17 @@ public class XenServerStorageResource {
boolean result = false; boolean result = false;
try { try {
Set<SR> srs = SR.getByNameLabel(conn, primaryStoreUuid); SR sr = SR.getByUuid(conn, primaryStoreUuid);
if (srs.size() != 1) { if (sr == null) {
throw new CloudRuntimeException("storage uuid: " + primaryStoreUuid + " is not unique"); throw new CloudRuntimeException("storage uuid: " + primaryStoreUuid + " is not unique");
} }
poolsr = srs.iterator().next(); poolsr = sr;
VDI.Record vdir = new VDI.Record(); VDI.Record vdir = new VDI.Record();
vdir.nameLabel = "Base-Image-" + UUID.randomUUID().toString(); vdir.nameLabel = "Base-Image-" + UUID.randomUUID().toString();
vdir.SR = poolsr; vdir.SR = poolsr;
vdir.type = Types.VdiType.USER; vdir.type = Types.VdiType.USER;
vdir.virtualSize = getTemplateSize(template.getPath()); vdir.virtualSize = getTemplateSize(conn, template.getPath());
vdi = VDI.create(conn, vdir); vdi = VDI.create(conn, vdir);
vdir = vdi.getRecord(conn); vdir = vdi.getRecord(conn);
@ -172,7 +191,7 @@ public class XenServerStorageResource {
String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd"; String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
//download a url into vdipath //download a url into vdipath
//downloadHttpToLocalFile(vdiPath, template.getPath()); //downloadHttpToLocalFile(vdiPath, template.getPath());
hypervisorResource.callHostPlugin(conn, "vmopsStorage", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", template.getPath()); hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", template.getPath());
result = true; result = true;
return new CopyTemplateToPrimaryStorageAnswer(cmd, vdi.getUuid(conn)); return new CopyTemplateToPrimaryStorageAnswer(cmd, vdi.getUuid(conn));
} catch (BadServerResponse e) { } catch (BadServerResponse e) {
@ -199,6 +218,35 @@ public class XenServerStorageResource {
return new Answer(cmd, false, "Failed to download template"); return new Answer(cmd, false, "Failed to download template");
} }
protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
PrimaryDataStoreTO dataStore = cmd.getDataStore();
Connection conn = hypervisorResource.getConnection();
try {
SR sr = hypervisorResource.getStorageRepository(conn, dataStore.getUuid());
hypervisorResource.setupHeartbeatSr(conn, sr, false);
long capacity = sr.getPhysicalSize(conn);
long available = capacity - sr.getPhysicalUtilisation(conn);
if (capacity == -1) {
String msg = "Pool capacity is -1! pool: ";
s_logger.warn(msg);
return new Answer(cmd, false, msg);
}
AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd);
answer.setCapacity(capacity);
answer.setUuid(sr.getUuid(conn));
answer.setAvailable(available);
return answer;
} catch (XenAPIException e) {
String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString();
s_logger.warn(msg, e);
return new Answer(cmd, false, msg);
} catch (Exception e) {
String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage();
s_logger.warn(msg, e);
return new Answer(cmd, false, msg);
}
}
protected Answer execute(CopyTemplateToPrimaryStorageCmd cmd) { protected Answer execute(CopyTemplateToPrimaryStorageCmd cmd) {
ImageOnPrimayDataStoreTO imageTO = cmd.getImage(); ImageOnPrimayDataStoreTO imageTO = cmd.getImage();
TemplateTO template = imageTO.getTemplate(); TemplateTO template = imageTO.getTemplate();

View File

@ -0,0 +1,66 @@
#!/usr/bin/python
# 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.
# This is for test purpose, to test xcp plugin
import sys
import XenAPI
import os.path
import traceback
import socket
def getHost():
hostname = socket.gethostname()
url = "http://localhost"
session = XenAPI.Session(url)
session.xenapi.login_with_password("root", "password")
host = session.xenapi.host
hosts = session.xenapi.host.get_by_name_label(hostname)
if len(hosts) != 1:
print "can't find host:" + hostname
sys.exit(1)
localhost = hosts[0]
return [host, localhost]
def callPlugin(pluginName, func, params):
hostPair = getHost()
host = hostPair[0]
localhost = hostPair[1]
return host.call_plugin(localhost, pluginName, func, params)
def main():
if len(sys.argv) < 3:
print "args: pluginName funcName params"
sys.exit(1)
pluginName = sys.argv[1]
funcName = sys.argv[2]
paramList = sys.argv[3:]
if (len(paramList) % 2) != 0:
print "params must be name/value pair"
sys.exit(2)
params = {}
pos = 0;
for i in range(len(paramList) / 2):
params[str(paramList[pos])] = str(paramList[pos+1])
pos = pos + 2
print "call: " + pluginName + " " + funcName + ", with params: " + str(params)
print "return: " + callPlugin(pluginName, funcName, params)
if __name__ == "__main__":
main()

View File

@ -22,24 +22,23 @@
import os, sys, time import os, sys, time
import XenAPIPlugin import XenAPIPlugin
sys.path.extend(["/opt/xensource/sm/", "/usr/local/sbin/", "/sbin/"]) sys.path.extend(["/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"])
import util
import base64 import base64
import hostvmstats
import socket import socket
import stat import stat
import tempfile import tempfile
import util
import subprocess import subprocess
import zlib import zlib
import urllib2 import urllib2
from util import CommandException import traceback
def echo(fn): def echo(fn):
def wrapped(*v, **k): def wrapped(*v, **k):
name = fn.__name__ name = fn.__name__
util.SMlog("#### VMOPS enter %s ####" % name ) util.SMlog("#### xen plugin enter %s ####" % name )
res = fn(*v, **k) res = fn(*v, **k)
util.SMlog("#### VMOPS exit %s ####" % name ) util.SMlog("#### xen plugin exit %s ####" % name )
return res return res
return wrapped return wrapped
@ -47,10 +46,26 @@ def echo(fn):
def downloadTemplateFromUrl(session, args): def downloadTemplateFromUrl(session, args):
destPath = args["destPath"] destPath = args["destPath"]
srcUrl = args["srcUrl"] srcUrl = args["srcUrl"]
try:
template = urllib2.urlopen(srcUrl) template = urllib2.urlopen(srcUrl)
destFile = open(destPath, "wb") destFile = open(destPath, "wb")
destFile.write(template.read()) destFile.write(template.read())
destFile.close() destFile.close()
return "success"
except:
util.SMlog("exception: " + str(sys.exc_info()))
return ""
@echo
def getTemplateSize(session, args):
srcUrl = args["srcUrl"]
try:
template = urllib2.urlopen(srcUrl)
headers = template.info()
return str(headers["Content-Length"])
except:
return ""
if __name__ == "__main__": if __name__ == "__main__":
XenAPIPlugin.dispatch({"downloadTemplateFromUrl": downloadTemplateFromUrl}) XenAPIPlugin.dispatch({"downloadTemplateFromUrl": downloadTemplateFromUrl
,"getTemplateSize": getTemplateSize
})

View File

@ -64,3 +64,4 @@ cloud-prepare-upgrade.sh=..,0755,/usr/lib/xcp/bin
getRouterStatus.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin getRouterStatus.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin
bumpUpPriority.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin bumpUpPriority.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin
getDomRVersion.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin getDomRVersion.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin
storagePlugin=.,0755,/usr/lib/xcp/plugins