mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
refactor kvm/vmware resource code
This commit is contained in:
parent
a83b87b7e5
commit
42e25a22fc
@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
package com.cloud.agent.api.to;
|
||||
|
||||
public enum DataObjectType {
|
||||
VOLUME,
|
||||
@ -16,9 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
package com.cloud.agent.api.to;
|
||||
|
||||
public interface DataTO {
|
||||
public DataObjectType getObjectType();
|
||||
60
api/src/com/cloud/agent/api/to/DiskTO.java
Normal file
60
api/src/com/cloud/agent/api/to/DiskTO.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.cloud.agent.api.to;
|
||||
|
||||
import com.cloud.storage.Volume;
|
||||
|
||||
public class DiskTO {
|
||||
private DataTO data;
|
||||
private Long diskSeq;
|
||||
private Volume.Type type;
|
||||
public DiskTO() {
|
||||
|
||||
}
|
||||
|
||||
public DiskTO(DataTO data, Long diskSeq, Volume.Type type) {
|
||||
this.data = data;
|
||||
this.diskSeq = diskSeq;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public DataTO getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(DataTO data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Long getDiskSeq() {
|
||||
return diskSeq;
|
||||
}
|
||||
|
||||
public void setDiskSeq(Long diskSeq) {
|
||||
this.diskSeq = diskSeq;
|
||||
}
|
||||
|
||||
public Volume.Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Volume.Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@ -57,7 +57,7 @@ public class VirtualMachineTO {
|
||||
Map<String, String> params;
|
||||
String uuid;
|
||||
|
||||
VolumeTO[] disks;
|
||||
DiskTO[] disks;
|
||||
NicTO[] nics;
|
||||
|
||||
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader, String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
|
||||
@ -206,11 +206,11 @@ public class VirtualMachineTO {
|
||||
this.bootupScripts = bootupScripts;
|
||||
}
|
||||
|
||||
public VolumeTO[] getDisks() {
|
||||
public DiskTO[] getDisks() {
|
||||
return disks;
|
||||
}
|
||||
|
||||
public void setDisks(VolumeTO[] disks) {
|
||||
public void setDisks(DiskTO[] disks) {
|
||||
this.disks = disks;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,8 @@ package com.cloud.vm;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
@ -111,11 +113,11 @@ public interface VirtualMachineProfile<T extends VirtualMachine> {
|
||||
|
||||
List<NicProfile> getNics();
|
||||
|
||||
List<VolumeTO> getDisks();
|
||||
List<DiskTO> getDisks();
|
||||
|
||||
void addNic(int index, NicProfile nic);
|
||||
|
||||
void addDisk(int index, VolumeTO disk);
|
||||
void addDisk(int index, DiskTO disk);
|
||||
|
||||
StringBuilder getBootArgsBuilder();
|
||||
|
||||
@ -125,7 +127,7 @@ public interface VirtualMachineProfile<T extends VirtualMachine> {
|
||||
|
||||
void addNic(NicProfile nic);
|
||||
|
||||
void addDisk(VolumeTO disk);
|
||||
void addDisk(DiskTO disk);
|
||||
|
||||
VirtualMachine.Type getType();
|
||||
|
||||
|
||||
@ -20,13 +20,13 @@ package com.cloud.serializer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.transport.ArrayTypeAdaptor;
|
||||
import com.cloud.agent.transport.InterfaceTypeAdaptor;
|
||||
import com.cloud.agent.transport.LoggingExclusionStrategy;
|
||||
|
||||
@ -46,8 +46,6 @@ import java.util.concurrent.Callable;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.DownloadCommand;
|
||||
@ -97,7 +95,9 @@ import com.cloud.agent.api.storage.ListVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.ListVolumeCommand;
|
||||
import com.cloud.agent.api.storage.UploadCommand;
|
||||
import com.cloud.agent.api.storage.ssCommand;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.agent.api.to.S3TO;
|
||||
import com.cloud.agent.api.to.SwiftTO;
|
||||
|
||||
45
core/src/com/cloud/storage/resource/StorageProcessor.java
Normal file
45
core/src/com/cloud/storage/resource/StorageProcessor.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectCommand;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
|
||||
public interface StorageProcessor {
|
||||
public Answer copyTemplateToPrimaryStorage(CopyCommand cmd);
|
||||
public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd);
|
||||
public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd);
|
||||
public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd);
|
||||
public Answer createTemplateFromVolume(CopyCommand cmd);
|
||||
public Answer backupSnasphot(CopyCommand cmd);
|
||||
public Answer attachIso(AttachCommand cmd);
|
||||
public Answer attachVolume(AttachCommand cmd);
|
||||
public Answer dettachIso(DettachCommand cmd);
|
||||
public Answer dettachVolume(DettachCommand cmd);
|
||||
public Answer createVolume(CreateObjectCommand cmd);
|
||||
public Answer createSnapshot(CreateObjectCommand cmd);
|
||||
public Answer deleteVolume(DeleteCommand cmd);
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
||||
public interface StorageSubsystemCommandHandler {
|
||||
public Answer handleStorageCommands(StorageSubSystemCommand command);
|
||||
}
|
||||
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.cloud.storage.resource;
|
||||
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectCommand;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Volume;
|
||||
|
||||
public class StorageSubsystemCommandHandlerBase implements StorageSubsystemCommandHandler {
|
||||
private static final Logger s_logger = Logger.getLogger(StorageSubsystemCommandHandlerBase.class);
|
||||
private StorageProcessor processor;
|
||||
public StorageSubsystemCommandHandlerBase(StorageProcessor processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
@Override
|
||||
public Answer handleStorageCommands(StorageSubSystemCommand command) {
|
||||
if (command instanceof CopyCommand) {
|
||||
return this.execute((CopyCommand)command);
|
||||
} else if (command instanceof CreateObjectCommand) {
|
||||
return execute((CreateObjectCommand) command);
|
||||
} else if (command instanceof DeleteCommand) {
|
||||
return execute((DeleteCommand)command);
|
||||
} else if (command instanceof AttachCommand) {
|
||||
return execute((AttachCommand)command);
|
||||
} else if (command instanceof DettachCommand) {
|
||||
return execute((DettachCommand)command);
|
||||
}
|
||||
return new Answer((Command)command, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
DataStoreTO srcDataStore = srcData.getDataStore();
|
||||
DataStoreTO destDataStore = destData.getDataStore();
|
||||
|
||||
if ((srcData.getObjectType() == DataObjectType.TEMPLATE) && (srcDataStore instanceof NfsTO) && (destData.getDataStore().getRole() == DataStoreRole.Primary)) {
|
||||
//copy template to primary storage
|
||||
return processor.copyTemplateToPrimaryStorage(cmd);
|
||||
} else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
|
||||
//clone template to a volume
|
||||
return processor.cloneVolumeFromBaseTemplate(cmd);
|
||||
} else if (srcData.getObjectType() == DataObjectType.VOLUME && (srcData.getDataStore().getRole() == DataStoreRole.ImageCache || srcDataStore.getRole() == DataStoreRole.Image)) {
|
||||
//copy volume from image cache to primary
|
||||
return processor.copyVolumeFromImageCacheToPrimary(cmd);
|
||||
} else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
|
||||
if (destData.getObjectType() == DataObjectType.VOLUME) {
|
||||
return processor.copyVolumeFromPrimaryToSecondary(cmd);
|
||||
} else if (destData.getObjectType() == DataObjectType.TEMPLATE) {
|
||||
return processor.createTemplateFromVolume(cmd);
|
||||
}
|
||||
} else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
|
||||
return processor.backupSnasphot(cmd);
|
||||
}
|
||||
|
||||
return new Answer(cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
|
||||
protected Answer execute(CreateObjectCommand cmd) {
|
||||
DataTO data = cmd.getData();
|
||||
try {
|
||||
if (data.getObjectType() == DataObjectType.VOLUME) {
|
||||
return processor.createVolume(cmd);
|
||||
} else if (data.getObjectType() == DataObjectType.SNAPSHOT) {
|
||||
return processor.createSnapshot(cmd);
|
||||
}
|
||||
return new CreateObjectAnswer("not supported type");
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString());
|
||||
return new CreateObjectAnswer(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(DeleteCommand cmd) {
|
||||
DataTO data = cmd.getData();
|
||||
Answer answer = null;
|
||||
if (data.getObjectType() == DataObjectType.VOLUME) {
|
||||
answer = processor.deleteVolume(cmd);
|
||||
} else {
|
||||
answer = new Answer(cmd, false, "unsupported type");
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected Answer execute(AttachCommand cmd) {
|
||||
DiskTO disk = cmd.getDisk();
|
||||
if (disk.getType() == Volume.Type.ISO) {
|
||||
return processor.attachIso(cmd);
|
||||
} else {
|
||||
return processor.attachVolume(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(DettachCommand cmd) {
|
||||
DiskTO disk = cmd.getDisk();
|
||||
if (disk.getType() == Volume.Type.ISO) {
|
||||
return processor.dettachIso(cmd);
|
||||
} else {
|
||||
return processor.dettachVolume(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,8 @@
|
||||
package org.apache.cloudstack.engine.subsystem.api.storage;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public interface DataObject {
|
||||
public long getId();
|
||||
|
||||
@ -24,6 +24,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
import org.apache.cloudstack.storage.command.CommandResult;
|
||||
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public interface DataStoreDriver {
|
||||
public String grantAccess(DataObject data, EndPoint ep);
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.to.DiskTO;
|
||||
|
||||
public class AttachAnswer extends Answer {
|
||||
private DiskTO disk;
|
||||
public AttachAnswer() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public AttachAnswer(DiskTO disk) {
|
||||
this.setDisk(disk);
|
||||
}
|
||||
public AttachAnswer(String errMsg) {
|
||||
super(null, false, errMsg);
|
||||
}
|
||||
|
||||
public DiskTO getDisk() {
|
||||
return disk;
|
||||
}
|
||||
|
||||
public void setDisk(DiskTO disk) {
|
||||
this.disk = disk;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
|
||||
public class AttachCommand extends Command implements StorageSubSystemCommand {
|
||||
private DiskTO disk;
|
||||
private String vmName;
|
||||
|
||||
public AttachCommand(DiskTO disk, String vmName) {
|
||||
this.disk = disk;
|
||||
this.vmName = vmName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
public DiskTO getDisk() {
|
||||
return disk;
|
||||
}
|
||||
public void setDisk(DiskTO disk) {
|
||||
this.disk = disk;
|
||||
}
|
||||
public String getVmName() {
|
||||
return vmName;
|
||||
}
|
||||
public void setVmName(String vmName) {
|
||||
this.vmName = vmName;
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,9 +17,9 @@
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public class CopyCmdAnswer extends Answer {
|
||||
private DataTO newData;
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public class CopyCommand extends Command implements StorageSubSystemCommand {
|
||||
private DataTO srcTO;
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public class CreateObjectAnswer extends Answer {
|
||||
private DataTO data;
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public class CreateObjectCommand extends Command implements StorageSubSystemCommand {
|
||||
private DataTO data;
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public class DeleteCommand extends Command implements StorageSubSystemCommand {
|
||||
private DataTO data;
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.to.DiskTO;
|
||||
|
||||
public class DettachAnswer extends Answer {
|
||||
private DiskTO disk;
|
||||
public DettachAnswer() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public DettachAnswer(DiskTO disk) {
|
||||
this.setDisk(disk);
|
||||
}
|
||||
public DettachAnswer(String errMsg) {
|
||||
super(null, false, errMsg);
|
||||
}
|
||||
|
||||
public DiskTO getDisk() {
|
||||
return disk;
|
||||
}
|
||||
|
||||
public void setDisk(DiskTO disk) {
|
||||
this.disk = disk;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
|
||||
public class DettachCommand extends Command implements StorageSubSystemCommand {
|
||||
private DiskTO disk;
|
||||
private String vmName;
|
||||
|
||||
public DettachCommand(DiskTO disk, String vmName) {
|
||||
this.disk = disk;
|
||||
this.vmName = vmName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
public DiskTO getDisk() {
|
||||
return disk;
|
||||
}
|
||||
public void setDisk(DiskTO disk) {
|
||||
this.disk = disk;
|
||||
}
|
||||
public String getVmName() {
|
||||
return vmName;
|
||||
}
|
||||
public void setVmName(String vmName) {
|
||||
this.vmName = vmName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -20,17 +20,26 @@ import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
|
||||
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
|
||||
public class PrimaryDataStoreTO implements DataStoreTO {
|
||||
private final String uuid;
|
||||
private final String name;
|
||||
private String type;
|
||||
private final long id;
|
||||
private StoragePoolType poolType;
|
||||
private String host;
|
||||
private String path;
|
||||
private int port;
|
||||
public PrimaryDataStoreTO(PrimaryDataStoreInfo dataStore) {
|
||||
this.uuid = dataStore.getUuid();
|
||||
this.name = dataStore.getName();
|
||||
// this.type = dataStore.getType();
|
||||
this.id = dataStore.getId();
|
||||
this.setPoolType(dataStore.getPoolType());
|
||||
this.setHost(dataStore.getHostAddress());
|
||||
this.setPath(dataStore.getPath());
|
||||
this.setPort(dataStore.getPort());
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@ -53,4 +62,36 @@ public class PrimaryDataStoreTO implements DataStoreTO {
|
||||
public DataStoreRole getRole() {
|
||||
return DataStoreRole.Primary;
|
||||
}
|
||||
|
||||
public StoragePoolType getPoolType() {
|
||||
return poolType;
|
||||
}
|
||||
|
||||
public void setPoolType(StoragePoolType poolType) {
|
||||
this.poolType = poolType;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package org.apache.cloudstack.storage.to;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
|
||||
public class SnapshotObjectTO implements DataTO {
|
||||
|
||||
@ -16,13 +16,13 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.storage.to;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
||||
import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
|
||||
@ -38,6 +38,7 @@ public class TemplateObjectTO implements DataTO {
|
||||
private String displayText;
|
||||
private DataStoreTO imageDataStore;
|
||||
private String name;
|
||||
private String guestOsType;
|
||||
|
||||
public TemplateObjectTO() {
|
||||
|
||||
@ -151,5 +152,11 @@ public class TemplateObjectTO implements DataTO {
|
||||
this.imageDataStore = imageDataStore;
|
||||
}
|
||||
|
||||
public String getGuestOsType() {
|
||||
return guestOsType;
|
||||
}
|
||||
|
||||
public void setGuestOsType(String guestOsType) {
|
||||
this.guestOsType = guestOsType;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,17 +16,18 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.storage.to;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.storage.Volume;
|
||||
|
||||
public class VolumeObjectTO implements DataTO {
|
||||
private String uuid;
|
||||
private VolumeType volumeType;
|
||||
private Volume.Type volumeType;
|
||||
private DiskFormat diskType;
|
||||
private DataStoreTO dataStore;
|
||||
private String name;
|
||||
@ -35,6 +36,8 @@ public class VolumeObjectTO implements DataTO {
|
||||
private Long volumeId;
|
||||
private String vmName;
|
||||
private long accountId;
|
||||
private String chainInfo;
|
||||
private long id;
|
||||
|
||||
public VolumeObjectTO() {
|
||||
|
||||
@ -52,6 +55,9 @@ public class VolumeObjectTO implements DataTO {
|
||||
this.vmName = volume.getAttachedVmName();
|
||||
this.size = volume.getSize();
|
||||
this.setVolumeId(volume.getId());
|
||||
this.chainInfo = volume.getChainInfo();
|
||||
this.volumeType = volume.getVolumeType();
|
||||
this.setId(volume.getId());
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
@ -62,7 +68,7 @@ public class VolumeObjectTO implements DataTO {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public VolumeType getVolumeType() {
|
||||
public Volume.Type getVolumeType() {
|
||||
return this.volumeType;
|
||||
}
|
||||
|
||||
@ -130,5 +136,21 @@ public class VolumeObjectTO implements DataTO {
|
||||
this.vmName = vmName;
|
||||
}
|
||||
|
||||
public String getChainInfo() {
|
||||
return chainInfo;
|
||||
}
|
||||
|
||||
public void setChainInfo(String chainInfo) {
|
||||
this.chainInfo = chainInfo;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -26,10 +26,8 @@ import javax.inject.Inject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
@ -61,7 +59,9 @@ import com.cloud.agent.api.UpgradeSnapshotCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.agent.api.to.S3TO;
|
||||
import com.cloud.agent.api.to.SwiftTO;
|
||||
|
||||
@ -33,6 +33,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.VMTemplateStoragePoolVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
@ -89,6 +90,16 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
|
||||
}
|
||||
return this.getTemplate(templateId, store);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateInfo getTemplate(long templateId, long zoneId) {
|
||||
TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplateZoneDownloadStatus(templateId, zoneId, VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
|
||||
if (tmplStore != null) {
|
||||
DataStore store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), DataStoreRole.Image);
|
||||
return this.getTemplate(templateId, store);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
@ -24,9 +24,7 @@ import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
|
||||
@ -40,6 +38,8 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
|
||||
@ -22,9 +22,7 @@ import java.util.Date;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
@ -39,6 +37,8 @@ import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
|
||||
@ -18,10 +18,10 @@ package org.apache.cloudstack.storage.datastore;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
@ -42,6 +41,7 @@ import org.apache.cloudstack.storage.db.ObjectInDataStoreVO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.VMTemplateStoragePoolVO;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
|
||||
@ -30,10 +30,10 @@ import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
|
||||
@ -25,7 +25,6 @@ import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
|
||||
@ -46,6 +45,7 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
import org.apache.cloudstack.storage.volume.VolumeObject;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
|
||||
@ -21,9 +21,7 @@ import java.util.Date;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||
@ -36,6 +34,8 @@ import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Volume;
|
||||
|
||||
@ -39,11 +39,11 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -56,11 +56,13 @@ import java.util.regex.Pattern;
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImg;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libvirt.Connect;
|
||||
import org.libvirt.Domain;
|
||||
import org.libvirt.DomainInfo;
|
||||
@ -166,9 +168,13 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||
import com.cloud.agent.api.storage.DestroyCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
||||
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.IpAddressTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
@ -194,11 +200,12 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InputDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.hostNicType;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef;
|
||||
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
|
||||
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
|
||||
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
|
||||
import com.cloud.hypervisor.kvm.storage.KVMStorageProcessor;
|
||||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.Networks.IsolationType;
|
||||
import com.cloud.network.Networks.RouterPrivateIpStrategy;
|
||||
@ -212,14 +219,16 @@ import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.resource.StorageSubsystemCommandHandler;
|
||||
import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
|
||||
import com.cloud.storage.template.Processor;
|
||||
import com.cloud.storage.template.Processor.FormatInfo;
|
||||
import com.cloud.storage.template.QCOW2Processor;
|
||||
import com.cloud.storage.template.TemplateProp;
|
||||
import com.cloud.storage.template.TemplateLocation;
|
||||
import com.cloud.storage.template.TemplateProp;
|
||||
import com.cloud.utils.FileUtil;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.FileUtil;
|
||||
import com.cloud.utils.PropertiesUtil;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
@ -345,7 +354,6 @@ ServerResource {
|
||||
protected String _localStoragePath;
|
||||
protected String _localStorageUUID;
|
||||
private final Map <String, String> _pifs = new HashMap<String, String>();
|
||||
private final Map<String, Map<String, String>> hostNetInfo = new HashMap<String, Map<String, String>>();
|
||||
private final Map<String, vmStats> _vmStats = new ConcurrentHashMap<String, vmStats>();
|
||||
|
||||
protected boolean _disconnected = true;
|
||||
@ -383,6 +391,8 @@ ServerResource {
|
||||
}
|
||||
|
||||
protected BridgeType _bridgeType;
|
||||
|
||||
protected StorageSubsystemCommandHandler storageHandler;
|
||||
|
||||
private String getEndIpFromStartIp(String startIp, int numIps) {
|
||||
String[] tokens = startIp.split("[.]");
|
||||
@ -810,6 +820,10 @@ ServerResource {
|
||||
params.put("libvirt.computing.resource", this);
|
||||
|
||||
configureVifDrivers(params);
|
||||
|
||||
KVMStorageProcessor storageProcessor = new KVMStorageProcessor(this._storagePoolMgr, this);
|
||||
storageProcessor.configure(name, params);
|
||||
storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -958,11 +972,6 @@ ServerResource {
|
||||
|
||||
return pif;
|
||||
}
|
||||
|
||||
private String getOvsPif(String bridge) {
|
||||
String pif = Script.runSimpleBashScript("ovs-vsctl list-ports " + bridge);
|
||||
return pif;
|
||||
}
|
||||
|
||||
private String matchPifFileInDirectory(String bridgeName){
|
||||
File f = new File("/sys/devices/virtual/net/" + bridgeName + "/brif");
|
||||
@ -1203,6 +1212,8 @@ ServerResource {
|
||||
return execute((CheckNetworkCommand) cmd);
|
||||
} else if (cmd instanceof NetworkRulesVmSecondaryIpCommand) {
|
||||
return execute((NetworkRulesVmSecondaryIpCommand) cmd);
|
||||
} else if (cmd instanceof StorageSubSystemCommand) {
|
||||
return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
|
||||
} else {
|
||||
s_logger.warn("Unsupported command ");
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
@ -1496,8 +1507,6 @@ ServerResource {
|
||||
vol.getPoolType(),
|
||||
vol.getPoolUuid());
|
||||
pool.deletePhysicalDisk(vol.getPath());
|
||||
String vmName = cmd.getVmName();
|
||||
String poolPath = pool.getLocalPath();
|
||||
return new Answer(cmd, true, "Success");
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.debug("Failed to delete volume: " + e.toString());
|
||||
@ -1606,7 +1615,6 @@ ServerResource {
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
|
||||
InterfaceDef routerNic = null;
|
||||
|
||||
@ -1621,7 +1629,6 @@ ServerResource {
|
||||
return new SetupGuestNetworkAnswer(cmd, false, "Can not find nic with mac " + nic.getMac() + " for VM " + routerName);
|
||||
}
|
||||
|
||||
String args = "vpc_guestnw.sh " + routerIP + " -C";
|
||||
String dev = "eth" + nic.getDeviceId();
|
||||
String netmask = NetUtils.getSubNet(routerGIP, nic.getNetmask());
|
||||
String result = _virtRouterResource.assignGuestNetwork(dev, routerIP,
|
||||
@ -1640,14 +1647,10 @@ ServerResource {
|
||||
|
||||
private SetNetworkACLAnswer execute(SetNetworkACLCommand cmd) {
|
||||
String[] results = new String[cmd.getRules().length];
|
||||
String callResult;
|
||||
Connect conn;
|
||||
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
|
||||
|
||||
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
String [][] rules = cmd.generateFwRules();
|
||||
String[] aclRules = rules[0];
|
||||
NicTO nic = cmd.getNic();
|
||||
@ -1671,7 +1674,7 @@ ServerResource {
|
||||
}
|
||||
|
||||
return new SetNetworkACLAnswer(cmd, true, results);
|
||||
} catch (LibvirtException e) {
|
||||
} catch (Exception e) {
|
||||
String msg = "SetNetworkACL failed due to " + e.toString();
|
||||
s_logger.error(msg, e);
|
||||
return new SetNetworkACLAnswer(cmd, false, results);
|
||||
@ -1686,7 +1689,6 @@ ServerResource {
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
Integer devNum = 0;
|
||||
String pubVlan = pubIP.getVlanId();
|
||||
List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
|
||||
@ -1733,7 +1735,6 @@ ServerResource {
|
||||
try {
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
IpAddressTO[] ips = cmd.getIpAddresses();
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
Integer devNum = 0;
|
||||
Map<String, Integer> vlanToNicNum = new HashMap<String, Integer>();
|
||||
List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
|
||||
@ -1919,7 +1920,6 @@ ServerResource {
|
||||
Long volumeId = cmd.getVolumeId();
|
||||
String secondaryStoragePoolUrl = cmd.getSecondaryStorageUrl();
|
||||
String snapshotName = cmd.getSnapshotName();
|
||||
String snapshotPath = cmd.getVolumePath();
|
||||
String snapshotDestPath = null;
|
||||
String snapshotRelPath = null;
|
||||
String vmName = cmd.getVmName();
|
||||
@ -2194,7 +2194,6 @@ ServerResource {
|
||||
KVMStoragePool secondaryStorage = null;
|
||||
KVMStoragePool primary = null;
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
String templateFolder = cmd.getAccountId() + File.separator
|
||||
+ cmd.getTemplateId() + File.separator;
|
||||
String templateInstallFolder = "/template/tmpl/" + templateFolder;
|
||||
@ -2290,10 +2289,6 @@ ServerResource {
|
||||
templateInstallFolder + cmd.getUniqueName() + ".qcow2",
|
||||
info.virtualSize, info.size, cmd.getUniqueName(),
|
||||
ImageFormat.QCOW2);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get secondary storage pool: "
|
||||
+ e.toString());
|
||||
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
|
||||
} catch (InternalErrorException e) {
|
||||
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
|
||||
} catch (IOException e) {
|
||||
@ -2372,7 +2367,6 @@ ServerResource {
|
||||
}
|
||||
|
||||
protected Answer execute(ModifyStoragePoolCommand cmd) {
|
||||
String poolType = cmd.getPool().getType().toString();
|
||||
KVMStoragePool storagepool = _storagePoolMgr.createStoragePool(cmd
|
||||
.getPool().getUuid(), cmd.getPool().getHost(),
|
||||
cmd.getPool().getPort(), cmd.getPool().getPath(),
|
||||
@ -2700,8 +2694,8 @@ ServerResource {
|
||||
}
|
||||
|
||||
/* setup disks, e.g for iso */
|
||||
VolumeTO[] volumes = vm.getDisks();
|
||||
for (VolumeTO volume : volumes) {
|
||||
DiskTO[] volumes = vm.getDisks();
|
||||
for (DiskTO volume : volumes) {
|
||||
if (volume.getType() == Volume.Type.ISO) {
|
||||
getVolumePath(conn, volume);
|
||||
}
|
||||
@ -3279,10 +3273,14 @@ ServerResource {
|
||||
}
|
||||
}
|
||||
|
||||
private String getVolumePath(Connect conn, VolumeTO volume)
|
||||
private String getVolumePath(Connect conn, DiskTO volume)
|
||||
throws LibvirtException, URISyntaxException {
|
||||
if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) {
|
||||
String isoPath = volume.getPath();
|
||||
DataTO data = volume.getData();
|
||||
DataStoreTO store = data.getDataStore();
|
||||
|
||||
if (volume.getType() == Volume.Type.ISO && data.getPath() != null) {
|
||||
NfsTO nfsStore = (NfsTO)store;
|
||||
String isoPath = nfsStore.getUrl() + File.separator + data.getPath();
|
||||
int index = isoPath.lastIndexOf("/");
|
||||
String path = isoPath.substring(0, index);
|
||||
String name = isoPath.substring(index + 1);
|
||||
@ -3291,26 +3289,28 @@ ServerResource {
|
||||
KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name);
|
||||
return isoVol.getPath();
|
||||
} else {
|
||||
return volume.getPath();
|
||||
return data.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
protected void createVbd(Connect conn, VirtualMachineTO vmSpec,
|
||||
String vmName, LibvirtVMDef vm) throws InternalErrorException,
|
||||
LibvirtException, URISyntaxException {
|
||||
List<VolumeTO> disks = Arrays.asList(vmSpec.getDisks());
|
||||
Collections.sort(disks, new Comparator<VolumeTO>() {
|
||||
List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
|
||||
Collections.sort(disks, new Comparator<DiskTO>() {
|
||||
@Override
|
||||
public int compare(VolumeTO arg0, VolumeTO arg1) {
|
||||
return arg0.getDeviceId() > arg1.getDeviceId() ? 1 : -1;
|
||||
public int compare(DiskTO arg0, DiskTO arg1) {
|
||||
return arg0.getDiskSeq() > arg1.getDiskSeq() ? 1 : -1;
|
||||
}
|
||||
});
|
||||
|
||||
for (VolumeTO volume : disks) {
|
||||
for (DiskTO volume : disks) {
|
||||
KVMPhysicalDisk physicalDisk = null;
|
||||
KVMStoragePool pool = null;
|
||||
if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) {
|
||||
String volPath = volume.getPath();
|
||||
DataTO data = volume.getData();
|
||||
if (volume.getType() == Volume.Type.ISO && data.getPath() != null) {
|
||||
NfsTO nfsStore = (NfsTO)data.getDataStore();
|
||||
String volPath = nfsStore.getUrl() + File.separator + data.getPath();
|
||||
int index = volPath.lastIndexOf("/");
|
||||
String volDir = volPath.substring(0, index);
|
||||
String volName = volPath.substring(index + 1);
|
||||
@ -3318,10 +3318,11 @@ ServerResource {
|
||||
getStoragePoolByURI(volDir);
|
||||
physicalDisk = secondaryStorage.getPhysicalDisk(volName);
|
||||
} else if (volume.getType() != Volume.Type.ISO) {
|
||||
PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
|
||||
pool = _storagePoolMgr.getStoragePool(
|
||||
volume.getPoolType(),
|
||||
volume.getPoolUuid());
|
||||
physicalDisk = pool.getPhysicalDisk(volume.getPath());
|
||||
store.getPoolType(),
|
||||
store.getUuid());
|
||||
physicalDisk = pool.getPhysicalDisk(data.getPath());
|
||||
}
|
||||
|
||||
String volPath = null;
|
||||
@ -3339,7 +3340,7 @@ ServerResource {
|
||||
disk.defISODisk(volPath);
|
||||
}
|
||||
} else {
|
||||
int devId = (int) volume.getDeviceId();
|
||||
int devId = volume.getDiskSeq().intValue();
|
||||
|
||||
if (pool.getType() == StoragePoolType.RBD) {
|
||||
/*
|
||||
@ -3379,12 +3380,14 @@ ServerResource {
|
||||
|
||||
// For LXC, find and add the root filesystem
|
||||
if (HypervisorType.LXC.toString().toLowerCase().equals(vm.getHvsType())) {
|
||||
for (VolumeTO volume : disks) {
|
||||
for (DiskTO volume : disks) {
|
||||
if (volume.getType() == Volume.Type.ROOT) {
|
||||
DataTO data = volume.getData();
|
||||
PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
|
||||
KVMStoragePool pool = _storagePoolMgr.getStoragePool(
|
||||
volume.getPoolType(),
|
||||
volume.getPoolUuid());
|
||||
KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(volume.getPath());
|
||||
store.getPoolType(),
|
||||
store.getUuid());
|
||||
KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(data.getPath());
|
||||
FilesystemDef rootFs = new FilesystemDef(physicalDisk.getPath(), "/");
|
||||
vm.getDevices().addDevice(rootFs);
|
||||
break;
|
||||
@ -3394,16 +3397,6 @@ ServerResource {
|
||||
|
||||
}
|
||||
|
||||
private VolumeTO getVolume(VirtualMachineTO vmSpec, Volume.Type type) {
|
||||
VolumeTO volumes[] = vmSpec.getDisks();
|
||||
for (VolumeTO volume : volumes) {
|
||||
if (volume.getType() == type) {
|
||||
return volume;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void createVif(LibvirtVMDef vm, NicTO nic)
|
||||
throws InternalErrorException, LibvirtException {
|
||||
vm.getDevices().addDevice(
|
||||
@ -3432,7 +3425,7 @@ ServerResource {
|
||||
return new CheckSshAnswer(cmd);
|
||||
}
|
||||
|
||||
private boolean cleanupDisk(Connect conn, DiskDef disk) {
|
||||
public boolean cleanupDisk(Connect conn, DiskDef disk) {
|
||||
// need to umount secondary storage
|
||||
String path = disk.getDiskPath();
|
||||
String poolUuid = null;
|
||||
@ -4237,28 +4230,6 @@ ServerResource {
|
||||
return parser.getEmulator();
|
||||
}
|
||||
|
||||
private String getGuestType(Connect conn, String vmName) {
|
||||
LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
|
||||
Domain dm = null;
|
||||
try {
|
||||
dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName
|
||||
.getBytes()));
|
||||
String xmlDesc = dm.getXMLDesc(0);
|
||||
parser.parseDomainXML(xmlDesc);
|
||||
return parser.getDescription();
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.trace("Ignoring libvirt error.", e);
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
if (dm != null) {
|
||||
dm.free();
|
||||
}
|
||||
} catch (LibvirtException l) {
|
||||
s_logger.trace("Ignoring libvirt error.", l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isGuestPVEnabled(String guestOS) {
|
||||
if (guestOS == null) {
|
||||
@ -4296,14 +4267,6 @@ ServerResource {
|
||||
}
|
||||
}
|
||||
|
||||
private InterfaceDef.nicModel getGuestNicModel(String guestOSType) {
|
||||
if (isGuestPVEnabled(guestOSType)) {
|
||||
return InterfaceDef.nicModel.VIRTIO;
|
||||
} else {
|
||||
return InterfaceDef.nicModel.E1000;
|
||||
}
|
||||
}
|
||||
|
||||
private DiskDef.diskBus getGuestDiskModel(String guestOSType) {
|
||||
if (isGuestPVEnabled(guestOSType)) {
|
||||
return DiskDef.diskBus.VIRTIO;
|
||||
@ -4337,7 +4300,7 @@ ServerResource {
|
||||
}
|
||||
}
|
||||
|
||||
private Domain getDomain(Connect conn, String vmName)
|
||||
public Domain getDomain(Connect conn, String vmName)
|
||||
throws LibvirtException {
|
||||
return conn
|
||||
.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes()));
|
||||
@ -4366,7 +4329,7 @@ ServerResource {
|
||||
}
|
||||
}
|
||||
|
||||
protected List<DiskDef> getDisks(Connect conn, String vmName) {
|
||||
public List<DiskDef> getDisks(Connect conn, String vmName) {
|
||||
LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
|
||||
Domain dm = null;
|
||||
try {
|
||||
@ -4396,38 +4359,7 @@ ServerResource {
|
||||
return command.execute();
|
||||
}
|
||||
|
||||
private String executeBashScript(String script, OutputInterpreter parser) {
|
||||
Script command = new Script("/bin/bash", _timeout, s_logger);
|
||||
command.add("-c");
|
||||
command.add(script);
|
||||
return command.execute(parser);
|
||||
}
|
||||
|
||||
private void deletExitingLinkLocalRoutTable(String linkLocalBr) {
|
||||
Script command = new Script("/bin/bash", _timeout);
|
||||
command.add("-c");
|
||||
command.add("ip route | grep " + NetUtils.getLinkLocalCIDR());
|
||||
OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
|
||||
String result = command.execute(parser);
|
||||
boolean foundLinkLocalBr = false;
|
||||
if (result == null && parser.getLines() != null) {
|
||||
String[] lines = parser.getLines().split("\\n");
|
||||
for (String line : lines) {
|
||||
String[] tokens = line.split(" ");
|
||||
if (!tokens[2].equalsIgnoreCase(linkLocalBr)) {
|
||||
Script.runSimpleBashScript("ip route del "
|
||||
+ NetUtils.getLinkLocalCIDR());
|
||||
} else {
|
||||
foundLinkLocalBr = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundLinkLocalBr) {
|
||||
Script.runSimpleBashScript("ip route add "
|
||||
+ NetUtils.getLinkLocalCIDR() + " dev " + linkLocalBr
|
||||
+ " src " + NetUtils.getLinkLocalGateway());
|
||||
}
|
||||
}
|
||||
|
||||
private class vmStats {
|
||||
long _usedTime;
|
||||
|
||||
@ -354,7 +354,7 @@ public class LibvirtVMDef {
|
||||
}
|
||||
|
||||
public static class DiskDef {
|
||||
enum deviceType {
|
||||
public enum deviceType {
|
||||
FLOPPY("floppy"), DISK("disk"), CDROM("cdrom");
|
||||
String _type;
|
||||
|
||||
@ -396,7 +396,7 @@ public class LibvirtVMDef {
|
||||
}
|
||||
}
|
||||
|
||||
enum diskBus {
|
||||
public enum diskBus {
|
||||
IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML(
|
||||
"uml"), FDC("fdc");
|
||||
String _bus;
|
||||
@ -411,7 +411,7 @@ public class LibvirtVMDef {
|
||||
}
|
||||
}
|
||||
|
||||
enum diskFmtType {
|
||||
public enum diskFmtType {
|
||||
RAW("raw"), QCOW2("qcow2");
|
||||
String _fmtType;
|
||||
|
||||
|
||||
@ -0,0 +1,879 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.cloud.hypervisor.kvm.storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectCommand;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachAnswer;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImg;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImgException;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
||||
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libvirt.Connect;
|
||||
import org.libvirt.Domain;
|
||||
import org.libvirt.DomainInfo;
|
||||
import org.libvirt.DomainSnapshot;
|
||||
import org.libvirt.LibvirtException;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.AttachVolumeAnswer;
|
||||
import com.cloud.agent.api.BackupSnapshotAnswer;
|
||||
import com.cloud.agent.api.ManageSnapshotAnswer;
|
||||
import com.cloud.agent.api.ManageSnapshotCommand;
|
||||
import com.cloud.agent.api.storage.CreateAnswer;
|
||||
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtConnection;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtDomainXMLParser;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef;
|
||||
import com.cloud.storage.JavaStorageLayer;
|
||||
import com.cloud.storage.StorageLayer;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.resource.StorageProcessor;
|
||||
import com.cloud.storage.template.Processor;
|
||||
import com.cloud.storage.template.QCOW2Processor;
|
||||
import com.cloud.storage.template.TemplateLocation;
|
||||
import com.cloud.storage.template.Processor.FormatInfo;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
|
||||
public class KVMStorageProcessor implements StorageProcessor {
|
||||
private static final Logger s_logger = Logger.getLogger(KVMStorageProcessor.class);
|
||||
private KVMStoragePoolManager storagePoolMgr;
|
||||
private LibvirtComputingResource resource;
|
||||
private StorageLayer storageLayer;
|
||||
private String _createTmplPath;
|
||||
private String _manageSnapshotPath;
|
||||
private int _cmdsTimeout;
|
||||
public KVMStorageProcessor(KVMStoragePoolManager storagePoolMgr, LibvirtComputingResource resource) {
|
||||
this.storagePoolMgr = storagePoolMgr;
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
protected String getDefaultStorageScriptsDir() {
|
||||
return "scripts/storage/qcow2";
|
||||
}
|
||||
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
storageLayer = new JavaStorageLayer();
|
||||
storageLayer.configure("StorageLayer", params);
|
||||
|
||||
String storageScriptsDir = (String) params.get("storage.scripts.dir");
|
||||
if (storageScriptsDir == null) {
|
||||
storageScriptsDir = getDefaultStorageScriptsDir();
|
||||
}
|
||||
|
||||
_createTmplPath = Script
|
||||
.findScript(storageScriptsDir, "createtmplt.sh");
|
||||
if (_createTmplPath == null) {
|
||||
throw new ConfigurationException(
|
||||
"Unable to find the createtmplt.sh");
|
||||
}
|
||||
|
||||
_manageSnapshotPath = Script.findScript(storageScriptsDir,
|
||||
"managesnapshot.sh");
|
||||
if (_manageSnapshotPath == null) {
|
||||
throw new ConfigurationException(
|
||||
"Unable to find the managesnapshot.sh");
|
||||
}
|
||||
|
||||
String value = (String) params.get("cmds.timeout");
|
||||
_cmdsTimeout = NumbersUtil.parseInt(value, 7200) * 1000;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
TemplateObjectTO template = (TemplateObjectTO)srcData;
|
||||
DataStoreTO imageStore = template.getDataStore();
|
||||
VolumeObjectTO volume = (VolumeObjectTO)destData;
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
|
||||
|
||||
if (!(imageStore instanceof NfsTO)) {
|
||||
return new CopyCmdAnswer("unsupported protocol");
|
||||
}
|
||||
|
||||
NfsTO nfsImageStore = (NfsTO)imageStore;
|
||||
String tmplturl = nfsImageStore.getUrl() + File.separator + template.getPath();
|
||||
int index = tmplturl.lastIndexOf("/");
|
||||
String mountpoint = tmplturl.substring(0, index);
|
||||
String tmpltname = null;
|
||||
if (index < tmplturl.length() - 1) {
|
||||
tmpltname = tmplturl.substring(index + 1);
|
||||
}
|
||||
|
||||
KVMPhysicalDisk tmplVol = null;
|
||||
KVMStoragePool secondaryPool = null;
|
||||
try {
|
||||
secondaryPool = storagePoolMgr.getStoragePoolByURI(mountpoint);
|
||||
|
||||
/* Get template vol */
|
||||
if (tmpltname == null) {
|
||||
secondaryPool.refresh();
|
||||
List<KVMPhysicalDisk> disks = secondaryPool.listPhysicalDisks();
|
||||
if (disks == null || disks.isEmpty()) {
|
||||
return new PrimaryStorageDownloadAnswer(
|
||||
"Failed to get volumes from pool: "
|
||||
+ secondaryPool.getUuid());
|
||||
}
|
||||
for (KVMPhysicalDisk disk : disks) {
|
||||
if (disk.getName().endsWith("qcow2")) {
|
||||
tmplVol = disk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tmplVol == null) {
|
||||
return new PrimaryStorageDownloadAnswer(
|
||||
"Failed to get template from pool: "
|
||||
+ secondaryPool.getUuid());
|
||||
}
|
||||
} else {
|
||||
tmplVol = secondaryPool.getPhysicalDisk(tmpltname);
|
||||
}
|
||||
|
||||
/* Copy volume to primary storage */
|
||||
KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(
|
||||
tmplVol, UUID.randomUUID().toString(), primaryPool);
|
||||
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(primaryVol.getName());
|
||||
newVol.setSize(primaryVol.getSize());
|
||||
return new CopyCmdAnswer(newVol);
|
||||
} catch (CloudRuntimeException e) {
|
||||
return new CopyCmdAnswer(e.toString());
|
||||
} finally {
|
||||
if (secondaryPool != null) {
|
||||
secondaryPool.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is much like PrimaryStorageDownloadCommand, but keeping it separate
|
||||
private KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool) {
|
||||
int index = templateUrl.lastIndexOf("/");
|
||||
String mountpoint = templateUrl.substring(0, index);
|
||||
String templateName = null;
|
||||
if (index < templateUrl.length() - 1) {
|
||||
templateName = templateUrl.substring(index + 1);
|
||||
}
|
||||
|
||||
KVMPhysicalDisk templateVol = null;
|
||||
KVMStoragePool secondaryPool = null;
|
||||
try {
|
||||
secondaryPool = storagePoolMgr.getStoragePoolByURI(mountpoint);
|
||||
/* Get template vol */
|
||||
if (templateName == null) {
|
||||
secondaryPool.refresh();
|
||||
List<KVMPhysicalDisk> disks = secondaryPool.listPhysicalDisks();
|
||||
if (disks == null || disks.isEmpty()) {
|
||||
s_logger.error("Failed to get volumes from pool: " + secondaryPool.getUuid());
|
||||
return null;
|
||||
}
|
||||
for (KVMPhysicalDisk disk : disks) {
|
||||
if (disk.getName().endsWith("qcow2")) {
|
||||
templateVol = disk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (templateVol == null) {
|
||||
s_logger.error("Failed to get template from pool: " + secondaryPool.getUuid());
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
templateVol = secondaryPool.getPhysicalDisk(templateName);
|
||||
}
|
||||
|
||||
/* Copy volume to primary storage */
|
||||
|
||||
KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), primaryPool);
|
||||
return primaryVol;
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.error("Failed to download template to primary storage",e);
|
||||
return null;
|
||||
} finally {
|
||||
if (secondaryPool != null) {
|
||||
secondaryPool.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
TemplateObjectTO template = (TemplateObjectTO)srcData;
|
||||
DataStoreTO imageStore = template.getDataStore();
|
||||
VolumeObjectTO volume = (VolumeObjectTO)destData;
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
|
||||
KVMPhysicalDisk BaseVol = null;
|
||||
KVMStoragePool primaryPool = null;
|
||||
KVMPhysicalDisk vol = null;
|
||||
|
||||
try {
|
||||
primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
|
||||
String templatePath = null;
|
||||
if (imageStore instanceof NfsTO) {
|
||||
NfsTO nfsImageStore = (NfsTO)imageStore;
|
||||
templatePath = nfsImageStore.getUrl();
|
||||
} else {
|
||||
s_logger.debug("Failed to create volume: ");
|
||||
return new CopyCmdAnswer("Unsupported protocol");
|
||||
}
|
||||
|
||||
if(primaryPool.getType() == StoragePoolType.CLVM) {
|
||||
vol = templateToPrimaryDownload(templatePath, primaryPool);
|
||||
} else {
|
||||
BaseVol = primaryPool.getPhysicalDisk(templatePath);
|
||||
vol = storagePoolMgr.createDiskFromTemplate(BaseVol, UUID
|
||||
.randomUUID().toString(), primaryPool);
|
||||
}
|
||||
if (vol == null) {
|
||||
return new CopyCmdAnswer(
|
||||
" Can't create storage volume on storage pool");
|
||||
}
|
||||
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(vol.getName());
|
||||
newVol.setSize(vol.getSize());
|
||||
|
||||
return new CopyCmdAnswer(newVol);
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.debug("Failed to create volume: " + e.toString());
|
||||
return new CopyCmdAnswer(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer createTemplateFromVolume(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
TemplateObjectTO template = (TemplateObjectTO)srcData;
|
||||
DataStoreTO imageStore = template.getDataStore();
|
||||
VolumeObjectTO volume = (VolumeObjectTO)destData;
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
|
||||
|
||||
if (!(imageStore instanceof NfsTO)) {
|
||||
return new CopyCmdAnswer("unsupported protocol");
|
||||
}
|
||||
NfsTO nfsImageStore = (NfsTO)imageStore;
|
||||
|
||||
KVMStoragePool secondaryStorage = null;
|
||||
KVMStoragePool primary = null;
|
||||
try {
|
||||
String templateFolder = template.getPath();
|
||||
|
||||
secondaryStorage = storagePoolMgr.getStoragePoolByURI(
|
||||
nfsImageStore.getUrl());
|
||||
|
||||
try {
|
||||
primary = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
} catch (CloudRuntimeException e) {
|
||||
if (e.getMessage().contains("not found")) {
|
||||
primary = storagePoolMgr.createStoragePool(primaryStore.getUuid(),
|
||||
primaryStore.getHost(), primaryStore.getPort(),
|
||||
primaryStore.getPath(), null,
|
||||
primaryStore.getPoolType());
|
||||
} else {
|
||||
return new CopyCmdAnswer(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
KVMPhysicalDisk disk = primary.getPhysicalDisk(volume.getPath());
|
||||
String tmpltPath = secondaryStorage.getLocalPath() + File.separator
|
||||
+ templateFolder;
|
||||
this.storageLayer.mkdirs(tmpltPath);
|
||||
String templateName = UUID.randomUUID().toString();
|
||||
|
||||
if (primary.getType() != StoragePoolType.RBD) {
|
||||
Script command = new Script(_createTmplPath, wait, s_logger);
|
||||
command.add("-f", disk.getPath());
|
||||
command.add("-t", tmpltPath);
|
||||
command.add("-n", templateName + ".qcow2");
|
||||
|
||||
String result = command.execute();
|
||||
|
||||
if (result != null) {
|
||||
s_logger.debug("failed to create template: " + result);
|
||||
return new CopyCmdAnswer(result);
|
||||
}
|
||||
} else {
|
||||
s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + templateName);
|
||||
|
||||
QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(),
|
||||
primary.getSourcePort(),
|
||||
primary.getAuthUserName(),
|
||||
primary.getAuthSecret(),
|
||||
disk.getPath()));
|
||||
srcFile.setFormat(PhysicalDiskFormat.RAW);
|
||||
|
||||
QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + templateName + ".qcow2");
|
||||
destFile.setFormat(PhysicalDiskFormat.QCOW2);
|
||||
|
||||
QemuImg q = new QemuImg();
|
||||
try {
|
||||
q.convert(srcFile, destFile);
|
||||
} catch (QemuImgException e) {
|
||||
s_logger.error("Failed to create new template while converting "
|
||||
+ srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage());
|
||||
}
|
||||
|
||||
File templateProp = new File(tmpltPath + "/template.properties");
|
||||
if (!templateProp.exists()) {
|
||||
templateProp.createNewFile();
|
||||
}
|
||||
|
||||
String templateContent = "filename=" + templateName + ".qcow2" + System.getProperty("line.separator");
|
||||
|
||||
DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy");
|
||||
Date date = new Date();
|
||||
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
|
||||
|
||||
FileOutputStream templFo = new FileOutputStream(templateProp);
|
||||
templFo.write(templateContent.getBytes());
|
||||
templFo.flush();
|
||||
templFo.close();
|
||||
}
|
||||
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put(StorageLayer.InstanceConfigKey, this.storageLayer);
|
||||
Processor qcow2Processor = new QCOW2Processor();
|
||||
|
||||
qcow2Processor.configure("QCOW2 Processor", params);
|
||||
|
||||
FormatInfo info = qcow2Processor.process(tmpltPath, null,
|
||||
templateName);
|
||||
|
||||
TemplateLocation loc = new TemplateLocation(this.storageLayer, tmpltPath);
|
||||
loc.create(1, true, templateName);
|
||||
loc.addFormat(info);
|
||||
loc.save();
|
||||
|
||||
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||
newTemplate.setPath(templateFolder + templateName + ".qcow2");
|
||||
return new CopyCmdAnswer(newTemplate);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to create template from volume: " + e.toString());
|
||||
return new CopyCmdAnswer(e.toString());
|
||||
} finally {
|
||||
if (secondaryStorage != null) {
|
||||
secondaryStorage.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer backupSnasphot(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData;
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)snapshot.getDataStore();
|
||||
SnapshotObjectTO destSnapshot = (SnapshotObjectTO)destData;
|
||||
DataStoreTO imageStore = destData.getDataStore();
|
||||
|
||||
if (!(imageStore instanceof NfsTO)) {
|
||||
return new CopyCmdAnswer("unsupported protocol");
|
||||
}
|
||||
NfsTO nfsImageStore = (NfsTO)imageStore;
|
||||
|
||||
String secondaryStoragePoolUrl = nfsImageStore.getUrl();
|
||||
//NOTE: snapshot name is encoded in snapshot path
|
||||
int index = snapshot.getPath().lastIndexOf("/");
|
||||
|
||||
String snapshotName = snapshot.getPath().substring(index + 1);
|
||||
String volumePath = snapshot.getVolume().getPath();
|
||||
String snapshotDestPath = null;
|
||||
String snapshotRelPath = null;
|
||||
String vmName = snapshot.getVmName();
|
||||
KVMStoragePool secondaryStoragePool = null;
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
|
||||
secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(
|
||||
secondaryStoragePoolUrl);
|
||||
|
||||
String ssPmountPath = secondaryStoragePool.getLocalPath();
|
||||
snapshotRelPath = destSnapshot.getPath();
|
||||
|
||||
snapshotDestPath = ssPmountPath + File.separator + snapshotRelPath;
|
||||
KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
KVMPhysicalDisk snapshotDisk = primaryPool.getPhysicalDisk(volumePath);
|
||||
Script command = new Script(_manageSnapshotPath, _cmdsTimeout,
|
||||
s_logger);
|
||||
command.add("-b", snapshotDisk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
command.add("-p", snapshotDestPath);
|
||||
command.add("-t", snapshotName);
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.debug("Failed to backup snaptshot: " + result);
|
||||
return new CopyCmdAnswer(result);
|
||||
}
|
||||
/* Delete the snapshot on primary */
|
||||
|
||||
DomainInfo.DomainState state = null;
|
||||
Domain vm = null;
|
||||
if (vmName != null) {
|
||||
try {
|
||||
vm = this.resource.getDomain(conn, vmName);
|
||||
state = vm.getInfo().state;
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.trace("Ignoring libvirt error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
KVMStoragePool primaryStorage = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING
|
||||
&& !primaryStorage.isExternalSnapshot()) {
|
||||
DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
|
||||
snap.delete(0);
|
||||
|
||||
/*
|
||||
* libvirt on RHEL6 doesn't handle resume event emitted from
|
||||
* qemu
|
||||
*/
|
||||
vm = this.resource.getDomain(conn, vmName);
|
||||
state = vm.getInfo().state;
|
||||
if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
|
||||
vm.resume();
|
||||
}
|
||||
} else {
|
||||
command = new Script(_manageSnapshotPath, _cmdsTimeout,
|
||||
s_logger);
|
||||
command.add("-d", snapshotDisk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.debug("Failed to backup snapshot: " + result);
|
||||
return new CopyCmdAnswer(
|
||||
"Failed to backup snapshot: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
|
||||
newSnapshot.setPath(snapshotRelPath
|
||||
+ File.separator + snapshotName);
|
||||
return new CopyCmdAnswer(newSnapshot);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to backup snapshot: " + e.toString());
|
||||
return new CopyCmdAnswer(e.toString());
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.debug("Failed to backup snapshot: " + e.toString());
|
||||
return new CopyCmdAnswer(e.toString());
|
||||
} finally {
|
||||
if (secondaryStoragePool != null) {
|
||||
secondaryStoragePool.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized String attachOrDetachISO(Connect conn,
|
||||
String vmName, String isoPath, boolean isAttach)
|
||||
throws LibvirtException, URISyntaxException, InternalErrorException {
|
||||
String isoXml = null;
|
||||
if (isoPath != null && isAttach) {
|
||||
int index = isoPath.lastIndexOf("/");
|
||||
String path = isoPath.substring(0, index);
|
||||
String name = isoPath.substring(index + 1);
|
||||
KVMStoragePool secondaryPool = storagePoolMgr.getStoragePoolByURI(
|
||||
path);
|
||||
KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name);
|
||||
isoPath = isoVol.getPath();
|
||||
|
||||
DiskDef iso = new DiskDef();
|
||||
iso.defISODisk(isoPath);
|
||||
isoXml = iso.toString();
|
||||
} else {
|
||||
DiskDef iso = new DiskDef();
|
||||
iso.defISODisk(null);
|
||||
isoXml = iso.toString();
|
||||
}
|
||||
|
||||
List<DiskDef> disks = this.resource.getDisks(conn, vmName);
|
||||
String result = attachOrDetachDevice(conn, true, vmName, isoXml);
|
||||
if (result == null && !isAttach) {
|
||||
for (DiskDef disk : disks) {
|
||||
if (disk.getDeviceType() == DiskDef.deviceType.CDROM) {
|
||||
this.resource.cleanupDisk(conn, disk);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public Answer attachIso(AttachCommand cmd) {
|
||||
DiskTO disk = cmd.getDisk();
|
||||
TemplateObjectTO isoTO = (TemplateObjectTO)disk.getData();
|
||||
DataStoreTO store = isoTO.getDataStore();
|
||||
if (!(store instanceof NfsTO)) {
|
||||
return new AttachAnswer("unsupported protocol");
|
||||
}
|
||||
NfsTO nfsStore = (NfsTO)store;
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
attachOrDetachISO(conn, cmd.getVmName(), nfsStore.getUrl() + File.separator + isoTO.getPath(),
|
||||
true);
|
||||
} catch (LibvirtException e) {
|
||||
return new Answer(cmd, false, e.toString());
|
||||
} catch (URISyntaxException e) {
|
||||
return new Answer(cmd, false, e.toString());
|
||||
} catch (InternalErrorException e) {
|
||||
return new Answer(cmd, false, e.toString());
|
||||
}
|
||||
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
protected synchronized String attachOrDetachDevice(Connect conn,
|
||||
boolean attach, String vmName, String xml) throws LibvirtException,
|
||||
InternalErrorException {
|
||||
Domain dm = null;
|
||||
try {
|
||||
dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes((vmName
|
||||
.getBytes())));
|
||||
|
||||
if (attach) {
|
||||
s_logger.debug("Attaching device: " + xml);
|
||||
dm.attachDevice(xml);
|
||||
} else {
|
||||
s_logger.debug("Detaching device: " + xml);
|
||||
dm.detachDevice(xml);
|
||||
}
|
||||
} catch (LibvirtException e) {
|
||||
if (attach) {
|
||||
s_logger.warn("Failed to attach device to " + vmName + ": "
|
||||
+ e.getMessage());
|
||||
} else {
|
||||
s_logger.warn("Failed to detach device from " + vmName + ": "
|
||||
+ e.getMessage());
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
if (dm != null) {
|
||||
try {
|
||||
dm.free();
|
||||
} catch (LibvirtException l) {
|
||||
s_logger.trace("Ignoring libvirt error.", l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected synchronized String attachOrDetachDisk(Connect conn,
|
||||
boolean attach, String vmName, KVMPhysicalDisk attachingDisk,
|
||||
int devId) throws LibvirtException, InternalErrorException {
|
||||
List<DiskDef> disks = null;
|
||||
Domain dm = null;
|
||||
DiskDef diskdef = null;
|
||||
try {
|
||||
if (!attach) {
|
||||
dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName
|
||||
.getBytes()));
|
||||
LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
|
||||
String xml = dm.getXMLDesc(0);
|
||||
parser.parseDomainXML(xml);
|
||||
disks = parser.getDisks();
|
||||
|
||||
for (DiskDef disk : disks) {
|
||||
String file = disk.getDiskPath();
|
||||
if (file != null
|
||||
&& file.equalsIgnoreCase(attachingDisk.getPath())) {
|
||||
diskdef = disk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (diskdef == null) {
|
||||
throw new InternalErrorException("disk: "
|
||||
+ attachingDisk.getPath()
|
||||
+ " is not attached before");
|
||||
}
|
||||
} else {
|
||||
diskdef = new DiskDef();
|
||||
if (attachingDisk.getFormat() == PhysicalDiskFormat.QCOW2) {
|
||||
diskdef.defFileBasedDisk(attachingDisk.getPath(), devId,
|
||||
DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2);
|
||||
} else if (attachingDisk.getFormat() == PhysicalDiskFormat.RAW) {
|
||||
diskdef.defBlockBasedDisk(attachingDisk.getPath(), devId,
|
||||
DiskDef.diskBus.VIRTIO);
|
||||
}
|
||||
}
|
||||
|
||||
String xml = diskdef.toString();
|
||||
return attachOrDetachDevice(conn, attach, vmName, xml);
|
||||
} finally {
|
||||
if (dm != null) {
|
||||
dm.free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer attachVolume(AttachCommand cmd) {
|
||||
DiskTO disk = cmd.getDisk();
|
||||
VolumeObjectTO vol = (VolumeObjectTO)disk.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore();
|
||||
String vmName = vol.getVmName();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
KVMStoragePool primary = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath());
|
||||
attachOrDetachDisk(conn, true, vmName, phyDisk,
|
||||
disk.getDiskSeq().intValue());
|
||||
|
||||
return new AttachAnswer(disk);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
|
||||
return new AttachAnswer(e.toString());
|
||||
} catch (InternalErrorException e) {
|
||||
s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
|
||||
return new AttachAnswer(e.toString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer dettachIso(DettachCommand cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer dettachVolume(DettachCommand cmd) {
|
||||
DiskTO disk = cmd.getDisk();
|
||||
VolumeObjectTO vol = (VolumeObjectTO)disk.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore();
|
||||
String vmName = vol.getVmName();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
KVMStoragePool primary = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
|
||||
KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath());
|
||||
attachOrDetachDisk(conn, false, vmName, phyDisk,
|
||||
disk.getDiskSeq().intValue());
|
||||
|
||||
return new DettachAnswer(disk);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
|
||||
return new DettachAnswer(e.toString());
|
||||
} catch (InternalErrorException e) {
|
||||
s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
|
||||
return new DettachAnswer(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer createVolume(CreateObjectCommand cmd) {
|
||||
VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
|
||||
|
||||
KVMStoragePool primaryPool = null;
|
||||
KVMPhysicalDisk vol = null;
|
||||
long disksize;
|
||||
try {
|
||||
primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
disksize = volume.getSize();
|
||||
|
||||
vol = primaryPool.createPhysicalDisk(UUID.randomUUID()
|
||||
.toString(), disksize);
|
||||
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setPath(vol.getName());
|
||||
|
||||
return new CreateObjectAnswer(newVol);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to create volume: " + e.toString());
|
||||
return new CreateObjectAnswer(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected static MessageFormat SnapshotXML = new MessageFormat(
|
||||
" <domainsnapshot>" + " <name>{0}</name>" + " <domain>"
|
||||
+ " <uuid>{1}</uuid>" + " </domain>"
|
||||
+ " </domainsnapshot>");
|
||||
|
||||
@Override
|
||||
public Answer createSnapshot(CreateObjectCommand cmd) {
|
||||
VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
|
||||
String snapshotName = UUID.randomUUID().toString();
|
||||
String vmName = volume.getVmName();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
DomainInfo.DomainState state = null;
|
||||
Domain vm = null;
|
||||
if (vmName != null) {
|
||||
try {
|
||||
vm = this.resource.getDomain(conn, vmName);
|
||||
state = vm.getInfo().state;
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.trace("Ignoring libvirt error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
|
||||
if (primaryPool.getType() == StoragePoolType.RBD) {
|
||||
s_logger.debug("Snapshots are not supported on RBD volumes");
|
||||
return new CreateObjectAnswer(
|
||||
"Snapshots are not supported on RBD volumes");
|
||||
}
|
||||
|
||||
KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(volume.getPath());
|
||||
if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING
|
||||
&& !primaryPool.isExternalSnapshot()) {
|
||||
String vmUuid = vm.getUUIDString();
|
||||
Object[] args = new Object[] { snapshotName, vmUuid };
|
||||
String snapshot = SnapshotXML.format(args);
|
||||
s_logger.debug(snapshot);
|
||||
|
||||
vm.snapshotCreateXML(snapshot);
|
||||
/*
|
||||
* libvirt on RHEL6 doesn't handle resume event emitted from
|
||||
* qemu
|
||||
*/
|
||||
vm = this.resource.getDomain(conn, vmName);
|
||||
state = vm.getInfo().state;
|
||||
if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
|
||||
vm.resume();
|
||||
}
|
||||
} else {
|
||||
|
||||
/* VM is not running, create a snapshot by ourself */
|
||||
final Script command = new Script(_manageSnapshotPath,
|
||||
this._cmdsTimeout, s_logger);
|
||||
command.add("-c", disk.getPath());
|
||||
command.add("-n", snapshotName);
|
||||
String result = command.execute();
|
||||
if (result != null) {
|
||||
s_logger.debug("Failed to manage snapshot: " + result);
|
||||
return new CreateObjectAnswer(
|
||||
"Failed to manage snapshot: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
|
||||
//NOTE: sort of hack, we'd better just put snapshtoName
|
||||
newSnapshot.setPath(disk.getPath() + File.separator + snapshotName);
|
||||
return new CreateObjectAnswer(newSnapshot);
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to manage snapshot: " + e.toString());
|
||||
return new CreateObjectAnswer(
|
||||
"Failed to manage snapshot: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer deleteVolume(DeleteCommand cmd) {
|
||||
VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore();
|
||||
try {
|
||||
KVMStoragePool pool = storagePoolMgr.getStoragePool(
|
||||
primaryStore.getPoolType(),
|
||||
primaryStore.getUuid());
|
||||
try {
|
||||
pool.getPhysicalDisk(vol.getPath());
|
||||
} catch(Exception e) {
|
||||
s_logger.debug("can't find volume: " + vol.getPath() + ", return true");
|
||||
return new Answer(null);
|
||||
}
|
||||
pool.deletePhysicalDisk(vol.getPath());
|
||||
return new Answer(null);
|
||||
} catch (CloudRuntimeException e) {
|
||||
s_logger.debug("Failed to delete volume: " + e.toString());
|
||||
return new Answer(null, false, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.cloud.hypervisor.kvm.storage;
|
||||
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectCommand;
|
||||
import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
|
||||
public class KVMStorageResource {
|
||||
private LibvirtComputingResource resource;
|
||||
public KVMStorageResource(LibvirtComputingResource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public Answer handleStorageCommands(StorageSubSystemCommand command) {
|
||||
if (command instanceof CopyCommand) {
|
||||
return this.execute((CopyCommand)command);
|
||||
} else if (command instanceof AttachPrimaryDataStoreCmd) {
|
||||
return this.execute((AttachPrimaryDataStoreCmd)command);
|
||||
} else if (command instanceof CreatePrimaryDataStoreCmd) {
|
||||
return execute((CreatePrimaryDataStoreCmd) command);
|
||||
} else if (command instanceof CreateObjectCommand) {
|
||||
return execute((CreateObjectCommand) command);
|
||||
} else if (command instanceof DeleteCommand) {
|
||||
return execute((DeleteCommand)command);
|
||||
} else if (command instanceof AttachCommand) {
|
||||
return execute((AttachCommand)command);
|
||||
} else if (command instanceof DettachCommand) {
|
||||
return execute((DettachCommand)command);
|
||||
}
|
||||
return new Answer((Command)command, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(CopyCommand cmd) {
|
||||
return new Answer((Command)cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
|
||||
return new Answer((Command)cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(CreatePrimaryDataStoreCmd cmd) {
|
||||
return new Answer((Command)cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(CreateObjectCommand cmd) {
|
||||
return new Answer((Command)cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(DeleteCommand cmd) {
|
||||
return new Answer((Command)cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(AttachCommand cmd) {
|
||||
return new Answer((Command)cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
protected Answer execute(DettachCommand cmd) {
|
||||
return new Answer((Command)cmd, false, "not implemented yet");
|
||||
}
|
||||
|
||||
}
|
||||
@ -39,6 +39,11 @@ import java.util.UUID;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.NDC;
|
||||
|
||||
@ -162,8 +167,11 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.FirewallRuleTO;
|
||||
import com.cloud.agent.api.to.IpAddressTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.PortForwardingRuleTO;
|
||||
import com.cloud.agent.api.to.StaticNatRuleTO;
|
||||
@ -177,6 +185,7 @@ import com.cloud.host.Host.Type;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
|
||||
import com.cloud.hypervisor.vmware.mo.ClusterMO;
|
||||
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
|
||||
import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO;
|
||||
@ -210,8 +219,12 @@ import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.resource.StoragePoolResource;
|
||||
import com.cloud.storage.resource.StorageSubsystemCommandHandler;
|
||||
import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
|
||||
import com.cloud.storage.resource.VmwareStorageProcessor;
|
||||
import com.cloud.storage.template.TemplateProp;
|
||||
import com.cloud.utils.DateUtil;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.db.DB;
|
||||
@ -313,6 +326,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
protected Gson _gson;
|
||||
|
||||
protected volatile long _cmdSequence = 1;
|
||||
|
||||
protected StorageSubsystemCommandHandler storageHandler;
|
||||
|
||||
protected static HashMap<VirtualMachinePowerState, State> s_statesTable;
|
||||
static {
|
||||
@ -321,6 +336,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
s_statesTable.put(VirtualMachinePowerState.POWERED_OFF, State.Stopped);
|
||||
s_statesTable.put(VirtualMachinePowerState.SUSPENDED, State.Stopped);
|
||||
}
|
||||
|
||||
public Gson getGson() {
|
||||
return this._gson;
|
||||
}
|
||||
|
||||
public VmwareResource() {
|
||||
_gson = GsonHelper.getGsonLogger();
|
||||
@ -472,6 +491,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
answer = execute((CheckS2SVpnConnectionsCommand) cmd);
|
||||
} else if (clz == ResizeVolumeCommand.class) {
|
||||
return execute((ResizeVolumeCommand) cmd);
|
||||
} else if (clz == StorageSubSystemCommand.class) {
|
||||
return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
|
||||
} else {
|
||||
answer = Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
@ -2026,14 +2047,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
return new CheckSshAnswer(cmd);
|
||||
}
|
||||
|
||||
private VolumeTO[] validateDisks(VolumeTO[] disks) {
|
||||
List<VolumeTO> validatedDisks = new ArrayList<VolumeTO>();
|
||||
private DiskTO[] validateDisks(DiskTO[] disks) {
|
||||
List<DiskTO> validatedDisks = new ArrayList<DiskTO>();
|
||||
|
||||
for (VolumeTO vol : disks) {
|
||||
if (vol.getPoolUuid() != null && !vol.getPoolUuid().isEmpty()) {
|
||||
validatedDisks.add(vol);
|
||||
} else if (vol.getPoolType() == StoragePoolType.ISO && (vol.getPath() != null && !vol.getPath().isEmpty())) {
|
||||
validatedDisks.add(vol);
|
||||
for (DiskTO vol : disks) {
|
||||
if (vol.getType() != Volume.Type.ISO) {
|
||||
VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
|
||||
if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) {
|
||||
validatedDisks.add(vol);
|
||||
}
|
||||
} else if (vol.getType() == Volume.Type.ISO) {
|
||||
TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData();
|
||||
if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) {
|
||||
validatedDisks.add(vol);
|
||||
}
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Drop invalid disk option, volumeTO: " + _gson.toJson(vol));
|
||||
@ -2041,7 +2069,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
}
|
||||
|
||||
return validatedDisks.toArray(new VolumeTO[0]);
|
||||
return validatedDisks.toArray(new DiskTO[0]);
|
||||
}
|
||||
|
||||
protected StartAnswer execute(StartCommand cmd) {
|
||||
@ -2068,7 +2096,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
s_logger.debug("VM " + vmName + " will be started with NIC device type: " + nicDeviceType);
|
||||
|
||||
VmwareHypervisorHost hyperHost = getHyperHost(context);
|
||||
VolumeTO[] disks = validateDisks(vmSpec.getDisks());
|
||||
DiskTO[] disks = validateDisks(vmSpec.getDisks());
|
||||
assert (disks.length > 0);
|
||||
NicTO[] nics = vmSpec.getNics();
|
||||
|
||||
@ -2105,9 +2133,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
} else {
|
||||
int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024));
|
||||
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
|
||||
for (VolumeTO vol : disks) {
|
||||
for (DiskTO vol : disks) {
|
||||
if (vol.getType() == Volume.Type.ROOT) {
|
||||
rootDiskDataStoreDetails = dataStoresDetails.get(vol.getPoolUuid());
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore();
|
||||
rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2126,12 +2155,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
|
||||
int totalChangeDevices = disks.length + nics.length;
|
||||
VolumeTO volIso = null;
|
||||
DiskTO volIso = null;
|
||||
if (vmSpec.getType() != VirtualMachine.Type.User) {
|
||||
// system VM needs a patch ISO
|
||||
totalChangeDevices++;
|
||||
} else {
|
||||
for (VolumeTO vol : disks) {
|
||||
for (DiskTO vol : disks) {
|
||||
if (vol.getType() == Volume.Type.ISO) {
|
||||
volIso = vol;
|
||||
break;
|
||||
@ -2188,23 +2217,35 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
i++;
|
||||
} else {
|
||||
// we will always plugin a CDROM device
|
||||
if (volIso != null && volIso.getPath() != null && !volIso.getPath().isEmpty()) {
|
||||
Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, volIso.getPath());
|
||||
assert (isoDatastoreInfo != null);
|
||||
assert (isoDatastoreInfo.second() != null);
|
||||
|
||||
if (volIso != null) {
|
||||
TemplateObjectTO iso = (TemplateObjectTO)volIso.getData();
|
||||
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, i, i + 1);
|
||||
deviceConfigSpecArray[i].setDevice(isoInfo.first());
|
||||
if (isoInfo.second()) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
|
||||
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
} else {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
|
||||
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
|
||||
}
|
||||
if (iso.getPath() != null && !iso.getPath().isEmpty()) {
|
||||
DataStoreTO imageStore = iso.getDataStore();
|
||||
if (!(imageStore instanceof NfsTO)) {
|
||||
s_logger.debug("unsupported protocol");
|
||||
throw new Exception("unsupported protocol");
|
||||
}
|
||||
NfsTO nfsImageStore = (NfsTO)imageStore;
|
||||
String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
|
||||
Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath);
|
||||
assert (isoDatastoreInfo != null);
|
||||
assert (isoDatastoreInfo.second() != null);
|
||||
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, i, i + 1);
|
||||
deviceConfigSpecArray[i].setDevice(isoInfo.first());
|
||||
if (isoInfo.second()) {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
|
||||
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
|
||||
} else {
|
||||
if(s_logger.isDebugEnabled())
|
||||
s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
|
||||
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, i, i + 1);
|
||||
@ -2224,7 +2265,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
i++;
|
||||
}
|
||||
|
||||
for (VolumeTO vol : sortVolumesByDeviceId(disks)) {
|
||||
for (DiskTO vol : sortVolumesByDeviceId(disks)) {
|
||||
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
|
||||
|
||||
if (vol.getType() == Volume.Type.ISO) {
|
||||
@ -2247,11 +2288,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
|
||||
if (vol.getType() != Volume.Type.ISO) {
|
||||
Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(vol.getPoolUuid());
|
||||
VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
|
||||
Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid());
|
||||
assert (volumeDsDetails != null);
|
||||
VirtualDevice device;
|
||||
datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), vol.getPath());
|
||||
String chainInfo = vol.getChainInfo();
|
||||
datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), volumeTO.getPath());
|
||||
String chainInfo = volumeTO.getChainInfo();
|
||||
|
||||
if (chainInfo != null && !chainInfo.isEmpty()) {
|
||||
String[] diskChain = _gson.fromJson(chainInfo, String[].class);
|
||||
@ -2424,19 +2467,19 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
return listForSort.toArray(new NicTO[0]);
|
||||
}
|
||||
|
||||
private VolumeTO[] sortVolumesByDeviceId(VolumeTO[] volumes) {
|
||||
private DiskTO[] sortVolumesByDeviceId(DiskTO[] volumes) {
|
||||
|
||||
List<VolumeTO> listForSort = new ArrayList<VolumeTO>();
|
||||
for (VolumeTO vol : volumes) {
|
||||
List<DiskTO> listForSort = new ArrayList<DiskTO>();
|
||||
for (DiskTO vol : volumes) {
|
||||
listForSort.add(vol);
|
||||
}
|
||||
Collections.sort(listForSort, new Comparator<VolumeTO>() {
|
||||
Collections.sort(listForSort, new Comparator<DiskTO>() {
|
||||
|
||||
@Override
|
||||
public int compare(VolumeTO arg0, VolumeTO arg1) {
|
||||
if (arg0.getDeviceId() < arg1.getDeviceId()) {
|
||||
public int compare(DiskTO arg0, DiskTO arg1) {
|
||||
if (arg0.getDiskSeq() < arg1.getDiskSeq()) {
|
||||
return -1;
|
||||
} else if (arg0.getDeviceId() == arg1.getDeviceId()) {
|
||||
} else if (arg0.getDiskSeq() == arg1.getDiskSeq()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2444,16 +2487,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
});
|
||||
|
||||
return listForSort.toArray(new VolumeTO[0]);
|
||||
return listForSort.toArray(new DiskTO[0]);
|
||||
}
|
||||
|
||||
private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, VolumeTO[] disks) throws Exception {
|
||||
private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, DiskTO[] disks) throws Exception {
|
||||
HashMap<String ,Pair<ManagedObjectReference, DatastoreMO>> poolMors = new HashMap<String, Pair<ManagedObjectReference, DatastoreMO>>();
|
||||
|
||||
assert (hyperHost != null) && (context != null);
|
||||
for (VolumeTO vol : disks) {
|
||||
for (DiskTO vol : disks) {
|
||||
if (vol.getType() != Volume.Type.ISO) {
|
||||
String poolUuid = vol.getPoolUuid();
|
||||
VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
|
||||
String poolUuid = primaryStore.getUuid();
|
||||
if(poolMors.get(poolUuid) == null) {
|
||||
ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
|
||||
if (morDataStore == null) {
|
||||
@ -2461,7 +2506,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
poolMors.put(vol.getPoolUuid(), new Pair<ManagedObjectReference, DatastoreMO> (morDataStore, new DatastoreMO(context, morDataStore)));
|
||||
poolMors.put(poolUuid, new Pair<ManagedObjectReference, DatastoreMO> (morDataStore, new DatastoreMO(context, morDataStore)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3306,7 +3351,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
|
||||
public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
|
||||
String storeName = getSecondaryDatastoreUUID(storeUrl);
|
||||
URI uri = new URI(storeUrl);
|
||||
|
||||
@ -3670,8 +3715,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(DestroyCommand cmd) {
|
||||
|
||||
public Answer execute(DeleteCommand cmd) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
|
||||
}
|
||||
@ -3691,11 +3736,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
try {
|
||||
VmwareContext context = getServiceContext();
|
||||
VmwareHypervisorHost hyperHost = getHyperHost(context);
|
||||
VolumeTO vol = cmd.getVolume();
|
||||
VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
|
||||
PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore();
|
||||
|
||||
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, vol.getPoolUuid());
|
||||
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
|
||||
if (morDs == null) {
|
||||
String msg = "Unable to find datastore based on volume mount point " + cmd.getVolume().getMountPoint();
|
||||
String msg = "Unable to find datastore based on volume mount point " + store.getPath();
|
||||
s_logger.error(msg);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
@ -3706,8 +3752,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
|
||||
ClusterMO clusterMo = new ClusterMO(context, morCluster);
|
||||
|
||||
if (cmd.getVolume().getType() == Volume.Type.ROOT) {
|
||||
String vmName = cmd.getVmName();
|
||||
if (vol.getVolumeType() == Volume.Type.ROOT) {
|
||||
String vmName = vol.getVmName();
|
||||
if (vmName != null) {
|
||||
VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName);
|
||||
if (vmMo != null) {
|
||||
@ -3734,20 +3780,20 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
|
||||
if (s_logger.isInfoEnabled())
|
||||
s_logger.info("Destroy volume by original name: " + cmd.getVolume().getPath() + ".vmdk");
|
||||
dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
|
||||
s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
|
||||
dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
|
||||
|
||||
// root volume may be created via linked-clone, delete the delta disk as well
|
||||
if (_fullCloneFlag) {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
|
||||
s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
|
||||
}
|
||||
dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
|
||||
dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
|
||||
} else {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-delta.vmdk");
|
||||
s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk");
|
||||
}
|
||||
dsMo.deleteFile(cmd.getVolume().getPath() + "-delta.vmdk", morDc, true);
|
||||
dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true);
|
||||
}
|
||||
return new Answer(cmd, true, "Success");
|
||||
}
|
||||
@ -3757,17 +3803,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
} else {
|
||||
// evitTemplate will be converted into DestroyCommand, test if we are running in this case
|
||||
VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(cmd.getVolume().getPath());
|
||||
VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vol.getPath());
|
||||
if (vmMo != null) {
|
||||
if (s_logger.isInfoEnabled())
|
||||
s_logger.info("Destroy template volume " + cmd.getVolume().getPath());
|
||||
s_logger.info("Destroy template volume " + vol.getPath());
|
||||
|
||||
vmMo.destroy();
|
||||
return new Answer(cmd, true, "Success");
|
||||
}
|
||||
}
|
||||
|
||||
String chainInfo = cmd.getVolume().getChainInfo();
|
||||
String chainInfo = vol.getChainInfo();
|
||||
if (chainInfo != null && !chainInfo.isEmpty()) {
|
||||
s_logger.info("Destroy volume by chain info: " + chainInfo);
|
||||
String[] diskChain = _gson.fromJson(chainInfo, String[].class);
|
||||
@ -3783,23 +3829,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name");
|
||||
}
|
||||
dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
|
||||
dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
|
||||
s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
|
||||
}
|
||||
dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
|
||||
dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
|
||||
}
|
||||
} else {
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Destroy volume by original name: " + cmd.getVolume().getPath() + ".vmdk");
|
||||
s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
|
||||
}
|
||||
dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
|
||||
dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
|
||||
|
||||
if (s_logger.isInfoEnabled()) {
|
||||
s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
|
||||
s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
|
||||
}
|
||||
dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
|
||||
dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
|
||||
}
|
||||
|
||||
return new Answer(cmd, true, "Success");
|
||||
@ -3815,7 +3861,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupNetwork(HostMO hostMo, NetworkDetails netDetails) {
|
||||
public void cleanupNetwork(HostMO hostMo, NetworkDetails netDetails) {
|
||||
// we will no longer cleanup VLAN networks in order to support native VMware HA
|
||||
/*
|
||||
* assert(netDetails.getName() != null); try { synchronized(this) { NetworkMO networkMo = new
|
||||
@ -4857,7 +4903,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
return s_statesTable.get(powerState);
|
||||
}
|
||||
|
||||
private static State getVmState(VirtualMachineMO vmMo) throws Exception {
|
||||
public static State getVmState(VirtualMachineMO vmMo) throws Exception {
|
||||
VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo();
|
||||
return convertState(runtimeInfo.getPowerState());
|
||||
}
|
||||
@ -4991,6 +5037,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
} else {
|
||||
_fullCloneFlag = false;
|
||||
}
|
||||
value = (String)params.get("scripts.timeout");
|
||||
int timeout = NumbersUtil.parseInt(value, 1440) * 1000;
|
||||
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
|
||||
VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, this._fullCloneFlag, (VmwareStorageMount)mgr,
|
||||
timeout, this, this._shutdown_waitMs
|
||||
);
|
||||
storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -5010,15 +5063,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
return true;
|
||||
}
|
||||
|
||||
private VmwareContext getServiceContext() {
|
||||
public VmwareContext getServiceContext() {
|
||||
return getServiceContext(null);
|
||||
}
|
||||
|
||||
private void invalidateServiceContext() {
|
||||
public void invalidateServiceContext() {
|
||||
invalidateServiceContext(null);
|
||||
}
|
||||
|
||||
private VmwareHypervisorHost getHyperHost(VmwareContext context) {
|
||||
public VmwareHypervisorHost getHyperHost(VmwareContext context) {
|
||||
return getHyperHost(context, null);
|
||||
}
|
||||
|
||||
@ -5115,4 +5168,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer execute(DestroyCommand cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ package com.cloud.storage.resource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
@ -29,6 +30,7 @@ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageManagerImpl;
|
||||
import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
|
||||
@ -51,6 +53,7 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
||||
private final VmwareStorageManager _storageMgr;
|
||||
|
||||
private final Gson _gson;
|
||||
private StorageSubsystemCommandHandler storageSubsystemHandler;
|
||||
|
||||
/*
|
||||
private Map<String, HostMO> _activeHosts = new HashMap<String, HostMO>();
|
||||
@ -60,6 +63,11 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
||||
_resource = resource;
|
||||
_storageMgr = new VmwareStorageManagerImpl(this);
|
||||
_gson = GsonHelper.getGsonLogger();
|
||||
|
||||
VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, true, (VmwareStorageMount)this,
|
||||
null, null, null
|
||||
);
|
||||
storageSubsystemHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,6 +85,8 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
|
||||
answer = execute((CopyVolumeCommand)cmd);
|
||||
} else if(cmd instanceof CreateVolumeFromSnapshotCommand) {
|
||||
answer = execute((CreateVolumeFromSnapshotCommand)cmd);
|
||||
} else if (cmd instanceof StorageSubSystemCommand) {
|
||||
answer = storageSubsystemHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
|
||||
} else {
|
||||
answer = _resource.defaultAction(cmd);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -58,6 +58,8 @@ import com.cloud.agent.api.to.*;
|
||||
import com.cloud.network.rules.FirewallRule;
|
||||
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
import org.w3c.dom.Document;
|
||||
@ -234,6 +236,8 @@ import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.resource.StorageSubsystemCommandHandler;
|
||||
import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
|
||||
import com.cloud.storage.template.TemplateProp;
|
||||
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
@ -334,7 +338,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
protected boolean _canBridgeFirewall = false;
|
||||
protected boolean _isOvs = false;
|
||||
protected List<VIF> _tmpDom0Vif = new ArrayList<VIF>();
|
||||
protected XenServerStorageResource storageResource;
|
||||
protected StorageSubsystemCommandHandler storageHandler;
|
||||
protected int _maxNics = 7;
|
||||
|
||||
public enum SRType {
|
||||
@ -594,7 +598,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
} else if (clazz == CheckS2SVpnConnectionsCommand.class) {
|
||||
return execute((CheckS2SVpnConnectionsCommand) cmd);
|
||||
} else if (cmd instanceof StorageSubSystemCommand) {
|
||||
return this.storageResource.handleStorageCommands((StorageSubSystemCommand)cmd);
|
||||
return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
|
||||
} else if (clazz == CreateVMSnapshotCommand.class) {
|
||||
return execute((CreateVMSnapshotCommand)cmd);
|
||||
} else if (clazz == DeleteVMSnapshotCommand.class) {
|
||||
@ -1089,31 +1093,42 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
}
|
||||
}
|
||||
|
||||
protected VDI mount(Connection conn, String vmName, VolumeTO volume) throws XmlRpcException, XenAPIException {
|
||||
if (volume.getType() == Volume.Type.ISO) {
|
||||
String isopath = volume.getPath();
|
||||
if (isopath == null) {
|
||||
protected VDI mount(Connection conn, String vmName, DiskTO volume) throws XmlRpcException, XenAPIException {
|
||||
DataTO data = volume.getData();
|
||||
Volume.Type type = volume.getType();
|
||||
if (type == Volume.Type.ISO) {
|
||||
TemplateObjectTO iso = (TemplateObjectTO)data;
|
||||
DataStoreTO store = iso.getDataStore();
|
||||
|
||||
if (store == null) {
|
||||
//It's a fake iso
|
||||
return null;
|
||||
}
|
||||
if (isopath.startsWith("xs-tools")) {
|
||||
|
||||
//corer case, xenserver pv driver iso
|
||||
String templateName = iso.getName();
|
||||
if (templateName.startsWith("xs-tools")) {
|
||||
try {
|
||||
Set<VDI> vdis = VDI.getByNameLabel(conn, isopath);
|
||||
Set<VDI> vdis = VDI.getByNameLabel(conn, templateName);
|
||||
if (vdis.isEmpty()) {
|
||||
throw new CloudRuntimeException("Could not find ISO with URL: " + isopath);
|
||||
throw new CloudRuntimeException("Could not find ISO with URL: " + templateName);
|
||||
}
|
||||
return vdis.iterator().next();
|
||||
|
||||
} catch (XenAPIException e) {
|
||||
throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString());
|
||||
throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString());
|
||||
throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!(store instanceof NfsTO)) {
|
||||
throw new CloudRuntimeException("only support mount iso on nfs");
|
||||
}
|
||||
NfsTO nfsStore = (NfsTO)store;
|
||||
String isoPath = nfsStore.getUrl() + File.separator + iso.getPath();
|
||||
int index = isoPath.lastIndexOf("/");
|
||||
|
||||
|
||||
int index = isopath.lastIndexOf("/");
|
||||
|
||||
String mountpoint = isopath.substring(0, index);
|
||||
String mountpoint = isoPath.substring(0, index);
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(mountpoint);
|
||||
@ -1122,20 +1137,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
}
|
||||
SR isoSr = createIsoSRbyURI(conn, uri, vmName, false);
|
||||
|
||||
String isoname = isopath.substring(index + 1);
|
||||
String isoname = isoPath.substring(index + 1);
|
||||
|
||||
VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr);
|
||||
|
||||
if (isoVdi == null) {
|
||||
throw new CloudRuntimeException("Unable to find ISO " + volume.getPath());
|
||||
throw new CloudRuntimeException("Unable to find ISO " + isoPath);
|
||||
}
|
||||
return isoVdi;
|
||||
} else {
|
||||
return VDI.getByUuid(conn, volume.getPath());
|
||||
VolumeObjectTO vol = (VolumeObjectTO)data;
|
||||
return VDI.getByUuid(conn,vol.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
protected VBD createVbd(Connection conn, VolumeTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException {
|
||||
protected VBD createVbd(Connection conn, DiskTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException {
|
||||
Volume.Type type = volume.getType();
|
||||
|
||||
VDI vdi = mount(conn, vmName, volume);
|
||||
@ -1153,7 +1169,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
vbdr.bootable = true;
|
||||
}
|
||||
|
||||
vbdr.userdevice = Long.toString(volume.getDeviceId());
|
||||
vbdr.userdevice = Long.toString(volume.getDiskSeq());
|
||||
if (volume.getType() == Volume.Type.ISO) {
|
||||
vbdr.mode = Types.VbdMode.RO;
|
||||
vbdr.type = Types.VbdType.CD;
|
||||
@ -1246,12 +1262,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
|
||||
if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
|
||||
if (vmSpec.getBootloader() == BootloaderType.CD) {
|
||||
VolumeTO [] disks = vmSpec.getDisks();
|
||||
for (VolumeTO disk : disks) {
|
||||
if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) {
|
||||
String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD);
|
||||
if (!isoGuestOsName.equals(guestOsTypeName)) {
|
||||
vmSpec.setBootloader(BootloaderType.PyGrub);
|
||||
DiskTO [] disks = vmSpec.getDisks();
|
||||
for (DiskTO disk : disks) {
|
||||
Volume.Type type = disk.getType();
|
||||
if (type == Volume.Type.ISO) {
|
||||
TemplateObjectTO tmpl = (TemplateObjectTO)disk.getData();
|
||||
String osType = tmpl.getGuestOsType();
|
||||
if (tmpl.getFormat() == ImageFormat.ISO && osType != null ) {
|
||||
String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD);
|
||||
if (!isoGuestOsName.equals(guestOsTypeName)) {
|
||||
vmSpec.setBootloader(BootloaderType.PyGrub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1496,7 +1517,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
Host host = Host.getByUuid(conn, _host.uuid);
|
||||
vm = createVmFromTemplate(conn, vmSpec, host);
|
||||
|
||||
for (VolumeTO disk : vmSpec.getDisks()) {
|
||||
for (DiskTO disk : vmSpec.getDisks()) {
|
||||
createVbd(conn, disk, vmName, vm, vmSpec.getBootloader());
|
||||
}
|
||||
|
||||
@ -5774,13 +5795,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
|
||||
|
||||
CheckXenHostInfo();
|
||||
|
||||
this.storageResource = getStorageResource();
|
||||
this.storageHandler = getStorageHandler();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
protected XenServerStorageResource getStorageResource() {
|
||||
return new XenServerStorageResource(this);
|
||||
protected StorageSubsystemCommandHandler getStorageHandler() {
|
||||
XenServerStorageProcessor processor = new XenServerStorageProcessor(this);
|
||||
return new StorageSubsystemCommandHandlerBase(processor);
|
||||
}
|
||||
|
||||
private void CheckXenHostInfo() throws ConfigurationException {
|
||||
|
||||
@ -26,11 +26,14 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
import com.cloud.agent.api.FenceAnswer;
|
||||
import com.cloud.agent.api.FenceCommand;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.resource.ServerResource;
|
||||
@ -194,13 +197,17 @@ public class XenServer56FP1Resource extends XenServer56Resource {
|
||||
|
||||
if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
|
||||
if (vmSpec.getBootloader() == BootloaderType.CD) {
|
||||
VolumeTO[] disks = vmSpec.getDisks();
|
||||
for (VolumeTO disk : disks) {
|
||||
if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) {
|
||||
String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD);
|
||||
if (!isoGuestOsName.equals(guestOsTypeName)) {
|
||||
vmSpec.setBootloader(BootloaderType.PyGrub);
|
||||
}
|
||||
DiskTO[] disks = vmSpec.getDisks();
|
||||
for (DiskTO disk : disks) {
|
||||
if (disk.getType() == Volume.Type.ISO ) {
|
||||
TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
|
||||
String osType = iso.getGuestOsType();
|
||||
if (osType != null) {
|
||||
String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD);
|
||||
if (!isoGuestOsName.equals(guestOsTypeName)) {
|
||||
vmSpec.setBootloader(BootloaderType.PyGrub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,13 +22,9 @@ import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -38,89 +34,315 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
|
||||
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectCommand;
|
||||
import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
|
||||
import org.apache.cloudstack.storage.command.DeleteCommand;
|
||||
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachAnswer;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
|
||||
import org.apache.cloudstack.storage.to.ImageStoreTO;
|
||||
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.xmlrpc.XmlRpcException;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.BackupSnapshotAnswer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ManageSnapshotAnswer;
|
||||
import com.cloud.agent.api.ManageSnapshotCommand;
|
||||
import com.cloud.agent.api.storage.CopyVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.CreateAnswer;
|
||||
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
|
||||
import com.cloud.agent.api.storage.DeleteVolumeCommand;
|
||||
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
|
||||
import com.cloud.agent.api.CreateStoragePoolCommand;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.agent.api.to.S3TO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.agent.api.to.SwiftTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.resource.StorageProcessor;
|
||||
import com.cloud.utils.S3Utils;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.storage.encoding.DecodedDataObject;
|
||||
import com.cloud.utils.storage.encoding.DecodedDataStore;
|
||||
import com.cloud.utils.storage.encoding.Decoder;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.xensource.xenapi.Connection;
|
||||
import com.xensource.xenapi.Host;
|
||||
import com.xensource.xenapi.PBD;
|
||||
import com.xensource.xenapi.Pool;
|
||||
import com.xensource.xenapi.SR;
|
||||
import com.xensource.xenapi.Types;
|
||||
import com.xensource.xenapi.Types.BadServerResponse;
|
||||
import com.xensource.xenapi.Types.XenAPIException;
|
||||
import com.xensource.xenapi.VBD;
|
||||
import com.xensource.xenapi.VDI;
|
||||
import com.xensource.xenapi.VM;
|
||||
import com.xensource.xenapi.VMGuestMetrics;
|
||||
|
||||
public class XenServerStorageResource {
|
||||
private static final Logger s_logger = Logger.getLogger(XenServerStorageResource.class);
|
||||
public class XenServerStorageProcessor implements StorageProcessor {
|
||||
private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
|
||||
protected CitrixResourceBase hypervisorResource;
|
||||
|
||||
public XenServerStorageResource(CitrixResourceBase resource) {
|
||||
public XenServerStorageProcessor(CitrixResourceBase resource) {
|
||||
this.hypervisorResource = resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttachAnswer attachIso(AttachCommand cmd) {
|
||||
DiskTO disk = cmd.getDisk();
|
||||
DataTO data = disk.getData();
|
||||
DataStoreTO store = data.getDataStore();
|
||||
|
||||
public Answer handleStorageCommands(StorageSubSystemCommand command) {
|
||||
if (command instanceof CopyCommand) {
|
||||
return this.execute((CopyCommand)command);
|
||||
} else if (command instanceof AttachPrimaryDataStoreCmd) {
|
||||
return this.execute((AttachPrimaryDataStoreCmd)command);
|
||||
} else if (command instanceof CreatePrimaryDataStoreCmd) {
|
||||
return execute((CreatePrimaryDataStoreCmd) command);
|
||||
} else if (command instanceof CreateObjectCommand) {
|
||||
return execute((CreateObjectCommand) command);
|
||||
} else if (command instanceof DeleteCommand) {
|
||||
return execute((DeleteCommand)command);
|
||||
if (!(store instanceof NfsTO)) {
|
||||
s_logger.debug("Can't attach a iso which is not created on nfs: ");
|
||||
return new AttachAnswer("Can't attach a iso which is not created on nfs: ");
|
||||
}
|
||||
NfsTO nfsStore = (NfsTO)store;
|
||||
String isoURL = nfsStore.getUrl() + File.separator + data.getPath();
|
||||
|
||||
String vmName = cmd.getVmName();
|
||||
try {
|
||||
Connection conn = this.hypervisorResource.getConnection();
|
||||
|
||||
VBD isoVBD = null;
|
||||
|
||||
// Find the VM
|
||||
VM vm = this.hypervisorResource.getVM(conn, vmName);
|
||||
// Find the ISO VDI
|
||||
VDI isoVDI = this.hypervisorResource.getIsoVDIByURL(conn, vmName, isoURL);
|
||||
|
||||
// Find the VM's CD-ROM VBD
|
||||
Set<VBD> vbds = vm.getVBDs(conn);
|
||||
for (VBD vbd : vbds) {
|
||||
String userDevice = vbd.getUserdevice(conn);
|
||||
Types.VbdType type = vbd.getType(conn);
|
||||
|
||||
if (userDevice.equals("3") && type == Types.VbdType.CD) {
|
||||
isoVBD = vbd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isoVBD == null) {
|
||||
throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName);
|
||||
} else {
|
||||
// If an ISO is already inserted, eject it
|
||||
if (isoVBD.getEmpty(conn) == false) {
|
||||
isoVBD.eject(conn);
|
||||
}
|
||||
|
||||
// Insert the new ISO
|
||||
isoVBD.insert(conn, isoVDI);
|
||||
}
|
||||
|
||||
return new AttachAnswer(disk);
|
||||
|
||||
} catch (XenAPIException e) {
|
||||
s_logger.warn("Failed to attach iso" + ": " + e.toString(), e);
|
||||
return new AttachAnswer(e.toString());
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Failed to attach iso" + ": " + e.toString(), e);
|
||||
return new AttachAnswer(e.toString());
|
||||
}
|
||||
return new Answer((Command)command, false, "not implemented yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttachAnswer attachVolume(AttachCommand cmd) {
|
||||
String vmName = cmd.getVmName();
|
||||
DiskTO disk = cmd.getDisk();
|
||||
DataTO data = disk.getData();
|
||||
|
||||
try {
|
||||
Connection conn = this.hypervisorResource.getConnection();
|
||||
// Look up the VDI
|
||||
VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath());
|
||||
// Look up the VM
|
||||
VM vm = this.hypervisorResource.getVM(conn, vmName);
|
||||
/* For HVM guest, if no pv driver installed, no attach/detach */
|
||||
boolean isHVM;
|
||||
if (vm.getPVBootloader(conn).equalsIgnoreCase("")) {
|
||||
isHVM = true;
|
||||
} else {
|
||||
isHVM = false;
|
||||
}
|
||||
VMGuestMetrics vgm = vm.getGuestMetrics(conn);
|
||||
boolean pvDrvInstalled = false;
|
||||
if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) {
|
||||
pvDrvInstalled = true;
|
||||
}
|
||||
if (isHVM && !pvDrvInstalled) {
|
||||
s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected");
|
||||
return new AttachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso.");
|
||||
}
|
||||
|
||||
// Figure out the disk number to attach the VM to
|
||||
String diskNumber = null;
|
||||
Long deviceId = disk.getDiskSeq();
|
||||
if( deviceId != null ) {
|
||||
if( deviceId.longValue() == 3 ) {
|
||||
String msg = "Device 3 is reserved for CD-ROM, choose other device";
|
||||
return new AttachAnswer(msg);
|
||||
}
|
||||
if(this.hypervisorResource.isDeviceUsed(conn, vm, deviceId)) {
|
||||
String msg = "Device " + deviceId + " is used in VM " + vmName;
|
||||
return new AttachAnswer(msg);
|
||||
}
|
||||
diskNumber = deviceId.toString();
|
||||
} else {
|
||||
diskNumber = this.hypervisorResource.getUnusedDeviceNum(conn, vm);
|
||||
}
|
||||
// Create a new VBD
|
||||
VBD.Record vbdr = new VBD.Record();
|
||||
vbdr.VM = vm;
|
||||
vbdr.VDI = vdi;
|
||||
vbdr.bootable = false;
|
||||
vbdr.userdevice = diskNumber;
|
||||
vbdr.mode = Types.VbdMode.RW;
|
||||
vbdr.type = Types.VbdType.DISK;
|
||||
vbdr.unpluggable = true;
|
||||
VBD vbd = VBD.create(conn, vbdr);
|
||||
|
||||
// Attach the VBD to the VM
|
||||
vbd.plug(conn);
|
||||
|
||||
// Update the VDI's label to include the VM name
|
||||
vdi.setNameLabel(conn, vmName + "-DATA");
|
||||
DiskTO newDisk = new DiskTO(disk.getData(), Long.parseLong(diskNumber), disk.getType());
|
||||
return new AttachAnswer(newDisk);
|
||||
|
||||
} catch (XenAPIException e) {
|
||||
String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
return new AttachAnswer(msg);
|
||||
} catch (Exception e) {
|
||||
String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage();
|
||||
s_logger.warn(msg, e);
|
||||
return new AttachAnswer(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer dettachIso(DettachCommand cmd) {
|
||||
DiskTO disk = cmd.getDisk();
|
||||
DataTO data = disk.getData();
|
||||
DataStoreTO store = data.getDataStore();
|
||||
|
||||
if (!(store instanceof NfsTO)) {
|
||||
s_logger.debug("Can't attach a iso which is not created on nfs: ");
|
||||
return new DettachAnswer("Can't attach a iso which is not created on nfs: ");
|
||||
}
|
||||
NfsTO nfsStore = (NfsTO)store;
|
||||
String isoURL = nfsStore.getUrl() + File.separator + data.getPath();
|
||||
|
||||
try {
|
||||
Connection conn = this.hypervisorResource.getConnection();
|
||||
// Find the VM
|
||||
VM vm = this.hypervisorResource.getVM(conn, cmd.getVmName());
|
||||
String vmUUID = vm.getUuid(conn);
|
||||
|
||||
// Find the ISO VDI
|
||||
VDI isoVDI = this.hypervisorResource.getIsoVDIByURL(conn, cmd.getVmName(), isoURL);
|
||||
|
||||
SR sr = isoVDI.getSR(conn);
|
||||
|
||||
// Look up all VBDs for this VDI
|
||||
Set<VBD> vbds = isoVDI.getVBDs(conn);
|
||||
|
||||
// Iterate through VBDs, and if the VBD belongs the VM, eject
|
||||
// the ISO from it
|
||||
for (VBD vbd : vbds) {
|
||||
VM vbdVM = vbd.getVM(conn);
|
||||
String vbdVmUUID = vbdVM.getUuid(conn);
|
||||
|
||||
if (vbdVmUUID.equals(vmUUID)) {
|
||||
// If an ISO is already inserted, eject it
|
||||
if (!vbd.getEmpty(conn)) {
|
||||
vbd.eject(conn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) {
|
||||
this.hypervisorResource.removeSR(conn, sr);
|
||||
}
|
||||
|
||||
return new DettachAnswer(disk);
|
||||
} catch (XenAPIException e) {
|
||||
String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
return new DettachAnswer(msg);
|
||||
} catch (Exception e) {
|
||||
String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage();
|
||||
s_logger.warn(msg, e);
|
||||
return new DettachAnswer(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Answer dettachVolume(DettachCommand cmd) {
|
||||
String vmName = cmd.getVmName();
|
||||
DiskTO disk = cmd.getDisk();
|
||||
DataTO data = disk.getData();
|
||||
try {
|
||||
Connection conn = this.hypervisorResource.getConnection();
|
||||
// Look up the VDI
|
||||
VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath());
|
||||
// Look up the VM
|
||||
VM vm = this.hypervisorResource.getVM(conn, vmName);
|
||||
/* For HVM guest, if no pv driver installed, no attach/detach */
|
||||
boolean isHVM;
|
||||
if (vm.getPVBootloader(conn).equalsIgnoreCase("")) {
|
||||
isHVM = true;
|
||||
} else {
|
||||
isHVM = false;
|
||||
}
|
||||
VMGuestMetrics vgm = vm.getGuestMetrics(conn);
|
||||
boolean pvDrvInstalled = false;
|
||||
if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) {
|
||||
pvDrvInstalled = true;
|
||||
}
|
||||
if (isHVM && !pvDrvInstalled) {
|
||||
s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected");
|
||||
return new DettachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso.");
|
||||
}
|
||||
|
||||
|
||||
// Look up all VBDs for this VDI
|
||||
Set<VBD> vbds = vdi.getVBDs(conn);
|
||||
|
||||
// Detach each VBD from its VM, and then destroy it
|
||||
for (VBD vbd : vbds) {
|
||||
VBD.Record vbdr = vbd.getRecord(conn);
|
||||
|
||||
if (vbdr.currentlyAttached) {
|
||||
vbd.unplug(conn);
|
||||
}
|
||||
|
||||
vbd.destroy(conn);
|
||||
}
|
||||
|
||||
// Update the VDI's label to be "detached"
|
||||
vdi.setNameLabel(conn, "detached");
|
||||
|
||||
this.hypervisorResource.umount(conn, vdi);
|
||||
|
||||
return new DettachAnswer(disk);
|
||||
} catch(Exception e) {
|
||||
s_logger.warn("Failed dettach volume: " + data.getPath());
|
||||
return new DettachAnswer("Failed dettach volume: " + data.getPath() + ", due to " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected SR getSRByNameLabel(Connection conn, String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException {
|
||||
Set<SR> srs = SR.getByNameLabel(conn, nameLabel);
|
||||
@ -146,26 +368,10 @@ public class XenServerStorageResource {
|
||||
vdi.destroy(conn);
|
||||
}
|
||||
|
||||
private Map<String, String> getParameters(URI uri) {
|
||||
String parameters = uri.getQuery();
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
List<String> paraLists = Arrays.asList(parameters.split("&"));
|
||||
for (String para : paraLists) {
|
||||
String[] pair = para.split("=");
|
||||
params.put(pair[0], pair[1]);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
protected CreateObjectAnswer getTemplateSize(CreateObjectCommand cmd, String templateUrl) {
|
||||
/*Connection conn = hypervisorResource.getConnection();
|
||||
long size = this.getTemplateSize(conn, templateUrl);
|
||||
return new CreateObjectAnswer(cmd, templateUrl, size);*/
|
||||
return null;
|
||||
}
|
||||
|
||||
protected CreateObjectAnswer createSnapshot(SnapshotObjectTO snapshotTO) {
|
||||
@Override
|
||||
public Answer createSnapshot(CreateObjectCommand cmd) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
SnapshotObjectTO snapshotTO = (SnapshotObjectTO)cmd.getData();
|
||||
long snapshotId = snapshotTO.getId();
|
||||
String snapshotName = snapshotTO.getName();
|
||||
String details = "create snapshot operation Failed for snapshotId: " + snapshotId;
|
||||
@ -211,22 +417,10 @@ public class XenServerStorageResource {
|
||||
|
||||
return new CreateObjectAnswer(details);
|
||||
}
|
||||
protected CreateObjectAnswer execute(CreateObjectCommand cmd) {
|
||||
DataTO data = cmd.getData();
|
||||
try {
|
||||
if (data.getObjectType() == DataObjectType.VOLUME) {
|
||||
return createVolume(data);
|
||||
} else if (data.getObjectType() == DataObjectType.SNAPSHOT) {
|
||||
return createSnapshot((SnapshotObjectTO)data);
|
||||
}
|
||||
return new CreateObjectAnswer("not supported type");
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString());
|
||||
return new CreateObjectAnswer(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer deleteVolume(VolumeObjectTO volume) {
|
||||
@Override
|
||||
public Answer deleteVolume(DeleteCommand cmd) {
|
||||
DataTO volume = cmd.getData();
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
String errorMsg = null;
|
||||
try {
|
||||
@ -246,46 +440,12 @@ public class XenServerStorageResource {
|
||||
return new Answer(null, false, errorMsg);
|
||||
}
|
||||
|
||||
protected Answer execute(DeleteCommand cmd) {
|
||||
DataTO data = cmd.getData();
|
||||
Answer answer = null;
|
||||
if (data.getObjectType() == DataObjectType.VOLUME) {
|
||||
answer = deleteVolume((VolumeObjectTO)data);
|
||||
} else {
|
||||
answer = new Answer(cmd, false, "unsupported type");
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
/* protected Answer execute(CreateVolumeFromBaseImageCommand cmd) {
|
||||
VolumeObjectTO volume = cmd.getVolume();
|
||||
ImageOnPrimayDataStoreTO baseImage = cmd.getImage();
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
|
||||
try {
|
||||
VDI baseVdi = VDI.getByUuid(conn, baseImage.getPathOnPrimaryDataStore());
|
||||
VDI newVol = baseVdi.createClone(conn, new HashMap<String, String>());
|
||||
newVol.setNameLabel(conn, volume.getName());
|
||||
return new CreateObjectAnswer(cmd, newVol.getUuid(conn), newVol.getVirtualSize(conn));
|
||||
} catch (BadServerResponse e) {
|
||||
return new Answer(cmd, false, e.toString());
|
||||
} catch (XenAPIException e) {
|
||||
return new Answer(cmd, false, e.toString());
|
||||
} catch (XmlRpcException e) {
|
||||
return new Answer(cmd, false, e.toString());
|
||||
}
|
||||
}*/
|
||||
|
||||
protected SR getNfsSR(Connection conn, DecodedDataStore store) {
|
||||
|
||||
protected SR getNfsSR(Connection conn, StorageFilerTO pool) {
|
||||
Map<String, String> deviceConfig = new HashMap<String, String>();
|
||||
|
||||
String uuid = store.getUuid();
|
||||
try {
|
||||
String server = store.getServer();
|
||||
String serverpath = store.getPath();
|
||||
|
||||
String server = pool.getHost();
|
||||
String serverpath = pool.getPath();
|
||||
serverpath = serverpath.replace("//", "/");
|
||||
Set<SR> srs = SR.getAll(conn);
|
||||
for (SR sr : srs) {
|
||||
@ -316,25 +476,25 @@ public class XenServerStorageResource {
|
||||
|
||||
if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) {
|
||||
throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:"
|
||||
+ dc.get("serverpath") + " for pool " + uuid + "on host:" + hypervisorResource.getHost().uuid);
|
||||
+ dc.get("serverpath") + " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().uuid);
|
||||
}
|
||||
|
||||
}
|
||||
deviceConfig.put("server", server);
|
||||
deviceConfig.put("serverpath", serverpath);
|
||||
Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid);
|
||||
SR sr = SR.create(conn, host, deviceConfig, new Long(0), uuid, uuid, SRType.NFS.toString(), "user", true,
|
||||
SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true,
|
||||
new HashMap<String, String>());
|
||||
sr.scan(conn);
|
||||
return sr;
|
||||
} catch (XenAPIException e) {
|
||||
throw new CloudRuntimeException("Unable to create NFS SR " + uuid, e);
|
||||
throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
|
||||
} catch (XmlRpcException e) {
|
||||
throw new CloudRuntimeException("Unable to create NFS SR " + uuid, e);
|
||||
throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
|
||||
}
|
||||
}
|
||||
/*
|
||||
protected SR getIscsiSR(Connection conn, PrimaryDataStoreTO pool) {
|
||||
|
||||
protected SR getIscsiSR(Connection conn, StorageFilerTO pool) {
|
||||
synchronized (pool.getUuid().intern()) {
|
||||
Map<String, String> deviceConfig = new HashMap<String, String>();
|
||||
try {
|
||||
@ -379,13 +539,13 @@ public class XenServerStorageResource {
|
||||
}
|
||||
if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) {
|
||||
throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:"
|
||||
+ dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + _host.uuid);
|
||||
+ dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + this.hypervisorResource.getHost().uuid);
|
||||
}
|
||||
}
|
||||
deviceConfig.put("target", target);
|
||||
deviceConfig.put("targetIQN", targetiqn);
|
||||
|
||||
Host host = Host.getByUuid(conn, _host.uuid);
|
||||
Host host = Host.getByUuid(conn, this.hypervisorResource.getHost().uuid);
|
||||
Map<String, String> smConfig = new HashMap<String, String>();
|
||||
String type = SRType.LVMOISCSI.toString();
|
||||
String poolId = Long.toString(pool.getId());
|
||||
@ -456,99 +616,24 @@ public class XenServerStorageResource {
|
||||
throw new CloudRuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
protected Answer execute(CreatePrimaryDataStoreCmd cmd) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
String storeUrl = cmd.getDataStore();
|
||||
|
||||
}
|
||||
protected Answer execute(CreateStoragePoolCommand cmd) {
|
||||
Connection conn = this.hypervisorResource.getConnection();
|
||||
StorageFilerTO pool = cmd.getPool();
|
||||
try {
|
||||
DecodedDataObject obj = Decoder.decode(storeUrl);
|
||||
DecodedDataStore store = obj.getStore();
|
||||
|
||||
if (store.getScheme().equalsIgnoreCase("nfs")) {
|
||||
SR sr = getNfsSR(conn, store);
|
||||
} else if (store.getScheme().equalsIgnoreCase("iscsi")) {
|
||||
//getIscsiSR(conn, dataStore);
|
||||
} else if (store.getScheme().equalsIgnoreCase("presetup")) {
|
||||
if (pool.getType() == StoragePoolType.NetworkFilesystem) {
|
||||
getNfsSR(conn, pool);
|
||||
} else if (pool.getType() == StoragePoolType.IscsiLUN) {
|
||||
getIscsiSR(conn, pool);
|
||||
} else if (pool.getType() == StoragePoolType.PreSetup) {
|
||||
} else {
|
||||
return new Answer(cmd, false, "The pool type: " + store.getScheme() + " is not supported.");
|
||||
return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported.");
|
||||
}
|
||||
return new Answer(cmd, true, "success");
|
||||
} catch (Exception e) {
|
||||
// String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath();
|
||||
//s_logger.warn(msg, e);
|
||||
return new Answer(cmd, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
private long getTemplateSize(Connection conn, String url) {
|
||||
String size = hypervisorResource.callHostPlugin(conn, "storagePlugin", "getTemplateSize", "srcUrl", url);
|
||||
if (size.equalsIgnoreCase("") || 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 {
|
||||
HttpResponse response = client.execute(method);
|
||||
Header header = response.getFirstHeader("Content-Length");
|
||||
if (header == null) {
|
||||
throw new CloudRuntimeException("Can't get content-lenght header from :" + url);
|
||||
}
|
||||
Long length = Long.parseLong(header.getValue());
|
||||
return length;
|
||||
} catch (HttpException e) {
|
||||
throw new CloudRuntimeException("Failed to get template lenght", e);
|
||||
} catch (IOException e) {
|
||||
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) {
|
||||
File destFile = new File(destFilePath);
|
||||
if (!destFile.exists()) {
|
||||
throw new CloudRuntimeException("dest file doesn't exist: " + destFilePath);
|
||||
}
|
||||
|
||||
DefaultHttpClient client = new DefaultHttpClient();
|
||||
HttpGet getMethod = new HttpGet(url);
|
||||
HttpResponse response;
|
||||
BufferedOutputStream output = null;
|
||||
long length = 0;
|
||||
try {
|
||||
response = client.execute(getMethod);
|
||||
HttpEntity entity = response.getEntity();
|
||||
length = entity.getContentLength();
|
||||
output = new BufferedOutputStream(new FileOutputStream(destFile));
|
||||
entity.writeTo(output);
|
||||
} catch (ClientProtocolException e) {
|
||||
throw new CloudRuntimeException("Failed to download template", e);
|
||||
} catch (IOException e) {
|
||||
throw new CloudRuntimeException("Failed to download template", e);
|
||||
} finally {
|
||||
if (output != null) {
|
||||
try {
|
||||
output.close();
|
||||
} catch (IOException e) {
|
||||
throw new CloudRuntimeException("Failed to download template", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//double check the length
|
||||
destFile = new File(destFilePath);
|
||||
if (destFile.length() != length) {
|
||||
throw new CloudRuntimeException("Download file length doesn't match: expected: " + length + ", actual: " + destFile.length());
|
||||
String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + this.hypervisorResource.getHost().uuid + " pool: " + pool.getHost() + pool.getPath();
|
||||
s_logger.warn(msg, e);
|
||||
return new Answer(cmd, false, msg);
|
||||
}
|
||||
|
||||
}
|
||||
@ -721,7 +806,11 @@ public class XenServerStorageResource {
|
||||
return parentUuid;
|
||||
}
|
||||
|
||||
protected CopyCmdAnswer copyTemplateToPrimaryStorage(DataTO srcData, DataTO destData, int wait) {
|
||||
@Override
|
||||
public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
DataStoreTO srcStore = srcData.getDataStore();
|
||||
try {
|
||||
if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) {
|
||||
@ -774,32 +863,42 @@ public class XenServerStorageResource {
|
||||
return new CopyCmdAnswer("not implemented yet");
|
||||
}
|
||||
|
||||
protected CreateObjectAnswer createVolume(DataTO data) throws BadServerResponse, XenAPIException, XmlRpcException {
|
||||
VolumeObjectTO volume = (VolumeObjectTO)data;
|
||||
@Override
|
||||
public Answer createVolume(CreateObjectCommand cmd) {
|
||||
DataTO data = cmd.getData();
|
||||
VolumeObjectTO volume = (VolumeObjectTO)data;
|
||||
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
|
||||
SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
|
||||
VDI.Record vdir = new VDI.Record();
|
||||
vdir.nameLabel = volume.getName();
|
||||
vdir.SR = poolSr;
|
||||
vdir.type = Types.VdiType.USER;
|
||||
try {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
|
||||
SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
|
||||
VDI.Record vdir = new VDI.Record();
|
||||
vdir.nameLabel = volume.getName();
|
||||
vdir.SR = poolSr;
|
||||
vdir.type = Types.VdiType.USER;
|
||||
|
||||
vdir.virtualSize = volume.getSize();
|
||||
VDI vdi;
|
||||
vdir.virtualSize = volume.getSize();
|
||||
VDI vdi;
|
||||
|
||||
vdi = VDI.create(conn, vdir);
|
||||
vdir = vdi.getRecord(conn);
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setName(vdir.nameLabel);
|
||||
newVol.setSize(vdir.virtualSize);
|
||||
newVol.setPath(vdir.uuid);
|
||||
vdi = VDI.create(conn, vdir);
|
||||
vdir = vdi.getRecord(conn);
|
||||
VolumeObjectTO newVol = new VolumeObjectTO();
|
||||
newVol.setName(vdir.nameLabel);
|
||||
newVol.setSize(vdir.virtualSize);
|
||||
newVol.setPath(vdir.uuid);
|
||||
|
||||
return new CreateObjectAnswer(newVol);
|
||||
return new CreateObjectAnswer(newVol);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("create volume failed: " + e.toString());
|
||||
return new CreateObjectAnswer(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected CopyCmdAnswer cloneVolumeFromBaseTemplate(DataTO srcData, DataTO destData) {
|
||||
@Override
|
||||
public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
|
||||
VolumeObjectTO volume = (VolumeObjectTO)destData;
|
||||
VDI vdi = null;
|
||||
@ -827,9 +926,12 @@ public class XenServerStorageResource {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected Answer copyVolumeFromImageCacheToPrimary(DataTO srcData, DataTO destData, int wait) {
|
||||
@Override
|
||||
public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
|
||||
VolumeObjectTO destVolume = (VolumeObjectTO)destData;
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore();
|
||||
@ -858,10 +960,12 @@ public class XenServerStorageResource {
|
||||
return new CopyCmdAnswer("unsupported protocol");
|
||||
}
|
||||
|
||||
protected Answer copyVolumeFromPrimaryToSecondary(DataTO srcData, DataTO destData, int wait) {
|
||||
@Override
|
||||
public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
|
||||
VolumeObjectTO destVolume = (VolumeObjectTO)destData;
|
||||
VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
|
||||
VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
DataStoreTO destStore = destVolume.getDataStore();
|
||||
|
||||
if (destStore instanceof NfsTO) {
|
||||
@ -1088,8 +1192,13 @@ public class XenServerStorageResource {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Answer backupSnasphot(DataTO srcData, DataTO destData, DataTO cacheData, int wait) {
|
||||
@Override
|
||||
public Answer backupSnasphot(CopyCommand cmd) {
|
||||
Connection conn = hypervisorResource.getConnection();
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO cacheData = cmd.getCacheTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
int wait = cmd.getWait();
|
||||
PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore();
|
||||
String primaryStorageNameLabel = primaryStore.getUuid();
|
||||
String secondaryStorageUrl = null;
|
||||
@ -1220,11 +1329,13 @@ public class XenServerStorageResource {
|
||||
return new CopyCmdAnswer(details);
|
||||
}
|
||||
|
||||
protected CopyCmdAnswer createTemplateFromVolume(DataTO srcData, DataTO destData, int wait) {
|
||||
@Override
|
||||
public Answer createTemplateFromVolume(CopyCommand cmd) {
|
||||
Connection conn = this.hypervisorResource.getConnection();
|
||||
VolumeObjectTO volume = (VolumeObjectTO)srcData;
|
||||
TemplateObjectTO template = (TemplateObjectTO)destData;
|
||||
NfsTO destStore = (NfsTO)destData.getDataStore();
|
||||
VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
|
||||
TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
|
||||
NfsTO destStore = (NfsTO)cmd.getDestTO().getDataStore();
|
||||
int wait = cmd.getWait();
|
||||
|
||||
String secondaryStoragePoolURL = destStore.getUrl();
|
||||
String volumeUUID = volume.getPath();
|
||||
@ -1290,38 +1401,4 @@ public class XenServerStorageResource {
|
||||
}
|
||||
return new CopyCmdAnswer(details);
|
||||
}
|
||||
|
||||
protected Answer execute(CopyCommand cmd) {
|
||||
DataTO srcData = cmd.getSrcTO();
|
||||
DataTO destData = cmd.getDestTO();
|
||||
DataStoreTO srcDataStore = srcData.getDataStore();
|
||||
DataStoreTO destDataStore = destData.getDataStore();
|
||||
DataObjectType srcType = srcData.getObjectType();
|
||||
DataObjectType destType = destData.getObjectType();
|
||||
DataStoreRole destRole = destDataStore.getRole();
|
||||
|
||||
boolean nfs = (srcDataStore instanceof NfsTO) ? true : false;
|
||||
|
||||
if ((srcData.getObjectType() == DataObjectType.TEMPLATE) && (srcDataStore instanceof NfsTO) && (destData.getDataStore().getRole() == DataStoreRole.Primary)) {
|
||||
//copy template to primary storage
|
||||
return copyTemplateToPrimaryStorage(srcData, destData, cmd.getWait());
|
||||
} else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
|
||||
//clone template to a volume
|
||||
return cloneVolumeFromBaseTemplate(srcData, destData);
|
||||
} else if (srcData.getObjectType() == DataObjectType.VOLUME && (srcData.getDataStore().getRole() == DataStoreRole.ImageCache || srcDataStore.getRole() == DataStoreRole.Image)) {
|
||||
//copy volume from image cache to primary
|
||||
return copyVolumeFromImageCacheToPrimary(srcData, destData, cmd.getWait());
|
||||
} else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
|
||||
if (destData.getObjectType() == DataObjectType.VOLUME) {
|
||||
return copyVolumeFromPrimaryToSecondary(srcData, destData, cmd.getWait());
|
||||
} else if (destData.getObjectType() == DataObjectType.TEMPLATE) {
|
||||
return createTemplateFromVolume(srcData, destData, cmd.getWait());
|
||||
}
|
||||
} else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
|
||||
DataTO cacheData = cmd.getCacheTO();
|
||||
return backupSnasphot(srcData, destData, cacheData, cmd.getWait());
|
||||
}
|
||||
|
||||
return new Answer(cmd, false, "not implemented yet");
|
||||
}
|
||||
}
|
||||
@ -27,10 +27,8 @@ import javax.inject.Inject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
@ -53,7 +51,9 @@ import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.storage.DeleteTemplateCommand;
|
||||
import com.cloud.agent.api.storage.DeleteVolumeCommand;
|
||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.NfsTO;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
|
||||
@ -29,10 +29,8 @@ import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
@ -57,7 +55,9 @@ import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.storage.DeleteTemplateCommand;
|
||||
import com.cloud.agent.api.storage.DeleteVolumeCommand;
|
||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.S3TO;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
|
||||
@ -25,9 +25,7 @@ import javax.inject.Inject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
@ -36,7 +34,9 @@ import org.apache.cloudstack.storage.command.CreateObjectAnswer;
|
||||
import org.apache.cloudstack.storage.command.CreateObjectCommand;
|
||||
import org.apache.cloudstack.storage.image.ImageStoreDriver;
|
||||
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
|
||||
//http-read-only based image store
|
||||
|
||||
@ -29,10 +29,8 @@ import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
|
||||
@ -56,7 +54,9 @@ import com.cloud.agent.api.DeleteSnapshotBackupCommand;
|
||||
import com.cloud.agent.api.storage.DeleteTemplateCommand;
|
||||
import com.cloud.agent.api.storage.DeleteVolumeCommand;
|
||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.SwiftTO;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.event.UsageEventUtils;
|
||||
|
||||
@ -25,9 +25,7 @@ import javax.inject.Inject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
|
||||
@ -50,7 +48,9 @@ import com.cloud.agent.api.storage.CreateCommand;
|
||||
import com.cloud.agent.api.storage.DestroyCommand;
|
||||
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
|
||||
import com.cloud.agent.api.storage.ResizeVolumeCommand;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
|
||||
@ -25,7 +25,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
|
||||
@ -42,6 +41,7 @@ import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.storage.encoding.DecodedDataObject;
|
||||
|
||||
@ -22,7 +22,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
@ -30,6 +29,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||
import org.apache.cloudstack.storage.command.CommandResult;
|
||||
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
|
||||
public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
@ -101,7 +102,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
|
||||
}
|
||||
|
||||
to.setNics(nics);
|
||||
to.setDisks(vmProfile.getDisks().toArray(new VolumeTO[vmProfile.getDisks().size()]));
|
||||
to.setDisks(vmProfile.getDisks().toArray(new DataTO[vmProfile.getDisks().size()]));
|
||||
|
||||
if(vmProfile.getTemplate().getBits() == 32) {
|
||||
to.setArch("i686");
|
||||
|
||||
@ -45,18 +45,22 @@ import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.DettachAnswer;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
||||
@ -69,8 +73,8 @@ import org.springframework.stereotype.Component;
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.AttachVolumeAnswer;
|
||||
import com.cloud.agent.api.AttachVolumeCommand;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.alert.AlertManager;
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import com.cloud.async.AsyncJobExecutor;
|
||||
@ -117,7 +121,6 @@ import com.cloud.server.ManagementServer;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Volume.Event;
|
||||
import com.cloud.storage.Volume.Type;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
@ -168,7 +171,6 @@ import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.SecondaryStorageVmDao;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.cloud.vm.snapshot.VMSnapshotVO;
|
||||
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
|
||||
|
||||
@ -1514,7 +1516,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
||||
String errorMsg = "Failed to attach volume: " + volume.getName()
|
||||
+ " to VM: " + vm.getHostName();
|
||||
boolean sendCommand = (vm.getState() == State.Running);
|
||||
AttachVolumeAnswer answer = null;
|
||||
AttachAnswer answer = null;
|
||||
Long hostId = vm.getHostId();
|
||||
if (hostId == null) {
|
||||
hostId = vm.getLastHostId();
|
||||
@ -1526,16 +1528,11 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
||||
}
|
||||
|
||||
if (sendCommand) {
|
||||
StoragePoolVO volumePool = _storagePoolDao.findById(volume
|
||||
.getPoolId());
|
||||
AttachVolumeCommand cmd = new AttachVolumeCommand(true,
|
||||
vm.getInstanceName(), volume.getPoolType(),
|
||||
volume.getFolder(), volume.getPath(), volume.getName(),
|
||||
deviceId, volume.getChainInfo());
|
||||
cmd.setPoolUuid(volumePool.getUuid());
|
||||
|
||||
DataTO volTO = this.volFactory.getVolume(volume.getId()).getTO();
|
||||
DiskTO disk = new DiskTO(volTO, deviceId, volume.getVolumeType());
|
||||
AttachCommand cmd = new AttachCommand(disk, vm.getInstanceName());
|
||||
try {
|
||||
answer = (AttachVolumeAnswer) _agentMgr.send(hostId, cmd);
|
||||
answer = (AttachAnswer) _agentMgr.send(hostId, cmd);
|
||||
} catch (Exception e) {
|
||||
throw new CloudRuntimeException(errorMsg + " due to: "
|
||||
+ e.getMessage());
|
||||
@ -1545,8 +1542,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
||||
if (!sendCommand || (answer != null && answer.getResult())) {
|
||||
// Mark the volume as attached
|
||||
if (sendCommand) {
|
||||
DiskTO disk = answer.getDisk();
|
||||
_volsDao.attachVolume(volume.getId(), vm.getId(),
|
||||
answer.getDeviceId());
|
||||
disk.getDiskSeq());
|
||||
} else {
|
||||
_volsDao.attachVolume(volume.getId(), vm.getId(), deviceId);
|
||||
}
|
||||
@ -1858,16 +1856,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
||||
Answer answer = null;
|
||||
|
||||
if (sendCommand) {
|
||||
AttachVolumeCommand cmd = new AttachVolumeCommand(false,
|
||||
vm.getInstanceName(), volume.getPoolType(),
|
||||
volume.getFolder(), volume.getPath(), volume.getName(),
|
||||
cmmd.getDeviceId() != null ? cmmd.getDeviceId() : volume
|
||||
.getDeviceId(), volume.getChainInfo());
|
||||
|
||||
StoragePoolVO volumePool = _storagePoolDao.findById(volume
|
||||
.getPoolId());
|
||||
cmd.setPoolUuid(volumePool.getUuid());
|
||||
|
||||
DataTO volTO = this.volFactory.getVolume(volume.getId()).getTO();
|
||||
DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getVolumeType());
|
||||
DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName());
|
||||
try {
|
||||
answer = _agentMgr.send(vm.getHostId(), cmd);
|
||||
} catch (Exception e) {
|
||||
@ -1879,12 +1870,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
||||
if (!sendCommand || (answer != null && answer.getResult())) {
|
||||
// Mark the volume as detached
|
||||
_volsDao.detachVolume(volume.getId());
|
||||
if (answer != null && answer instanceof AttachVolumeAnswer) {
|
||||
volume.setChainInfo(((AttachVolumeAnswer) answer)
|
||||
.getChainInfo());
|
||||
_volsDao.update(volume.getId(), volume);
|
||||
}
|
||||
|
||||
return _volsDao.findById(volumeId);
|
||||
} else {
|
||||
|
||||
@ -2097,22 +2082,17 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
||||
}
|
||||
|
||||
for (VolumeVO vol : vols) {
|
||||
PrimaryDataStoreInfo pool = (PrimaryDataStoreInfo)this.dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary);
|
||||
vm.addDisk(new VolumeTO(vol, pool));
|
||||
DataTO volTO = this.volFactory.getVolume(vol.getId()).getTO();
|
||||
DiskTO disk = new DiskTO(volTO, vol.getDeviceId(), vol.getVolumeType());
|
||||
vm.addDisk(disk);
|
||||
}
|
||||
|
||||
if (vm.getType() == VirtualMachine.Type.User) {
|
||||
UserVmVO userVM = (UserVmVO) vm.getVirtualMachine();
|
||||
if (userVM.getIsoId() != null) {
|
||||
Pair<String, String> isoPathPair = this._tmpltMgr.getAbsoluteIsoPath(
|
||||
userVM.getIsoId(), userVM.getDataCenterId());
|
||||
if (isoPathPair != null) {
|
||||
String isoPath = isoPathPair.first();
|
||||
VolumeTO iso = new VolumeTO(vm.getId(), Volume.Type.ISO,
|
||||
StoragePoolType.ISO, null, null, null, isoPath, 0,
|
||||
null, null);
|
||||
vm.addDisk(iso);
|
||||
}
|
||||
DataTO dataTO = this.tmplFactory.getTemplate(userVM.getIsoId(), DataStoreRole.Image, userVM.getDataCenterId()).getTO();
|
||||
DiskTO iso = new DiskTO(dataTO, 3L, Volume.Type.ISO);
|
||||
vm.addDisk(iso);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2328,7 +2308,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
|
||||
pool = (StoragePool)dataStoreMgr.getDataStore(result.second().getId(), DataStoreRole.Primary);
|
||||
vol = result.first();
|
||||
}
|
||||
vm.addDisk(new VolumeTO(vol, pool));
|
||||
DataTO volumeTO = this.volFactory.getVolume(vol.getId()).getTO();
|
||||
DiskTO disk = new DiskTO(volumeTO, vol.getDeviceId(), vol.getVolumeType());
|
||||
vm.addDisk(disk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,6 @@ import java.util.TimerTask;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
|
||||
@ -50,6 +49,7 @@ import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
import com.cloud.agent.api.StartupSecondaryStorageCommand;
|
||||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.ConnectionException;
|
||||
import com.cloud.host.Host;
|
||||
|
||||
@ -65,7 +65,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
|
||||
import org.apache.cloudstack.framework.async.AsyncCallFuture;
|
||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||
import org.apache.cloudstack.storage.command.CommandResult;
|
||||
import org.apache.cloudstack.storage.command.DettachCommand;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
@ -79,8 +81,11 @@ import org.springframework.stereotype.Component;
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.AttachIsoCommand;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ComputeChecksumCommand;
|
||||
import com.cloud.agent.api.storage.DestroyCommand;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.api.ApiDBUtils;
|
||||
import com.cloud.async.AsyncJobManager;
|
||||
import com.cloud.async.AsyncJobVO;
|
||||
@ -1024,27 +1029,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
||||
} else if (vm.getState() != State.Running) {
|
||||
return true;
|
||||
}
|
||||
String isoPath;
|
||||
VMTemplateVO tmplt = this._tmpltDao.findById(isoId);
|
||||
//FIXME: if it's s3, need to download into cache store
|
||||
TemplateInfo tmplt = this._tmplFactory.getTemplate(isoId, DataStoreRole.Image, vm.getDataCenterId());
|
||||
if (tmplt == null) {
|
||||
s_logger.warn("ISO: " + isoId + " does not exist");
|
||||
return false;
|
||||
}
|
||||
// Get the path of the ISO
|
||||
Pair<String, String> isoPathPair = null;
|
||||
if (tmplt.getTemplateType() == TemplateType.PERHOST) {
|
||||
isoPath = tmplt.getName();
|
||||
} else {
|
||||
isoPathPair = getAbsoluteIsoPath(isoId,
|
||||
vm.getDataCenterId());
|
||||
if (isoPathPair == null) {
|
||||
s_logger.warn("Couldn't get absolute iso path");
|
||||
return false;
|
||||
} else {
|
||||
isoPath = isoPathPair.first();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String vmName = vm.getInstanceName();
|
||||
|
||||
HostVO host = _hostDao.findById(vm.getHostId());
|
||||
@ -1052,12 +1043,16 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
||||
s_logger.warn("Host: " + vm.getHostId() + " does not exist");
|
||||
return false;
|
||||
}
|
||||
AttachIsoCommand cmd = new AttachIsoCommand(vmName, isoPath, attach);
|
||||
if (isoPathPair != null) {
|
||||
cmd.setStoreUrl(isoPathPair.second());
|
||||
|
||||
DataTO isoTO = tmplt.getTO();
|
||||
DiskTO disk = new DiskTO(isoTO, null, Volume.Type.ISO);
|
||||
Command cmd = null;
|
||||
if (attach) {
|
||||
cmd = new AttachCommand(disk, vmName);
|
||||
} else {
|
||||
cmd = new DettachCommand(disk, vmName);
|
||||
}
|
||||
Answer a = _agentMgr.easySend(vm.getHostId(), cmd);
|
||||
|
||||
return (a != null && a.getResult());
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,10 @@ import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
|
||||
import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity;
|
||||
import org.apache.cloudstack.engine.service.api.OrchestrationService;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
@ -58,6 +61,7 @@ import com.cloud.agent.api.StopAnswer;
|
||||
import com.cloud.agent.api.UnPlugNicAnswer;
|
||||
import com.cloud.agent.api.UnPlugNicCommand;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
@ -159,6 +163,7 @@ import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.StoragePoolStatus;
|
||||
@ -373,6 +378,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
|
||||
@Inject
|
||||
List<DeployPlannerSelector> plannerSelectors;
|
||||
@Inject
|
||||
TemplateDataFactory templateFactory;
|
||||
|
||||
protected ScheduledExecutorService _executor = null;
|
||||
protected int _expungeInterval;
|
||||
@ -2625,52 +2632,33 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
|
||||
vm.setDetails(details);
|
||||
|
||||
if (vm.getIsoId() != null) {
|
||||
String isoPath = null;
|
||||
|
||||
VirtualMachineTemplate template = _templateDao.findById(vm
|
||||
.getIsoId());
|
||||
TemplateInfo template = templateFactory.getTemplate(vm.getIsoId(), DataStoreRole.Image, vm.getDataCenterId());
|
||||
|
||||
if (template == null || template.getFormat() != ImageFormat.ISO) {
|
||||
throw new CloudRuntimeException(
|
||||
"Can not find ISO in vm_template table for id "
|
||||
+ vm.getIsoId());
|
||||
}
|
||||
|
||||
Pair<String, String> isoPathPair = this.templateMgr.getAbsoluteIsoPath(
|
||||
template.getId(), vm.getDataCenterId());
|
||||
|
||||
if (template.getTemplateType() == TemplateType.PERHOST) {
|
||||
isoPath = template.getName();
|
||||
} else {
|
||||
if (isoPathPair == null) {
|
||||
s_logger.warn("Couldn't get absolute iso path");
|
||||
return false;
|
||||
} else {
|
||||
isoPath = isoPathPair.first();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (template.isBootable()) {
|
||||
profile.setBootLoaderType(BootloaderType.CD);
|
||||
}
|
||||
|
||||
GuestOSVO guestOS = _guestOSDao.findById(template.getGuestOSId());
|
||||
String displayName = null;
|
||||
if (guestOS != null) {
|
||||
displayName = guestOS.getDisplayName();
|
||||
}
|
||||
VolumeTO iso = new VolumeTO(profile.getId(), Volume.Type.ISO,
|
||||
StoragePoolType.ISO, null, template.getName(), null,
|
||||
isoPath, 0, null, displayName);
|
||||
|
||||
iso.setDeviceId(3);
|
||||
profile.addDisk(iso);
|
||||
|
||||
TemplateObjectTO iso = (TemplateObjectTO)template.getTO();
|
||||
iso.setGuestOsType(displayName);
|
||||
DiskTO disk = new DiskTO(iso, 3L, Volume.Type.ISO);
|
||||
profile.addDisk(disk);
|
||||
} else {
|
||||
VirtualMachineTemplate template = profile.getTemplate();
|
||||
/* create a iso placeholder */
|
||||
VolumeTO iso = new VolumeTO(profile.getId(), Volume.Type.ISO,
|
||||
StoragePoolType.ISO, null, template.getName(), null, null,
|
||||
0, null);
|
||||
iso.setDeviceId(3);
|
||||
profile.addDisk(iso);
|
||||
TemplateObjectTO iso = new TemplateObjectTO();
|
||||
iso.setFormat(ImageFormat.ISO);
|
||||
DiskTO disk = new DiskTO(iso, 3L, Volume.Type.ISO);
|
||||
profile.addDisk(disk);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@ -22,6 +22,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import com.cloud.agent.api.to.DiskTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
@ -46,7 +47,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
|
||||
UserVmDetailVO _userVmDetails;
|
||||
Map<Param, Object> _params;
|
||||
List<NicProfile> _nics = new ArrayList<NicProfile>();
|
||||
List<VolumeTO> _disks = new ArrayList<VolumeTO>();
|
||||
List<DiskTO> _disks = new ArrayList<DiskTO>();
|
||||
StringBuilder _bootArgs = new StringBuilder();
|
||||
Account _owner;
|
||||
BootloaderType _bootloader;
|
||||
@ -141,7 +142,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
|
||||
_nics = nics;
|
||||
}
|
||||
|
||||
public void setDisks(List<VolumeTO> disks) {
|
||||
public void setDisks(List<DiskTO> disks) {
|
||||
_disks = disks;
|
||||
}
|
||||
|
||||
@ -151,7 +152,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VolumeTO> getDisks() {
|
||||
public List<DiskTO> getDisks() {
|
||||
return _disks;
|
||||
}
|
||||
|
||||
@ -161,7 +162,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDisk(int index, VolumeTO disk) {
|
||||
public void addDisk(int index, DiskTO disk) {
|
||||
_disks.add(index, disk);
|
||||
}
|
||||
|
||||
@ -210,7 +211,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDisk(VolumeTO disk) {
|
||||
public void addDisk(DiskTO disk) {
|
||||
_disks.add(disk);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user