refactor kvm/vmware resource code

This commit is contained in:
Edison Su 2013-05-09 23:09:42 -07:00
parent a83b87b7e5
commit 42e25a22fc
57 changed files with 3397 additions and 670 deletions

View File

@ -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,

View File

@ -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();

View 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;
}
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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;

View 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);
}

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
@ -90,6 +91,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
public TemplateInfo getTemplate(long templateId, DataStoreRole storeRole, Long zoneId) {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
@ -384,6 +392,8 @@ ServerResource {
protected BridgeType _bridgeType;
protected StorageSubsystemCommandHandler storageHandler;
private String getEndIpFromStartIp(String startIp, int numIps) {
String[] tokens = startIp.split("[.]");
assert (tokens.length == 4);
@ -811,6 +821,10 @@ ServerResource {
configureVifDrivers(params);
KVMStorageProcessor storageProcessor = new KVMStorageProcessor(this._storagePoolMgr, this);
storageProcessor.configure(name, params);
storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
return true;
}
@ -959,11 +973,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;

View File

@ -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;

View File

@ -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());
}
}
}

View File

@ -0,0 +1,87 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package 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");
}
}

View File

@ -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;
@ -314,6 +327,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
protected volatile long _cmdSequence = 1;
protected StorageSubsystemCommandHandler storageHandler;
protected static HashMap<VirtualMachinePowerState, State> s_statesTable;
static {
s_statesTable = new HashMap<VirtualMachinePowerState, State>();
@ -322,6 +337,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
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);
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 (volIso != null) {
TemplateObjectTO iso = (TemplateObjectTO)volIso.getData();
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;
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);
}
}
}
}
}

View File

@ -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,90 +34,316 @@ 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;
}
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);
@Override
public AttachAnswer attachIso(AttachCommand 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 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);
if (srs.size() != 1) {
@ -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");
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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,26 +1029,12 @@ 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();
@ -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());
}

View File

@ -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;
TemplateInfo template = templateFactory.getTemplate(vm.getIsoId(), DataStoreRole.Image, vm.getDataCenterId());
VirtualMachineTemplate template = _templateDao.findById(vm
.getIsoId());
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;

View File

@ -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);
}