mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
finaly, finish download template to primary storage
This commit is contained in:
parent
1d5019c3d0
commit
ac88c16be6
@ -31,12 +31,14 @@ import com.cloud.agent.Listener;
|
||||
import com.cloud.agent.StartupCommandProcessor;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.SetupCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.manager.AgentAttache;
|
||||
import com.cloud.agent.manager.Commands;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.ConnectionException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.host.HostEnvironment;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status.Event;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
@ -100,6 +102,11 @@ public class DirectAgentManagerSimpleImpl implements AgentManager {
|
||||
} catch (ConfigurationException e) {
|
||||
logger.debug("Failed to load resource:" + e.toString());
|
||||
}
|
||||
HostEnvironment env = new HostEnvironment();
|
||||
SetupCommand cmd = new SetupCommand(env);
|
||||
cmd.setNeedSetup(true);
|
||||
|
||||
resource.executeRequest(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -69,7 +69,7 @@ public class DirectAgentTest {
|
||||
private long dcId;
|
||||
private long clusterId;
|
||||
private long hostId;
|
||||
private String hostGuid = "759ee4c9-a15a-297b-67c6-ac267d8aa429";
|
||||
private String hostGuid = "9d4c9db8-32f7-25c3-0435-eab4bf3adcea";
|
||||
@Before
|
||||
public void setUp() {
|
||||
HostVO host = hostDao.findByGuid(hostGuid);
|
||||
@ -102,7 +102,7 @@ public class DirectAgentTest {
|
||||
host.setName("devcloud xen host");
|
||||
host.setType(Host.Type.Routing);
|
||||
host.setHypervisorType(HypervisorType.XenServer);
|
||||
host.setPrivateIpAddress("192.168.56.2");
|
||||
host.setPrivateIpAddress("192.168.56.10");
|
||||
host.setDataCenterId(dc.getId());
|
||||
host.setVersion("6.0.1");
|
||||
host.setAvailable(true);
|
||||
@ -133,7 +133,7 @@ public class DirectAgentTest {
|
||||
public void testDownloadTemplate() {
|
||||
ImageOnPrimayDataStoreTO image = Mockito.mock(ImageOnPrimayDataStoreTO.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);
|
||||
|
||||
ImageDataStoreTO imageStore = Mockito.mock(ImageDataStoreTO.class);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
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.CopyTemplateToPrimaryStorageAnswer;
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer sendCommand(HypervisorHostEndPoint host, Command command) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ public class volumeServiceTest {
|
||||
HostVO host = new HostVO(UUID.randomUUID().toString());
|
||||
host.setName("devcloud xen host");
|
||||
host.setType(Host.Type.Routing);
|
||||
host.setPrivateIpAddress("192.168.56.2");
|
||||
host.setPrivateIpAddress("192.168.56.10");
|
||||
host.setDataCenterId(dc.getId());
|
||||
host.setVersion("6.0.1");
|
||||
host.setAvailable(true);
|
||||
@ -237,7 +237,7 @@ public class volumeServiceTest {
|
||||
PrimaryDataStoreProvider provider = primaryDataStoreProviderMgr.getDataStoreProvider("default primary data store provider");
|
||||
|
||||
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("clusterId", clusterId.toString());
|
||||
params.put("name", "my primary data store");
|
||||
|
||||
@ -24,5 +24,6 @@ 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);
|
||||
void sendCommandAsync(HypervisorHostEndPoint ep, final Command command, final AsyncCompletionCallback<Answer> callback);
|
||||
Answer sendCommand(HypervisorHostEndPoint ep, final Command command);
|
||||
}
|
||||
|
||||
@ -42,24 +42,22 @@ public class HypervisorHostEndPoint implements EndPoint {
|
||||
this.hostId = hostId;
|
||||
this.hostAddress = hostAddress;
|
||||
}
|
||||
|
||||
public String getHostAddr() {
|
||||
return this.hostAddress;
|
||||
}
|
||||
|
||||
public long getHostId() {
|
||||
return this.hostId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer sendMessage(Command cmd) {
|
||||
Answer answer = null;
|
||||
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;
|
||||
return rpcServer.sendCommand(this, cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessageAsync(Command cmd, AsyncCompletionCallback<Answer> callback) {
|
||||
rpcServer.sendCommandAsync(this.hostAddress, cmd, callback);
|
||||
rpcServer.sendCommandAsync(this, cmd, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,19 +20,23 @@ package org.apache.cloudstack.storage;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
|
||||
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.RpcException;
|
||||
import org.apache.cloudstack.framework.rpc.RpcProvider;
|
||||
import org.apache.cloudstack.framework.rpc.RpcServiceDispatcher;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Component
|
||||
public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(HypervsiorHostEndPointRpcServer.class);
|
||||
private RpcProvider _rpcProvider;
|
||||
@Inject
|
||||
public HypervsiorHostEndPointRpcServer(RpcProvider rpcProvider) {
|
||||
@ -41,8 +45,8 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) {
|
||||
_rpcProvider.newCall(host).addCallbackListener(new RpcCallbackListener<Answer>() {
|
||||
public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback<Answer> callback) {
|
||||
_rpcProvider.newCall(host.getHostAddr()).addCallbackListener(new RpcCallbackListener<Answer>() {
|
||||
@Override
|
||||
public void onSuccess(Answer result) {
|
||||
callback.complete(result);
|
||||
@ -55,4 +59,50 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
|
||||
}
|
||||
}).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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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.PrimaryDataStoreInfo;
|
||||
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.PrimaryDataStore;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreVO;
|
||||
|
||||
public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
|
||||
protected PrimaryDataStoreInfo dataStore;
|
||||
protected PrimaryDataStore dataStore;
|
||||
protected PrimaryDataStoreDao dataStoreDao;
|
||||
public DefaultPrimaryDataStoreLifeCycleImpl(PrimaryDataStoreDao dataStoreDao) {
|
||||
this.dataStoreDao = dataStoreDao;
|
||||
@ -36,7 +39,7 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
|
||||
|
||||
@Override
|
||||
public void setDataStore(PrimaryDataStoreInfo dataStore) {
|
||||
this.dataStore = dataStore;
|
||||
this.dataStore = (PrimaryDataStore)dataStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,11 +53,18 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
|
||||
|
||||
@Override
|
||||
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);
|
||||
PrimaryDataStoreVO dataStoreVO = dataStoreDao.findById(this.dataStore.getId());
|
||||
dataStoreVO.setDataCenterId(scope.getZoneId());
|
||||
dataStoreVO.setPodId(scope.getPodId());
|
||||
dataStoreVO.setClusterId(scope.getScopeId());
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -5042,7 +5042,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
boolean add = cmd.getAdd();
|
||||
if( add ) {
|
||||
try {
|
||||
SR sr = getStorageRepository(conn, pool);
|
||||
SR sr = getStorageRepository(conn, pool.getUuid());
|
||||
setupHeartbeatSr(conn, sr, false);
|
||||
long capacity = sr.getPhysicalSize(conn);
|
||||
long available = capacity - sr.getPhysicalUtilisation(conn);
|
||||
@ -5065,7 +5065,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
SR sr = getStorageRepository(conn, pool);
|
||||
SR sr = getStorageRepository(conn, pool.getUuid());
|
||||
String srUuid = sr.getUuid(conn);
|
||||
String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false");
|
||||
if (result == null || !result.split("#")[1].equals("0")) {
|
||||
@ -5330,7 +5330,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
Connection conn = getConnection();
|
||||
StorageFilerTO poolTO = cmd.getPool();
|
||||
try {
|
||||
SR sr = getStorageRepository(conn, poolTO);
|
||||
SR sr = getStorageRepository(conn, poolTO.getUuid());
|
||||
removeSR(conn, sr);
|
||||
Answer answer = new Answer(cmd, true, "success");
|
||||
return answer;
|
||||
@ -5587,7 +5587,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
DiskProfile dskch = cmd.getDiskCharacteristics();
|
||||
VDI vdi = null;
|
||||
try {
|
||||
SR poolSr = getStorageRepository(conn, pool);
|
||||
SR poolSr = getStorageRepository(conn, pool.getUuid());
|
||||
if (cmd.getTemplateUrl() != null) {
|
||||
VDI tmpltvdi = null;
|
||||
|
||||
@ -5973,7 +5973,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
String remoteVolumesMountPath = uri.getHost() + ":" + uri.getPath() + "/volumes/";
|
||||
String volumeFolder = String.valueOf(cmd.getVolumeId()) + "/";
|
||||
String mountpoint = remoteVolumesMountPath + volumeFolder;
|
||||
SR primaryStoragePool = getStorageRepository(conn, poolTO);
|
||||
SR primaryStoragePool = getStorageRepository(conn, poolTO.getUuid());
|
||||
String srUuid = primaryStoragePool.getUuid(conn);
|
||||
if (toSecondaryStorage) {
|
||||
// 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;
|
||||
try {
|
||||
srs = SR.getByNameLabel(conn, pool.getUuid());
|
||||
srs = SR.getByNameLabel(conn, uuid);
|
||||
} 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) {
|
||||
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) {
|
||||
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) {
|
||||
SR sr = srs.iterator().next();
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("SR retrieved for " + pool.getId());
|
||||
s_logger.debug("SR retrieved for " + uuid);
|
||||
}
|
||||
|
||||
if (checkSR(conn, 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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -28,6 +28,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
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.CopyTemplateToPrimaryStorageAnswer;
|
||||
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.Command;
|
||||
import com.cloud.agent.api.ModifyStoragePoolAnswer;
|
||||
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.xensource.xenapi.Connection;
|
||||
import com.xensource.xenapi.PBD;
|
||||
@ -72,11 +77,25 @@ public class XenServerStorageResource {
|
||||
public Answer handleStorageCommands(StorageSubSystemCommand command) {
|
||||
if (command instanceof CopyTemplateToPrimaryStorageCmd) {
|
||||
return this.execute((CopyTemplateToPrimaryStorageCmd)command);
|
||||
} else if (command instanceof AttachPrimaryDataStoreCmd) {
|
||||
return this.execute((AttachPrimaryDataStoreCmd)command);
|
||||
}
|
||||
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);
|
||||
DefaultHttpClient client = new DefaultHttpClient();
|
||||
try {
|
||||
@ -93,7 +112,7 @@ public class XenServerStorageResource {
|
||||
throw new CloudRuntimeException("Failed to get template lenght", e);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new CloudRuntimeException("Failed to get template lenght", e);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private void downloadHttpToLocalFile(String destFilePath, String url) {
|
||||
@ -143,17 +162,17 @@ public class XenServerStorageResource {
|
||||
boolean result = false;
|
||||
try {
|
||||
|
||||
Set<SR> srs = SR.getByNameLabel(conn, primaryStoreUuid);
|
||||
if (srs.size() != 1) {
|
||||
SR sr = SR.getByUuid(conn, primaryStoreUuid);
|
||||
if (sr == null) {
|
||||
throw new CloudRuntimeException("storage uuid: " + primaryStoreUuid + " is not unique");
|
||||
}
|
||||
poolsr = srs.iterator().next();
|
||||
poolsr = sr;
|
||||
VDI.Record vdir = new VDI.Record();
|
||||
vdir.nameLabel = "Base-Image-" + UUID.randomUUID().toString();
|
||||
vdir.SR = poolsr;
|
||||
vdir.type = Types.VdiType.USER;
|
||||
|
||||
vdir.virtualSize = getTemplateSize(template.getPath());
|
||||
vdir.virtualSize = getTemplateSize(conn, template.getPath());
|
||||
vdi = VDI.create(conn, vdir);
|
||||
|
||||
vdir = vdi.getRecord(conn);
|
||||
@ -172,7 +191,7 @@ public class XenServerStorageResource {
|
||||
String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
|
||||
//download a url into vdipath
|
||||
//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;
|
||||
return new CopyTemplateToPrimaryStorageAnswer(cmd, vdi.getUuid(conn));
|
||||
} catch (BadServerResponse e) {
|
||||
@ -199,6 +218,35 @@ public class XenServerStorageResource {
|
||||
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) {
|
||||
ImageOnPrimayDataStoreTO imageTO = cmd.getImage();
|
||||
TemplateTO template = imageTO.getTemplate();
|
||||
|
||||
66
scripts/vm/hypervisor/xenserver/mockxcpplugin.py
Normal file
66
scripts/vm/hypervisor/xenserver/mockxcpplugin.py
Normal 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()
|
||||
@ -22,24 +22,23 @@
|
||||
|
||||
import os, sys, time
|
||||
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 hostvmstats
|
||||
import socket
|
||||
import stat
|
||||
import tempfile
|
||||
import util
|
||||
import subprocess
|
||||
import zlib
|
||||
import urllib2
|
||||
from util import CommandException
|
||||
import traceback
|
||||
|
||||
def echo(fn):
|
||||
def wrapped(*v, **k):
|
||||
name = fn.__name__
|
||||
util.SMlog("#### VMOPS enter %s ####" % name )
|
||||
util.SMlog("#### xen plugin enter %s ####" % name )
|
||||
res = fn(*v, **k)
|
||||
util.SMlog("#### VMOPS exit %s ####" % name )
|
||||
util.SMlog("#### xen plugin exit %s ####" % name )
|
||||
return res
|
||||
return wrapped
|
||||
|
||||
@ -47,10 +46,26 @@ def echo(fn):
|
||||
def downloadTemplateFromUrl(session, args):
|
||||
destPath = args["destPath"]
|
||||
srcUrl = args["srcUrl"]
|
||||
template = urllib2.urlopen(srcUrl)
|
||||
destFile = open(destPath, "wb")
|
||||
destFile.write(template.read())
|
||||
destFile.close()
|
||||
try:
|
||||
template = urllib2.urlopen(srcUrl)
|
||||
destFile = open(destPath, "wb")
|
||||
destFile.write(template.read())
|
||||
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__":
|
||||
XenAPIPlugin.dispatch({"downloadTemplateFromUrl": downloadTemplateFromUrl})
|
||||
XenAPIPlugin.dispatch({"downloadTemplateFromUrl": downloadTemplateFromUrl
|
||||
,"getTemplateSize": getTemplateSize
|
||||
})
|
||||
|
||||
@ -64,3 +64,4 @@ cloud-prepare-upgrade.sh=..,0755,/usr/lib/xcp/bin
|
||||
getRouterStatus.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
|
||||
storagePlugin=.,0755,/usr/lib/xcp/plugins
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user