diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java index c7a981eeb41..f43f5a5be74 100755 --- a/api/src/com/cloud/storage/Volume.java +++ b/api/src/com/cloud/storage/Volume.java @@ -37,6 +37,9 @@ public interface Volume extends PartOf, OwnedBy, BasedOn { Destroyed } + enum SourceType { + Snapshot,DiskOffering,Template,Blank + } /** * @return the volume name */ @@ -75,4 +78,12 @@ public interface Volume extends PartOf, OwnedBy, BasedOn { Long getPoolId(); State getState(); + + SourceType getSourceType(); + + void setSourceType(SourceType sourceType); + + void setSourceId(Long sourceId); + + Long getSourceId(); } diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index 986ac065f6d..ce698854bbe 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -149,6 +149,7 @@ + diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index bfda859aa7d..8b16dec93c9 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -3491,9 +3491,25 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR protected String callHostPlugin(String plugin, String cmd, String... params) { Map args = new HashMap(); + Session slaveSession = null; + Connection slaveConn = null; try { - Connection conn = getConnection(); - Host host = Host.getByUuid(conn, _host.uuid); + URL slaveUrl = null; + try { + slaveUrl = new URL("http://" + _host.ip); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + slaveConn = new Connection(slaveUrl, 10); + slaveSession = Session.slaveLocalLoginWithPassword(slaveConn, _username, _password); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Slave logon successful. session= " + slaveSession); + } + Host host = Host.getByUuid(slaveConn, _host.uuid); + + for (int i = 0; i < params.length; i += 2) { args.put(params[i], params[i + 1]); } @@ -3502,7 +3518,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR s_logger.trace("callHostPlugin executing for command " + cmd + " with " + getArgsString(args)); } - String result = host.callPlugin(conn, plugin, cmd, args); + String result = host.callPlugin(slaveConn, plugin, cmd, args); if (s_logger.isTraceEnabled()) { s_logger.trace("callHostPlugin Result: " + result); } @@ -3511,6 +3527,13 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR s_logger.warn("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.toString()); } catch (XmlRpcException e) { s_logger.debug("callHostPlugin failed for cmd: " + cmd + " with args " + getArgsString(args) + " due to " + e.getMessage()); + } finally { + if( slaveSession != null) { + try { + slaveSession.localLogout(slaveConn); + } catch (Exception e) { + } + } } return null; } @@ -3979,6 +4002,10 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR s_logger.debug("Can't get xs-tools.iso: " + e.toString()); } } + + protected boolean can_bridge_firewall() { + return false; + } protected boolean getHostInfo() throws IllegalArgumentException{ Connection conn = getConnection(); @@ -3998,7 +4025,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return false; } - _canBridgeFirewall = Boolean.valueOf(callHostPlugin("vmops", "can_bridge_firewall", "host_uuid", _host.uuid)); + _canBridgeFirewall = can_bridge_firewall(); Nic privateNic = getLocalNetwork(conn, name); if (privateNic == null) { @@ -4008,6 +4035,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR s_logger.warn("Unable to determine the private network for host " + _host.ip); return false; } + _privateNetworkName = name; privateNic = getLocalNetwork(conn, name); if (privateNic == null) { s_logger.warn("Unable to get private network " + name); @@ -4026,6 +4054,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } else { guestNic = privateNic; + _guestNetworkName = _privateNetworkName; } _host.guestNetwork = guestNic.nr.uuid; _host.guestPif = guestNic.pr.uuid; @@ -4039,6 +4068,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } else { publicNic = guestNic; + _publicNetworkName = _guestNetworkName; } _host.publicPif = publicNic.pr.uuid; _host.publicNetwork = publicNic.nr.uuid; @@ -4061,6 +4091,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR _host.storagePif2 = storageNic2.pr.uuid; s_logger.info("Private Network is " + _privateNetworkName + " for host " + _host.ip); + s_logger.info("Guest Network is " + _guestNetworkName + " for host " + _host.ip); s_logger.info("Public Network is " + _publicNetworkName + " for host " + _host.ip); s_logger.info("Storage Network 1 is " + _storageNetworkName1 + " for host " + _host.ip); s_logger.info("Storage Network 2 is " + _storageNetworkName2 + " for host " + _host.ip); diff --git a/core/src/com/cloud/storage/StorageResource.java b/core/src/com/cloud/storage/StorageResource.java index c80509708a4..7ad29f10c83 100755 --- a/core/src/com/cloud/storage/StorageResource.java +++ b/core/src/com/cloud/storage/StorageResource.java @@ -195,7 +195,7 @@ public abstract class StorageResource extends ServerResourceBase implements Serv String path = rootdiskFolder + File.separator + "rootdisk"; long totalSize = getVolumeSize(path); - VolumeVO vol = new VolumeVO(null, null, -1, -1, -1, -1, new Long(-1), rootdiskFolder, path, totalSize, Volume.VolumeType.ROOT); + VolumeVO vol = new VolumeVO(null, -1, -1, -1, -1, new Long(-1), rootdiskFolder, path, totalSize, Volume.VolumeType.ROOT); vols.add(vol); // Get the datadisk volume @@ -203,7 +203,7 @@ public abstract class StorageResource extends ServerResourceBase implements Serv path = datadiskFolder + File.separator + datadiskName; totalSize = getVolumeSize(path); - vol = new VolumeVO(null, null, -1, -1, -1, -1, new Long(-1), datadiskFolder, path, totalSize, Volume.VolumeType.DATADISK); + vol = new VolumeVO(null, -1, -1, -1, -1, new Long(-1), datadiskFolder, path, totalSize, Volume.VolumeType.DATADISK); vols.add(vol); } @@ -216,7 +216,7 @@ public abstract class StorageResource extends ServerResourceBase implements Serv String path = getVolumeName(imagePath, null); long totalSize = getVolumeSize(path); - VolumeVO vol = new VolumeVO(null, null, -1, -1, -1, -1, new Long(-1), null, path, totalSize, Volume.VolumeType.ROOT); + VolumeVO vol = new VolumeVO(null, -1, -1, -1, -1, new Long(-1), null, path, totalSize, Volume.VolumeType.ROOT); vols.add(vol); @@ -225,7 +225,7 @@ public abstract class StorageResource extends ServerResourceBase implements Serv totalSize = getVolumeSize(path); - vol = new VolumeVO(null, null, -1, -1, -1, -1, new Long(-1), null, path, totalSize, Volume.VolumeType.DATADISK); + vol = new VolumeVO(null, -1, -1, -1, -1, new Long(-1), null, path, totalSize, Volume.VolumeType.DATADISK); vols.add(vol); } diff --git a/core/src/com/cloud/storage/VolumeVO.java b/core/src/com/cloud/storage/VolumeVO.java index e80a02a6d1d..48ccc908c99 100755 --- a/core/src/com/cloud/storage/VolumeVO.java +++ b/core/src/com/cloud/storage/VolumeVO.java @@ -149,6 +149,13 @@ public class VolumeVO implements Volume { @Enumerated(value=EnumType.STRING) private State state; + @Column(name="source_type") + @Enumerated(value=EnumType.STRING) + Volume.SourceType sourceType; + + @Column(name="source_id") + Long sourceId; + /** * Constructor for data disk. * @param type @@ -178,8 +185,7 @@ public class VolumeVO implements Volume { } // Real Constructor - public VolumeVO(long id, VolumeType type, String name, long dcId, long domainId, long accountId, long diskOfferingId, long size) { - this.id = id; + public VolumeVO(VolumeType type, String name, long dcId, long domainId, long accountId, long diskOfferingId, long size) { this.volumeType = type; this.name = name; this.dataCenterId = dcId; @@ -212,8 +218,7 @@ public class VolumeVO implements Volume { } - public VolumeVO(Long id, String name, long dcId, long podId, long accountId, long domainId, Long instanceId, String folder, String path, long size, Volume.VolumeType vType) { - this.id = id; + public VolumeVO(String name, long dcId, long podId, long accountId, long domainId, Long instanceId, String folder, String path, long size, Volume.VolumeType vType) { this.name = name; this.accountId = accountId; this.domainId = domainId; @@ -510,4 +515,24 @@ public class VolumeVO implements Volume { public String toString() { return new StringBuilder("Vol[").append(id).append("|vm=").append(instanceId).append("|").append(volumeType).append("]").toString(); } + + @Override + public SourceType getSourceType() { + return this.sourceType; + } + + @Override + public void setSourceType(SourceType sourceType) { + this.sourceType = sourceType; + } + + @Override + public void setSourceId(Long sourceId){ + this.sourceId = sourceId; + } + + @Override + public Long getSourceId(){ + return this.sourceId; + } } diff --git a/scripts/vm/hypervisor/xenserver/hostvmstats.py b/scripts/vm/hypervisor/xenserver/hostvmstats.py index 89af959db61..8aa3eede4f9 100644 --- a/scripts/vm/hypervisor/xenserver/hostvmstats.py +++ b/scripts/vm/hypervisor/xenserver/hostvmstats.py @@ -7,14 +7,8 @@ import time import logging logging.basicConfig(filename='/tmp/xapilog',level=logging.DEBUG) -def get_xapi_session(): - xapi = XenAPI.xapi_local(); - xapi.login_with_password("","") - return xapi._session - -def get_stats(collect_host_stats, consolidation_function, interval, start_time): +def get_stats(session, collect_host_stats, consolidation_function, interval, start_time): try: - session = get_xapi_session() if collect_host_stats == "true" : url = "http://localhost/rrd_updates?" diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index 3ac93f4abd5..dfc0c1d168e 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -4,6 +4,7 @@ import os, sys, time import XenAPIPlugin +import XenAPI sys.path.append("/opt/xensource/sm/") import SR, VDI, SRCommand, util, lvutil from util import CommandException @@ -35,13 +36,20 @@ def echo(fn): return res return wrapped + +def get_xapi_session(): + xapi = XenAPI.xapi_local(); + xapi.login_with_password("","") + return xapi._session + @echo def gethostvmstats(session, args): collect_host_stats = args['collectHostStats'] consolidation_function = args['consolidationFunction'] interval = args['interval'] start_time = args['startTime'] - result = hostvmstats.get_stats(collect_host_stats, consolidation_function, interval, start_time) + session = get_xapi_session() + result = hostvmstats.get_stats(session, collect_host_stats, consolidation_function, interval, start_time) return result @echo @@ -454,7 +462,9 @@ def heartbeat(session, args): txt='fail' return txt -def get_private_nic(session, args): +def get_private_nic( args): + session = get_xapi_session() + vms = session.xenapi.VM.get_all() host_uuid = args.get('host_uuid') host = session.xenapi.host.get_by_uuid(host_uuid) piflist = session.xenapi.host.get_PIFs(host) @@ -481,7 +491,7 @@ def can_bridge_firewall(session, args): util.pread2(['iptables', '-D', 'FORWARD', '-j', 'RH-Firewall-1-INPUT']) except: util.SMlog('Chain BRIDGE-FIREWALL already exists') - privnic = get_private_nic(session, args) + privnic = get_private_nic(args) result = 'true' try: util.pread2(['/bin/bash', '-c', 'iptables -n -L FORWARD | grep BRIDGE-FIREWALL']) @@ -496,8 +506,8 @@ def can_bridge_firewall(session, args): if not os.path.exists('/var/run/cloud'): os.makedirs('/var/run/cloud') - cleanup_rules_for_dead_vms(session) - cleanup_rules(session) + cleanup_rules_for_dead_vms() + cleanup_rules() return result @@ -875,6 +885,8 @@ def get_rule_log_for_vm(session, vmName): def get_rule_logs_for_vms(session, args): host_uuid = args.pop('host_uuid') try: + session = get_xapi_session() + thishost = session.xenapi.host.get_by_uuid(host_uuid) hostrec = session.xenapi.host.get_record(thishost) vms = hostrec.get('resident_VMs') @@ -897,7 +909,9 @@ def get_rule_logs_for_vms(session, args): return ";".join(result) @echo -def cleanup_rules_for_dead_vms(session): +def cleanup_rules_for_dead_vms(): + try: + session = get_xapi_session() vms = session.xenapi.VM.get_all() cleaned = 0 for vm_name in [session.xenapi.VM.get_name_label(x) for x in vms]: @@ -913,9 +927,16 @@ def cleanup_rules_for_dead_vms(session): cleaned = cleaned+1 util.SMlog("Cleaned up rules for " + str(cleaned) + " vms") + except: + util.SMlog("Failed to cleanup rules for dead vms!") + + @echo -def cleanup_rules(session): +def cleanup_rules(): + try: + session = get_xapi_session() + chainscmd = "iptables-save | grep '^:' | awk '{print $1}' | cut -d':' -f2" chains = util.pread2(['/bin/bash', '-c', chainscmd]).split('\n') cleaned = 0 @@ -942,6 +963,8 @@ def cleanup_rules(session): destroy_network_rules_for_vm(session, {'vmName':vmname}) util.SMlog("Cleaned up rules for " + str(len(cleanup)) + " chains") + except: + util.SMlog("Failed to cleanup rules !") @echo def check_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): @@ -1005,6 +1028,8 @@ def remove_rule_log_for_vm(vmName): @echo def network_rules(session, args): + try: + session = get_xapi_session() vm_name = args.get('vmName') vmName = vm_name vm_ip = args.get('vmIP') @@ -1101,6 +1126,8 @@ def network_rules(session, args): return 'false' return 'true' + except: + util.SMlog("Failed to network rule !") diff --git a/server/src/com/cloud/api/BaseCmd.java b/server/src/com/cloud/api/BaseCmd.java index e9072b732b4..4c630bd734c 100644 --- a/server/src/com/cloud/api/BaseCmd.java +++ b/server/src/com/cloud/api/BaseCmd.java @@ -337,6 +337,8 @@ public abstract class BaseCmd { STATE("state", BaseCmd.TYPE_STRING, "state"), STOPPED_VMS("stoppedvms", BaseCmd.TYPE_LONG, "stoppedvms"), STORAGE("storage", BaseCmd.TYPE_LONG, "storage"), + SOURCE_ID("sourceid", BaseCmd.TYPE_LONG, "sourceid"), + SOURCE_TYPE("sourcetype",BaseCmd.TYPE_STRING,"sourcetype"), STORAGE_TYPE("storagetype", BaseCmd.TYPE_STRING, "storageType"), SUCCESS("success", BaseCmd.TYPE_BOOLEAN, "success"), SUM_ACROSS_ZONE("sumacrosszone", BaseCmd.TYPE_BOOLEAN, "sumAcrossZone"), diff --git a/server/src/com/cloud/api/commands/ListVolumesCmd.java b/server/src/com/cloud/api/commands/ListVolumesCmd.java index a4680be0441..b856e4eae2f 100644 --- a/server/src/com/cloud/api/commands/ListVolumesCmd.java +++ b/server/src/com/cloud/api/commands/ListVolumesCmd.java @@ -223,7 +223,9 @@ public class ListVolumesCmd extends BaseCmd{ Long poolId = volume.getPoolId(); String poolName = (poolId == null) ? "none" : getManagementServer().findPoolById(poolId).getName(); volumeData.add(new Pair(BaseCmd.Properties.STORAGE.getName(), poolName)); - + volumeData.add(new Pair(BaseCmd.Properties.SOURCE_ID.getName(),volume.getSourceId())); + volumeData.add(new Pair(BaseCmd.Properties.SOURCE_TYPE.getName(),volume.getSourceType().toString())); + vTag[i++] = volumeData; } Pair volumeTag = new Pair("volume", vTag); diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java index 19c1aea8bee..2f043069012 100644 --- a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java @@ -99,8 +99,8 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer, String password) throws DiscoveryException { Map> resources = new HashMap>(); Map details = new HashMap(); - if (!uri.getScheme().equals("http")) { - String msg = "urlString is not http so we're not taking care of the discovery for this: " + uri; + if (!uri.getScheme().equals("kvm")) { + String msg = "urlString is not kvm so we're not taking care of the discovery for this: " + uri; s_logger.debug(msg); return null; } diff --git a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index e7017710f9e..cc1fb72b343 100644 --- a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -53,6 +53,7 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.xen.resource.CitrixResourceBase; import com.cloud.hypervisor.xen.resource.XcpServerResource; import com.cloud.hypervisor.xen.resource.XenServerConnectionPool; +import com.cloud.hypervisor.xen.resource.XenServerResource; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; import com.cloud.resource.ServerResource; @@ -170,15 +171,10 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if (_hostDao.findByGuid(record.uuid) != null) { s_logger.debug("Skipping " + record.address + " because " + record.uuid + " is already in the database."); continue; - } - - - if (!checkServer(conn, dcId, podId, host, record)) { - continue; - } - + } + + CitrixResourceBase resource = createServerResource(dcId, podId, record); s_logger.info("Found host " + record.hostname + " ip=" + record.address + " product version=" + prodVersion); - CitrixResourceBase resource = createServerResource(record); Map details = new HashMap(); Map params = new HashMap(); @@ -379,22 +375,21 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L return true; } - - protected boolean checkServer(Connection conn, long dcId, Long podId, Host host, Host.Record record) { + + protected CitrixResourceBase createServerResource(long dcId, Long podId, Host.Record record) { String prodBrand = record.softwareVersion.get("product_brand").trim(); String prodVersion = record.softwareVersion.get("product_version").trim(); - if(!prodBrand.equals("XenCloudPlatform") || !prodVersion.equals("0.1.1")) { - String msg = "Only support XCP 0.1.1, but this one is " + prodBrand + " " + prodVersion; - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, msg, msg); - s_logger.debug(msg); - throw new RuntimeException(msg); - } - return true; - } - - protected CitrixResourceBase createServerResource(Host.Record record) { - return new XcpServerResource(); + if(prodBrand.equals("XenCloudPlatform") && prodVersion.equals("0.1.1")) + return new XcpServerResource(); + + if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) + return new XenServerResource(); + + String msg = "Only support XCP 0.1.1 and Xerver 5.6.0, but this one is " + prodBrand + " " + prodVersion; + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, msg, msg); + s_logger.debug(msg); + throw new RuntimeException(msg); } protected void serverConfig() { diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 76091274ccd..99c13301707 100644 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -102,6 +102,7 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume.MirrorState; +import com.cloud.storage.Volume.SourceType; import com.cloud.storage.Volume.VolumeType; import com.cloud.storage.allocator.StoragePoolAllocator; import com.cloud.storage.dao.DiskOfferingDao; @@ -233,7 +234,7 @@ public class StorageManagerImpl implements StorageManager { long deviceId = 0; Transaction txn = Transaction.currentTxn(); txn.start(); - rootVol = new VolumeVO(rootDisk.getVolumeId(), VolumeType.ROOT, rootDisk.getName(), dc.getId(), account.getDomainId(), account.getId(), rootDisk.getDiskOfferingId(), rootDisk.getSize()); + rootVol = new VolumeVO(VolumeType.ROOT, rootDisk.getName(), dc.getId(), account.getDomainId(), account.getId(), rootDisk.getDiskOfferingId(), rootDisk.getSize()); if (rootDisk.getTemplateId() != null) { rootVol.setTemplateId(rootDisk.getTemplateId()); } @@ -242,7 +243,7 @@ public class StorageManagerImpl implements StorageManager { rootVol = _volsDao.persist(rootVol); vols.add(rootVol); for (DiskCharacteristics dataDisk : dataDisks) { - dataVol = new VolumeVO(dataDisk.getVolumeId(), VolumeType.DATADISK, dataDisk.getName(), dc.getId(), account.getDomainId(), account.getId(), dataDisk.getDiskOfferingId(), dataDisk.getSize()); + dataVol = new VolumeVO(VolumeType.DATADISK, dataDisk.getName(), dc.getId(), account.getDomainId(), account.getId(), dataDisk.getDiskOfferingId(), dataDisk.getSize()); dataVol.setDeviceId(deviceId++); dataVol.setInstanceId(vm.getId()); dataVol = _volsDao.persist(dataVol); @@ -484,7 +485,7 @@ public class StorageManagerImpl implements StorageManager { // Create the Volume object and save it so that we can return it to the user Account account = _accountDao.findById(accountId); - VolumeVO volume = new VolumeVO(null, userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, 0, Volume.VolumeType.DATADISK); + VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, 0, Volume.VolumeType.DATADISK); volume.setPoolId(null); volume.setDataCenterId(dc.getId()); volume.setPodId(null); @@ -499,6 +500,8 @@ public class StorageManagerImpl implements StorageManager { volume.setInstanceId(null); volume.setUpdated(new Date()); volume.setStatus(AsyncInstanceCreateStatus.Creating); + volume.setSourceType(SourceType.Snapshot); + volume.setSourceId(snapshot.getId()); volume = _volsDao.persist(volume); volumeId = volume.getId(); @@ -853,18 +856,24 @@ public class StorageManagerImpl implements StorageManager { if (Storage.ImageFormat.ISO == template.getFormat()) { rootVol = new VolumeVO(VolumeType.ROOT, vm.getId(), vm.getInstanceName() + "-ROOT", dc.getId(), pod.getId(), account.getId(), account.getDomainId(),(size>0)? size : diskOffering.getDiskSizeInBytes()); rootVol.setDiskOfferingId(diskOffering.getId()); + rootVol.setSourceType(SourceType.Template); + rootVol.setSourceId(template.getId()); rootVol.setDeviceId(0l); rootVol = _volsDao.persist(rootVol); } else { rootVol = new VolumeVO(VolumeType.ROOT, vm.getId(), template.getId(), vm.getInstanceName() + "-ROOT", dc.getId(), pod.getId(), account.getId(), account.getDomainId(), offering.isRecreatable()); rootVol.setDiskOfferingId(offering.getId()); rootVol.setTemplateId(template.getId()); + rootVol.setSourceId(template.getId()); + rootVol.setSourceType(SourceType.Template); rootVol.setDeviceId(0l); rootVol = _volsDao.persist(rootVol); if (diskOffering != null && diskOffering.getDiskSizeInBytes() > 0) { dataVol = new VolumeVO(VolumeType.DATADISK, vm.getId(), vm.getInstanceName() + "-DATA", dc.getId(), pod.getId(), account.getId(), account.getDomainId(), (size>0)? size : diskOffering.getDiskSizeInBytes()); dataVol.setDiskOfferingId(diskOffering.getId()); + dataVol.setSourceType(SourceType.DiskOffering); + dataVol.setSourceId(diskOffering.getId()); dataVol.setDeviceId(1l); dataVol = _volsDao.persist(dataVol); } @@ -1572,7 +1581,7 @@ public class StorageManagerImpl implements StorageManager { // Create the Volume object and save it so that we can return it to the user Account account = _accountDao.findById(accountId); - VolumeVO volume = new VolumeVO(null, userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, 0, Volume.VolumeType.DATADISK); + VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1, new Long(-1), null, null, 0, Volume.VolumeType.DATADISK); volume.setPoolId(null); volume.setDataCenterId(dc.getId()); volume.setPodId(null); @@ -1585,6 +1594,8 @@ public class StorageManagerImpl implements StorageManager { volume.setUpdated(new Date()); volume.setStatus(AsyncInstanceCreateStatus.Creating); volume.setDomainId(account.getDomainId()); + volume.setSourceId(diskOffering.getId()); + volume.setSourceType(SourceType.DiskOffering); volume = _volsDao.persist(volume); AsyncJobExecutor asyncExecutor = BaseAsyncJobExecutor.getCurrentExecutor(); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 4b23fa18abb..c4c28ecb2aa 100644 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -254,6 +254,8 @@ CREATE TABLE `cloud`.`volumes` ( `removed` datetime COMMENT 'Date removed. not null if removed', `status` varchar(32) COMMENT 'Async API volume creation status', `state` varchar(32) COMMENT 'State machine', + `source_id` bigint unsigned COMMENT 'id for the source', + `source_type` varchar(32) COMMENT 'source from which the volume is created -- snapshot, diskoffering, template, blank', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/setup/db/migration/schema-21to22.sql b/setup/db/migration/schema-21to22.sql index 108ed2a9e20..dff1e91ae52 100644 --- a/setup/db/migration/schema-21to22.sql +++ b/setup/db/migration/schema-21to22.sql @@ -7,3 +7,5 @@ ALTER TABLE `cloud`.`data_center` MODIFY COLUMN `guest_network_cidr` varchar(18) ALTER TABLE `cloud`.`resource_count` ADD COLUMN `domain_id` bigint unsigned; -- add the new column ALTER TABLE `cloud`.`resource_count` MODIFY COLUMN `account_id` bigint unsigned; -- modify the column to allow NULL values ALTER TABLE `cloud`.`storage_pool` add COLUMN STATUS varchar(32) not null; -- new status column for maintenance mode support for primary storage +ALTER TABLE `cloud`.`volumes` ADD COLUMN `source_id` bigint unsigned; -- id for the source +ALTER TABLE `cloud`.`volumes` ADD COLUMN `source_type` varchar(32); --source from which the volume is created i.e. snapshot, diskoffering, template, blank