From 109fe6fc702dcb868e5ceae464a26ddb993052ec Mon Sep 17 00:00:00 2001 From: Naredula Janardhana Reddy Date: Mon, 19 Dec 2011 09:56:11 +0530 Subject: [PATCH 01/69] Bug 12445: Added DeleteSnapshotBackupCommand to ssvm. --- .../com/cloud/storage/resource/NfsSecondaryStorageResource.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index 678ad623fc2..20584a2efb1 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -153,6 +153,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return execute((ListTemplateCommand)cmd); } else if (cmd instanceof downloadSnapshotFromSwiftCommand){ return execute((downloadSnapshotFromSwiftCommand)cmd); + } else if (cmd instanceof DeleteSnapshotBackupCommand){ + return execute((DeleteSnapshotBackupCommand)cmd); } else if (cmd instanceof DeleteSnapshotsDirCommand){ return execute((DeleteSnapshotsDirCommand)cmd); } else if (cmd instanceof downloadTemplateFromSwiftToSecondaryStorageCommand) { From c3903673bcc5f07c7ed958eb04e8807e42541279 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Fri, 16 Dec 2011 17:41:29 +0530 Subject: [PATCH 02/69] upgrade schema changes for simulator_name_label on physical_network_traffic_type --- setup/db/db/schema-2214to30.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup/db/db/schema-2214to30.sql b/setup/db/db/schema-2214to30.sql index 6ea206197c5..56178f103c2 100755 --- a/setup/db/db/schema-2214to30.sql +++ b/setup/db/db/schema-2214to30.sql @@ -496,3 +496,5 @@ CREATE TABLE `cloud`.`op_user_stats_log` ( `updated` datetime COMMENT 'stats update timestamp', UNIQUE KEY (`user_stats_id`, `updated`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `simulator_network_label` varchar(255) COMMENT 'The name labels needed for identifying the simulator'; From 18f865fc3e488094662e4944747ac6cb567ab45f Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 19 Dec 2011 11:05:28 +0530 Subject: [PATCH 03/69] Reviving the simulator * SSVM to act as a direct connect agent * Storage Resources handle SSVM commands * create-schema.sql already has simulator_network_label. removing the label from create-schema-simulator.sql --- .gitignore | 3 +- .../agent/manager/MockAgentManagerImpl.java | 12 +- .../cloud/resource/AgentStorageResource.java | 3 +- build/replace.properties | 2 +- setup/db/create-schema-simulator.sql | 4 - tools/testClient/deployDataCenter.py | 2 + .../sandbox/advanced/xen.properties | 18 +-- tools/testClient/sandbox/simulator/setup.py | 113 ++++++++---------- .../sandbox/simulator/tests/testProvision.py | 5 - 9 files changed, 71 insertions(+), 91 deletions(-) diff --git a/.gitignore b/.gitignore index af4d3baf996..784ca1b1ba3 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ dist/ cloud-*.tar.bz2 *.log *.pyc +*.cfg build.number api.log.*.gz cloud.log.*.* @@ -23,4 +24,4 @@ unittest deps/cloud.userlibraries .DS_Store .idea -*.iml \ No newline at end of file +*.iml diff --git a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java index 6e2be2f31d1..648d196663d 100755 --- a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java +++ b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java @@ -29,6 +29,7 @@ import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationAnswer; import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.StartupCommand; import com.cloud.dc.dao.HostPodDao; import com.cloud.host.Host.Type; import com.cloud.resource.AgentResourceBase; @@ -264,18 +265,15 @@ public class MockAgentManagerImpl implements MockAgentManager { params.put("guid", this.guid); storageResource.configure("secondaryStorage", params); storageResource.start(); + StartupCommand[] cmds = storageResource.initialize(); + _resourceMgr.createHostVOForConnectedAgent(cmds); + _resources.put(this.guid, storageResource); } catch (ConfigurationException e) { s_logger.debug("Failed to load secondary storage resource: " + e.toString()); return; } - Map details = new HashMap(); - - _resourceMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details); - _resources.put(this.guid, storageResource); - } - + } } - } @Override diff --git a/agent-simulator/src/com/cloud/resource/AgentStorageResource.java b/agent-simulator/src/com/cloud/resource/AgentStorageResource.java index 48793257d04..2e5460adb1d 100644 --- a/agent-simulator/src/com/cloud/resource/AgentStorageResource.java +++ b/agent-simulator/src/com/cloud/resource/AgentStorageResource.java @@ -18,6 +18,7 @@ import com.cloud.agent.api.ReadyAnswer; import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand; +import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.storage.ssCommand; import com.cloud.agent.manager.SimulatorManager; import com.cloud.agent.manager.SimulatorManager.AgentType; @@ -67,7 +68,7 @@ public class AgentStorageResource extends AgentResourceBase implements Secondary @Override public StartupCommand[] initialize() { - StartupSecondaryStorageCommand cmd = new StartupSecondaryStorageCommand(); + StartupStorageCommand cmd = new StartupStorageCommand(); cmd.setPrivateIpAddress(agentHost.getPrivateIpAddress()); cmd.setPrivateNetmask(agentHost.getPrivateNetMask()); diff --git a/build/replace.properties b/build/replace.properties index 47724fd9e22..fc106e604f1 100644 --- a/build/replace.properties +++ b/build/replace.properties @@ -6,4 +6,4 @@ DBHOST=localhost AGENTLOGDIR=logs AGENTLOG=logs/agent.log MSMNTDIR=/mnt -COMPONENTS-SPEC=components-premium.xml +COMPONENTS-SPEC=components-simulator.xml diff --git a/setup/db/create-schema-simulator.sql b/setup/db/create-schema-simulator.sql index 8c01a025e4a..ac8f319c36d 100644 --- a/setup/db/create-schema-simulator.sql +++ b/setup/db/create-schema-simulator.sql @@ -103,7 +103,3 @@ CREATE TABLE `cloud`.`mocksecurityrules` ( INDEX `i_mocksecurityrules__vmid`(`vmid`), INDEX `i_mocksecurityrules__hostid`(`hostid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - --- Some alterations reqd for the simulator to work with a regular DB -ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `simulator_network_label` varchar(255) COMMENT 'The name labels needed for identifying the simulator' diff --git a/tools/testClient/deployDataCenter.py b/tools/testClient/deployDataCenter.py index 470b59aaee8..b8f4fafa24c 100644 --- a/tools/testClient/deployDataCenter.py +++ b/tools/testClient/deployDataCenter.py @@ -142,6 +142,8 @@ class deployDataCenters(): self.createVlanIpRanges("Advanced", ipranges, zoneId, networkId=networkId) def configureProviders(self, providers, zoneid, networktype): + if providers == None: + return for prov in providers: pnets = listPhysicalNetworks.listPhysicalNetworksCmd() pnets.zoneid = zoneid diff --git a/tools/testClient/sandbox/advanced/xen.properties b/tools/testClient/sandbox/advanced/xen.properties index 4d44e07e067..90c2f710fe3 100644 --- a/tools/testClient/sandbox/advanced/xen.properties +++ b/tools/testClient/sandbox/advanced/xen.properties @@ -15,22 +15,22 @@ check.pod.cidrs=true secstorage.allowed.internal.sites=10.147.28.0/24 [environment] dns=10.147.28.6 -mshost=localhost +mshost=10.147.29.110 database=localhost hypervisor=XenServer [cloudstack] -guest.vlan=675-679 +guest.vlan=670-674 #pod configuration private.gateway=10.147.29.1 -private.pod.startip=10.147.29.150 -private.pod.endip=10.147.29.159 +private.pod.startip=10.147.29.140 +private.pod.endip=10.147.29.149 #public vlan range public.gateway=10.147.31.1 public.vlan=31 -public.vlan.startip=10.147.31.150 -public.vlan.endip=10.147.31.159 +public.vlan.startip=10.147.31.140 +public.vlan.endip=10.147.31.149 #hosts -host=10.147.29.57 +host=10.147.29.56 #pools -pool=nfs://10.147.28.6:/export/home/prasanna/budhgaya -secondary=nfs://10.147.28.6:/export/home/prasanna/sstor +pool=nfs://10.147.28.6:/export/home/prasanna/taxila +secondary=nfs://10.147.28.6:/export/home/prasanna/secondary diff --git a/tools/testClient/sandbox/simulator/setup.py b/tools/testClient/sandbox/simulator/setup.py index 194e8f716ea..3dda7d62a3b 100644 --- a/tools/testClient/sandbox/simulator/setup.py +++ b/tools/testClient/sandbox/simulator/setup.py @@ -8,106 +8,87 @@ ############################################################ ''' +from ConfigParser import SafeConfigParser from optparse import OptionParser from configGenerator import * import random -def getGlobalSettings(): - global_settings = {'expunge.delay': '60', - 'expunge.interval': '60', - 'expunge.workers': '3', - 'workers': '10', - 'use.user.concentrated.pod.allocation': 'false', - 'vm.allocation.algorithm': 'random', - 'vm.op.wait.interval': '5', - 'guest.domain.suffix': 'sandbox.simulator', - 'instance.name': 'SIMQA', - 'direct.agent.load.size': '1000', - 'default.page.size': '10000', - 'linkLocalIp.nums': '10', - 'check.pod.cidrs': 'false', - } - for k, v in global_settings.iteritems(): +def getGlobalSettings(config): + for k, v in dict(config.items('globals')).iteritems(): cfg = configuration() cfg.name = k cfg.value = v yield cfg -def describeResources(dbnode='localhost', mshost='localhost'): +def describeResources(config): zs = cloudstackConfiguration() - numberofpods = 1 - - clustersPerPod = 10 - hostsPerCluster = 2 z = zone() - z.dns1 = '4.2.2.2' - z.dns2 = '10.223.110.254' - z.internaldns1 = '10.147.28.6' - z.internaldns2 = '10.223.110.254' - z.name = 'Sandbox-Simulator' + z.dns1 = config.get('environment', 'dns') + z.internaldns1 = config.get('environment', 'dns') + z.name = 'Sandbox-%s'%(config.get('environment', 'hypervisor')) z.networktype = 'Advanced' z.guestcidraddress = '10.1.1.0/24' - z.vlan='100-300' + + prov = provider() + prov.vlan = config.get('cloudstack','guest.vlan') + z.providers.append(prov) p = pod() p.name = 'POD0' - p.gateway = '172.1.1.1' - p.startip = '172.1.1.2' - p.endip = '172.1.1.200' + p.gateway = config.get('cloudstack', 'private.gateway') + p.startip = config.get('cloudstack', 'private.pod.startip') + p.endip = config.get('cloudstack', 'private.pod.endip') p.netmask = '255.255.255.0' v = iprange() - v.vlan = '30' - v.gateway = '172.1.2.1' - v.startip = '172.1.2.2' - v.endip = '172.1.2.200' + v.gateway = config.get('cloudstack', 'public.gateway') + v.startip = config.get('cloudstack', 'public.vlan.startip') + v.endip = config.get('cloudstack', 'public.vlan.endip') v.netmask = '255.255.255.0' + v.vlan = config.get('cloudstack', 'public.vlan') + z.ipranges.append(v) - curhost = 1 - for i in range(1, clustersPerPod + 1): - c = cluster() - c.clustername = 'POD1-CLUSTER' + str(i) - c.hypervisor = 'Simulator' - c.clustertype = 'CloudManaged' + c = cluster() + c.clustername = 'C0' + c.hypervisor = config.get('environment', 'hypervisor') + c.clustertype = 'CloudManaged' - for j in range(1, hostsPerCluster + 1): - h = host() - h.username = 'root' - h.password = 'password' - h.url = 'http://sim/test-%d'%(curhost) - c.hosts.append(h) - curhost = curhost + 1 + h = host() + h.username = 'root' + h.password = 'password' + h.url = 'http://%s'%(config.get('cloudstack', 'host')) + c.hosts.append(h) - ps = primaryStorage() - ps.name = 'spool'+str(i) - ps.url = 'nfs://172.16.24.32/export/path/'+str(i) - c.primaryStorages.append(ps) - p.clusters.append(c) + ps = primaryStorage() + ps.name = 'PS0' + ps.url = config.get('cloudstack', 'pool') + c.primaryStorages.append(ps) + p.clusters.append(c) + z.pods.append(p) secondary = secondaryStorage() - secondary.url = 'nfs://172.16.25.32/secondary/path' - - z.pods.append(p) - z.ipranges.append(v) + secondary.url = config.get('cloudstack', 'secondary') z.secondaryStorages.append(secondary) + + '''Add zone''' zs.zones.append(z) '''Add mgt server''' mgt = managementServer() - mgt.mgtSvrIp = mshost + mgt.mgtSvrIp = config.get('environment', 'mshost') zs.mgtSvr.append(mgt) '''Add a database''' db = dbServer() - db.dbSvr = opts.dbnode + db.dbSvr = config.get('environment', 'database') zs.dbSvr = db '''Add some configuration''' - [zs.globalConfig.append(cfg) for cfg in getGlobalSettings()] + [zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)] ''''add loggers''' testClientLogger = logger() @@ -125,10 +106,16 @@ def describeResources(dbnode='localhost', mshost='localhost'): if __name__ == '__main__': parser = OptionParser() - parser.add_option('-o', '--output', action='store', default='./sandbox.cfg', dest='output', help='the path where the json config file generated') - parser.add_option('-d', '--dbnode', dest='dbnode', help='hostname/ip of the database node', action='store') - parser.add_option('-m', '--mshost', dest='mshost', help='hostname/ip of management server', action='store') + parser.add_option('-i', '--input', action='store', default='setup.properties', \ + dest='input', help='file containing environment setup information') + parser.add_option('-o', '--output', action='store', default='./sandbox.cfg', \ + dest='output', help='path where environment json will be generated') + (opts, args) = parser.parse_args() - cfg = describeResources(opts.dbnode, opts.mshost) + + cfg_parser = SafeConfigParser() + cfg_parser.read(opts.input) + + cfg = describeResources(cfg_parser) generate_setup_config(cfg, opts.output) diff --git a/tools/testClient/sandbox/simulator/tests/testProvision.py b/tools/testClient/sandbox/simulator/tests/testProvision.py index 5388d1041ec..ebaf6eee176 100644 --- a/tools/testClient/sandbox/simulator/tests/testProvision.py +++ b/tools/testClient/sandbox/simulator/tests/testProvision.py @@ -1,9 +1,4 @@ #!/usr/bin/env python -try: - import unittest2 as unittest -except ImportError: - import unittest - import random import hashlib from cloudstackTestCase import * From f2241bfef6d25414aa5a2f400d40950167b35e11 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 19 Dec 2011 11:50:42 +0530 Subject: [PATCH 04/69] change to direct agent --- .../src/com/cloud/agent/manager/MockAgentManagerImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java index 648d196663d..5d0e454db4b 100755 --- a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java +++ b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java @@ -31,6 +31,7 @@ import com.cloud.agent.api.PrepareForMigrationAnswer; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.dc.dao.HostPodDao; +import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.resource.AgentResourceBase; import com.cloud.resource.AgentRoutingResource; @@ -266,7 +267,8 @@ public class MockAgentManagerImpl implements MockAgentManager { storageResource.configure("secondaryStorage", params); storageResource.start(); StartupCommand[] cmds = storageResource.initialize(); - _resourceMgr.createHostVOForConnectedAgent(cmds); + //on the simulator the ssvm is as good as a direct agent + _resourceMgr.addHost(mockHost.getDataCenterId(), storageResource, Host.Type.SecondaryStorageVM, null); _resources.put(this.guid, storageResource); } catch (ConfigurationException e) { s_logger.debug("Failed to load secondary storage resource: " + e.toString()); From 58b53f0d3c2b3b1789eabb379fd4fd6c21c7250e Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 19 Dec 2011 15:02:19 +0530 Subject: [PATCH 05/69] SimulatorSecondaryDiscoverer implements the resource protocol to recieve resource state transition events related to secondary storage VM from the ResourceManager. --- .../agent/manager/MockAgentManagerImpl.java | 5 +- .../cloud/resource/AgentStorageResource.java | 2 +- .../cloud/resource/SimulatorDiscoverer.java | 2 - .../SimulatorSecondaryDiscoverer.java | 111 +++++++++++++++++- 4 files changed, 112 insertions(+), 8 deletions(-) diff --git a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java index 5d0e454db4b..e59824f0cdb 100755 --- a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java +++ b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java @@ -263,12 +263,13 @@ public class MockAgentManagerImpl implements MockAgentManager { AgentStorageResource storageResource = new AgentStorageResource(); try { Map params = new HashMap(); + Map details = new HashMap(); params.put("guid", this.guid); + details.put("guid", this.guid); storageResource.configure("secondaryStorage", params); storageResource.start(); - StartupCommand[] cmds = storageResource.initialize(); //on the simulator the ssvm is as good as a direct agent - _resourceMgr.addHost(mockHost.getDataCenterId(), storageResource, Host.Type.SecondaryStorageVM, null); + _resourceMgr.addHost(mockHost.getDataCenterId(), storageResource, Host.Type.SecondaryStorageVM, details); _resources.put(this.guid, storageResource); } catch (ConfigurationException e) { s_logger.debug("Failed to load secondary storage resource: " + e.toString()); diff --git a/agent-simulator/src/com/cloud/resource/AgentStorageResource.java b/agent-simulator/src/com/cloud/resource/AgentStorageResource.java index 2e5460adb1d..9bc0f48afdc 100644 --- a/agent-simulator/src/com/cloud/resource/AgentStorageResource.java +++ b/agent-simulator/src/com/cloud/resource/AgentStorageResource.java @@ -68,7 +68,7 @@ public class AgentStorageResource extends AgentResourceBase implements Secondary @Override public StartupCommand[] initialize() { - StartupStorageCommand cmd = new StartupStorageCommand(); + StartupSecondaryStorageCommand cmd = new StartupSecondaryStorageCommand(); cmd.setPrivateIpAddress(agentHost.getPrivateIpAddress()); cmd.setPrivateNetmask(agentHost.getPrivateNetMask()); diff --git a/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java b/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java index 3b9b789e4f4..420853def10 100755 --- a/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java +++ b/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java @@ -307,7 +307,6 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L @Override public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { - // TODO Auto-generated method stub return null; } @@ -331,7 +330,6 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L @Override public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { - // TODO Auto-generated method stub return null; } diff --git a/agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java b/agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java index d3b74f29057..6fd0c6e226f 100644 --- a/agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java +++ b/agent-simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java @@ -6,17 +6,34 @@ import java.util.Map; import javax.ejb.Local; import javax.naming.ConfigurationException; +import com.cloud.agent.AgentManager; +import com.cloud.agent.Listener; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupSecondaryStorageCommand; import com.cloud.agent.manager.MockStorageManager; +import com.cloud.exception.ConnectionException; import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.secondary.SecondaryStorageDiscoverer; import com.cloud.utils.component.Inject; +import com.cloud.utils.exception.CloudRuntimeException; @Local(value=Discoverer.class) -public class SimulatorSecondaryDiscoverer extends SecondaryStorageDiscoverer { - @Inject - MockStorageManager _mockStorageMgr = null; +public class SimulatorSecondaryDiscoverer extends SecondaryStorageDiscoverer implements ResourceStateAdapter, Listener { + @Inject MockStorageManager _mockStorageMgr = null; + @Inject AgentManager _agentMgr; + @Inject ResourceManager _resourceMgr; + @Inject SnapshotDao _snapshotDao; @Override public boolean configure(String name, Map params) throws ConfigurationException { + _agentMgr.registerForHostEvents(this, true, false, false); + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return super.configure(name, params); } @@ -27,4 +44,92 @@ public class SimulatorSecondaryDiscoverer extends SecondaryStorageDiscoverer { _mockStorageMgr.preinstallTemplates(host.getStorageUrl(), host.getDataCenterId()); } } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, + StartupCommand[] cmd) { + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, + StartupCommand[] startup, ServerResource resource, + Map details, List hostTags) { + //for detecting SSVM dispatch + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupSecondaryStorageCommand)) { + return null; + } + + host.setType(com.cloud.host.Host.Type.SecondaryStorageVM); + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, + boolean isForceDeleteStorage) throws UnableDeleteHostException { + long hostId = host.getId(); + List snapshots = _snapshotDao.listByHostId(hostId); + if (snapshots != null && !snapshots.isEmpty()) { + throw new CloudRuntimeException("Cannot delete this secondary storage because there are still snapshots on it "); + } + _vmTemplateHostDao.deleteByHost(hostId); + host.setGuid(null); + _hostDao.update(hostId, host); + _hostDao.remove(hostId); + return new DeleteHostAnswer(true); + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return true; + } + + @Override + public int getTimeout() { + return 0; + } + + @Override + public boolean isRecurring() { + return false; + } + + @Override + public boolean processAnswers(long agentId, long seq, Answer[] answers) { + return false; + } + + @Override + public boolean processCommands(long agentId, long seq, Command[] commands) { + return false; + } + + @Override + public void processConnect(HostVO host, StartupCommand cmd, + boolean forRebalance) throws ConnectionException { + + } + + @Override + public AgentControlAnswer processControlCommand(long agentId, + AgentControlCommand cmd) { + return null; + } + + @Override + public boolean processDisconnect(long agentId, Status state) { + return false; + } + + @Override + public boolean processTimeout(long agentId, long seq) { + return false; + } } From d99c0d5528a7c8ea6a61222e32c48128ddb6699b Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 19 Dec 2011 15:32:56 +0530 Subject: [PATCH 06/69] reverting faulty checkin --- build/replace.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/replace.properties b/build/replace.properties index fc106e604f1..47724fd9e22 100644 --- a/build/replace.properties +++ b/build/replace.properties @@ -6,4 +6,4 @@ DBHOST=localhost AGENTLOGDIR=logs AGENTLOG=logs/agent.log MSMNTDIR=/mnt -COMPONENTS-SPEC=components-simulator.xml +COMPONENTS-SPEC=components-premium.xml From 62b571a5284c575b0e64567e92488ed75e587650 Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 09:47:53 -0800 Subject: [PATCH 07/69] bug 12612: Implement 'view all' pre-filter Example: detailView: { ... viewAll: { ... preFilter: { // Return true to show button; false to hide return false; } } } --- ui/scripts/ui/widgets/detailView.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js index 54ff39905c8..5d099a2875c 100644 --- a/ui/scripts/ui/widgets/detailView.js +++ b/ui/scripts/ui/widgets/detailView.js @@ -731,7 +731,14 @@ }).prependTo($firstRow.closest('div.detail-group').closest('.details')); // 'View all' button - if (detailViewArgs.viewAll) { + var showViewAll = detailViewArgs.viewAll ? + ( + detailViewArgs.viewAll.preFilter ? + detailViewArgs.viewAll.preFilter({ + context: context + }) : true + ) : true; + if (detailViewArgs.viewAll && showViewAll) { $('
') .addClass('view-all') .append( From 4f058feef231f2dfdedf67fe058936cead05db43 Mon Sep 17 00:00:00 2001 From: Murali reddy Date: Mon, 19 Dec 2011 23:47:11 +0530 Subject: [PATCH 08/69] bug 12276: public IP's should be associated with a network service provider depending on the network rules for which IP is used for --- .../element/LoadBalancingServiceProvider.java | 10 +++ .../PortForwardingServiceProvider.java | 10 +++ .../element/SourceNatServiceProvider.java | 15 ++++ .../element/StaticNatServiceProvider.java | 10 +++ .../com/cloud/network/NetworkManagerImpl.java | 77 ++++++++++++++++++- .../element/ElasticLoadBalancerElement.java | 7 ++ .../F5ExternalLoadBalancerElement.java | 7 ++ .../JuniperSRXExternalFirewallElement.java | 16 ++-- .../NetscalerExternalLoadBalancerElement.java | 7 ++ .../network/element/VirtualRouterElement.java | 16 ++++ 10 files changed, 164 insertions(+), 11 deletions(-) diff --git a/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java b/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java index 32b9b4776e9..7d31f3cd7fe 100644 --- a/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java +++ b/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java @@ -4,6 +4,7 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; +import com.cloud.network.PublicIpAddress; import com.cloud.network.lb.LoadBalancingRule; public interface LoadBalancingServiceProvider extends NetworkElement { @@ -15,4 +16,13 @@ public interface LoadBalancingServiceProvider extends NetworkElement { * @throws ResourceUnavailableException */ boolean applyLBRules(Network network, List rules) throws ResourceUnavailableException; + + /** + * Apply ip addresses to this network service provider + * @param network + * @param ipAddress + * @return + * @throws ResourceUnavailableException + */ + boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/element/PortForwardingServiceProvider.java b/api/src/com/cloud/network/element/PortForwardingServiceProvider.java index bdd6bc01da4..2bcdc8c7fa0 100644 --- a/api/src/com/cloud/network/element/PortForwardingServiceProvider.java +++ b/api/src/com/cloud/network/element/PortForwardingServiceProvider.java @@ -4,6 +4,7 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; +import com.cloud.network.PublicIpAddress; import com.cloud.network.rules.PortForwardingRule; public interface PortForwardingServiceProvider extends NetworkElement { @@ -15,4 +16,13 @@ public interface PortForwardingServiceProvider extends NetworkElement { * @throws ResourceUnavailableException */ boolean applyPFRules(Network network, List rules) throws ResourceUnavailableException; + + /** + * Apply ip addresses to this network service provider + * @param network + * @param ipAddress + * @return + * @throws ResourceUnavailableException + */ + boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/element/SourceNatServiceProvider.java b/api/src/com/cloud/network/element/SourceNatServiceProvider.java index d21e0b660a1..f42c445997c 100644 --- a/api/src/com/cloud/network/element/SourceNatServiceProvider.java +++ b/api/src/com/cloud/network/element/SourceNatServiceProvider.java @@ -1,4 +1,19 @@ package com.cloud.network.element; +import java.util.List; + +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.network.PublicIpAddress; + public interface SourceNatServiceProvider extends NetworkElement { + + /** + * Apply ip addresses to this network + * @param network + * @param ipAddress + * @return + * @throws ResourceUnavailableException + */ + boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/element/StaticNatServiceProvider.java b/api/src/com/cloud/network/element/StaticNatServiceProvider.java index c73ce2b77c5..c5c0608fe76 100644 --- a/api/src/com/cloud/network/element/StaticNatServiceProvider.java +++ b/api/src/com/cloud/network/element/StaticNatServiceProvider.java @@ -4,6 +4,7 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; +import com.cloud.network.PublicIpAddress; import com.cloud.network.rules.StaticNat; public interface StaticNatServiceProvider extends NetworkElement { @@ -15,4 +16,13 @@ public interface StaticNatServiceProvider extends NetworkElement { * @throws ResourceUnavailableException */ boolean applyStaticNats(Network config, List rules) throws ResourceUnavailableException; + + /** + * Apply ip addresses to this network service provider + * @param network + * @param ipAddress + * @return + * @throws ResourceUnavailableException + */ + boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException; } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 92ea5c8fc39..57bd3cb5768 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -601,8 +601,79 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag return success; } + protected boolean applyProviderIpAssociations(Network network, Purpose purpose, boolean continueOnError, List rules) throws ResourceUnavailableException { + boolean success = true; + + List publicIps = new ArrayList(); + for (FirewallRule rule : rules) { + IPAddressVO lbIp = _ipAddressDao.findById(rule.getSourceIpAddressId()); + PublicIp publicIp = new PublicIp(lbIp, _vlanDao.findById(lbIp.getVlanId()), NetUtils.createSequenceBasedMacAddress(lbIp.getMacAddress())); + publicIps.add(publicIp); + } + + for (NetworkElement ne : _networkElements) { + try { + boolean handled; + switch (purpose) { + case LoadBalancing: + if (!(ne instanceof LoadBalancingServiceProvider)) { + continue; + } + LoadBalancingServiceProvider lbProvider = (LoadBalancingServiceProvider) ne; + s_logger.trace("Asking " + ne + " to apply ip associations for " + purpose.toString() + " purpose"); + handled = lbProvider.applyLoadBalancerIp(network, publicIps); + break; + + case PortForwarding: + if (!(ne instanceof PortForwardingServiceProvider)) { + continue; + } + PortForwardingServiceProvider pfProvider = (PortForwardingServiceProvider) ne; + s_logger.trace("Asking " + ne + " to apply ip associations for " + purpose.toString() + " purpose"); + handled = pfProvider.applyIps(network, publicIps); + break; + + case StaticNat: + case Firewall: + if (!(ne instanceof FirewallServiceProvider)) { + continue; + } + s_logger.trace("Asking " + ne + " to apply ip associations for " + purpose.toString() + " purpose"); + FirewallServiceProvider fwProvider = (FirewallServiceProvider) ne; + handled = fwProvider.applyIps(network, publicIps); + break; + + default: + s_logger.debug("Unable to handle IP association for purpose: " + purpose.toString()); + handled = false; + } + s_logger.debug("Network Rules for network " + network.getId() + " were " + (handled ? "" : " not") + " handled by " + ne.getName()); + } catch (ResourceUnavailableException e) { + success = false; + if (!continueOnError) { + throw e; + } else { + s_logger.debug("Resource is not available: " + ne.getName(), e); + } + } + } + return success; + } + protected boolean applyIpAssociations(Network network, boolean continueOnError, List publicIps) throws ResourceUnavailableException { boolean success = true; + List srcNatpublicIps = new ArrayList(); + + // apply IP only for source NAT public IP at this point. Depending on the network service for which + // public IP will be used do IP Association to respective network service provider before apply rules + if (publicIps != null && !publicIps.isEmpty()) { + for (PublicIp ip : publicIps) { + if (ip.isSourceNat()) { + srcNatpublicIps.add(ip); + } + } + } + for (NetworkElement element : _networkElements) { try { if (!(element instanceof FirewallServiceProvider)) { @@ -610,7 +681,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag } FirewallServiceProvider e = (FirewallServiceProvider)element; s_logger.trace("Asking " + element + " to apply ip associations"); - e.applyIps(network, publicIps); + e.applyIps(network, srcNatpublicIps); } catch (ResourceUnavailableException e) { success = false; if (!continueOnError) { @@ -2583,6 +2654,10 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag boolean success = true; Network network = _networksDao.findById(rules.get(0).getNetworkId()); Purpose purpose = rules.get(0).getPurpose(); + + // associate the IP with corresponding network service provider + applyProviderIpAssociations(network, purpose, continueOnError, rules); + for (NetworkElement ne : _networkElements) { try { boolean handled; diff --git a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java index cbb429a4465..3fc8f11bbb4 100644 --- a/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/ElasticLoadBalancerElement.java @@ -39,6 +39,7 @@ import com.cloud.network.Network.Service; import com.cloud.network.NetworkManager; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.PublicIpAddress; import com.cloud.network.dao.NetworkDao; import com.cloud.network.lb.ElasticLoadBalancerManager; import com.cloud.network.lb.LoadBalancingRule; @@ -179,4 +180,10 @@ public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalan public boolean verifyServicesCombination(List services) { return true; } + + @Override + public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 6f58a9a3b4b..68567f88dbc 100644 --- a/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -66,6 +66,7 @@ import com.cloud.network.NetworkManager; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkVO; +import com.cloud.network.PublicIpAddress; import com.cloud.network.dao.ExternalLoadBalancerDeviceDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkExternalLoadBalancerDao; @@ -440,4 +441,10 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan public boolean verifyServicesCombination(List services) { return true; } + + @Override + public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { + // return true, as IP will be associated as part of LB rule configuration + return true; + } } diff --git a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index c70f2280b85..17daa651b69 100644 --- a/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/server/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -175,16 +175,6 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan return true; } - @Override - public boolean applyIps(Network network, List ipAddresses) throws ResourceUnavailableException { - if (!canHandle(network)) { - return false; - } - - return applyIps(network, ipAddresses); - } - - @Override public boolean applyFWRules(Network config, List rules) throws ResourceUnavailableException { if (!canHandle(config)) { @@ -505,4 +495,10 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan public boolean verifyServicesCombination(List services) { return true; } + + @Override + public boolean applyIps(Network network, List ipAddress) throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } } \ No newline at end of file diff --git a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java index 06c638461d4..a87e9a98327 100644 --- a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java @@ -64,6 +64,7 @@ import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkVO; +import com.cloud.network.PublicIpAddress; import com.cloud.network.dao.ExternalLoadBalancerDeviceDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkExternalLoadBalancerDao; @@ -465,4 +466,10 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe public boolean verifyServicesCombination(List services) { return true; } + + @Override + public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { + // return true, as IP will be associated as part of LB rule configuration + return true; + } } \ No newline at end of file diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 024a8097fc4..57a3ce0f2d4 100644 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -270,6 +270,21 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } } + @Override + public boolean applyLoadBalancerIp(Network network, List ipAddress) throws ResourceUnavailableException { + if (canHandle(network, Service.Lb)) { + List routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); + if (routers == null || routers.isEmpty()) { + s_logger.debug("Virtual router element doesn't need to associate load balancer ip addresses on the backend; virtual router doesn't exist in the network " + network.getId()); + return true; + } + + return _routerMgr.associateIP(network, ipAddress, routers); + } else { + return false; + } + } + @Override public Provider getProvider() { return Provider.VirtualRouter; @@ -644,4 +659,5 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl } return true; } + } From 742c9c9a45244d8f6dddbce8325f2c93c109ece0 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 10:23:36 -0800 Subject: [PATCH 09/69] bug 12615: fixed resource limits - treat -1 as unlimited for domain limit status 12615: resolved fixed --- api/src/com/cloud/configuration/Resource.java | 2 ++ .../resourcelimit/ResourceLimitManagerImpl.java | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/src/com/cloud/configuration/Resource.java b/api/src/com/cloud/configuration/Resource.java index 4c9cda41058..f9a05f09143 100644 --- a/api/src/com/cloud/configuration/Resource.java +++ b/api/src/com/cloud/configuration/Resource.java @@ -18,6 +18,8 @@ package com.cloud.configuration; public interface Resource { + + public static final short RESOURCE_UNLIMITED = -1; public enum ResourceType{ user_vm ("user_vm", 0, ResourceOwnerType.Account, ResourceOwnerType.Domain), diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 6bc6a7f054e..9eb61dc8744 100755 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -200,7 +200,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ @Override public long findCorrectResourceLimitForAccount(Account account, ResourceType type) { - long max = -1; //if resource limit is not found, then we treat it as unlimited + long max = Resource.RESOURCE_UNLIMITED; //if resource limit is not found, then we treat it as unlimited ResourceLimitVO limit = _resourceLimitDao.findByOwnerIdAndType(account.getId(), ResourceOwnerType.Account, type); // Check if limit is configured for account @@ -224,7 +224,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ @Override public long findCorrectResourceLimitForDomain(Domain domain, ResourceType type) { - long max = -1; + long max = Resource.RESOURCE_UNLIMITED; // Check account ResourceLimitVO limit = _resourceLimitDao.findByOwnerIdAndType(domain.getId(), ResourceOwnerType.Domain, type); @@ -274,7 +274,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ // Check account limits long accountLimit = findCorrectResourceLimitForAccount(account, type); long potentialCount = _resourceCountDao.getResourceCount(account.getId(), ResourceOwnerType.Account, type) + numResources; - if (accountLimit != -1 && potentialCount > accountLimit) { + if (accountLimit != Resource.RESOURCE_UNLIMITED && potentialCount > accountLimit) { String message = "Maximum number of resources of type \"" + type + "\" for account name=" + account.getAccountName() + " in domain id=" + account.getDomainId() + " has been exceeded."; if (project != null) { @@ -295,7 +295,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ while (domainId != null) { DomainVO domain = _domainDao.findById(domainId); ResourceLimitVO domainLimit = _resourceLimitDao.findByOwnerIdAndType(domainId, ResourceOwnerType.Domain, type); - if (domainLimit != null) { + if (domainLimit != null && domainLimit.getMax().longValue() != Resource.RESOURCE_UNLIMITED) { long domainCount = _resourceCountDao.getResourceCount(domainId, ResourceOwnerType.Domain, type); if ((domainCount + numResources) > domainLimit.getMax().longValue()) { throw new ResourceAllocationException("Maximum number of resources of type \"" + type + "\" for domain id=" + domainId + " has been exceeded.", type); @@ -458,8 +458,8 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ Account caller = UserContext.current().getCaller(); if (max == null) { - max = new Long(-1); - } else if (max < -1) { + max = new Long(Resource.RESOURCE_UNLIMITED); + } else if (max.longValue() < Resource.RESOURCE_UNLIMITED) { throw new InvalidParameterValueException("Please specify either '-1' for an infinite limit, or a limit that is at least '0'."); } From 890928f3c459f23a00e3c43a69f1b808e4bb26de Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 10:30:40 -0800 Subject: [PATCH 10/69] Pass context to editable selects --- ui/scripts/ui/widgets/detailView.js | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js index 5d099a2875c..3aebd5b146c 100644 --- a/ui/scripts/ui/widgets/detailView.js +++ b/ui/scripts/ui/widgets/detailView.js @@ -689,6 +689,7 @@ value.selected = $value.html(); value.select({ + context: context, response: { success: function(args) { // Get matching select data From 2bab7dc838e59d95cedda37ab6615c32eea476d5 Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 10:31:49 -0800 Subject: [PATCH 11/69] bug 12560: Implement change network offering status 12560: resolved fixed --- ui/scripts/network.js | 59 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/ui/scripts/network.js b/ui/scripts/network.js index d1c4e60802b..3d6ddb7980b 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -114,6 +114,33 @@ detailView: { name: 'Network details', viewAll: { path: 'network.ipAddresses', label: 'Associated IP Addresses' }, + actions: { + edit: { + label: 'Edit network', + messages: { + notification: function() { return 'Updated network'; } + }, + action: function(args) { + $.ajax({ + url: createURL('updateNetwork'), + data: $.extend(args.data, { + id: args.context.networks[0].id + }), + success: function(json) { + args.response.success({ + _custom: { + jobId: json.updatenetworkresponse.jobid + } + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { poll: pollAsyncJobResult } + } + }, tabs: { details: { title: 'Details', @@ -125,7 +152,37 @@ type: { label: 'Type' }, displaytext: { label: 'Description' }, traffictype: { label: 'Traffic Type' }, - gateway: { label: 'Gateway' } + gateway: { label: 'Gateway' }, + networkofferingid: { + label: 'Network Offering', + isEditable: true, + select: function(args) { + $.ajax({ + url: createURL('listNetworkOfferings'), + data: { + state: 'enabled', + traffictype: args.context.networks[0].traffictype, + guestiptype: args.context.networks[0].type + }, + success: function(json) { + args.response.success({ + data: $.map( + json.listnetworkofferingsresponse.networkoffering, + function(networkOffering) { + return { + id: networkOffering.id, + description: networkOffering.name + }; + } + ) + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } }, { startip: { label: 'Start IP' }, From f3f752b5be1f66262292b3c3b2ad4d09248e46ee Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 10:41:40 -0800 Subject: [PATCH 12/69] bug 12624: fixed list public isos for regular user status 12624: resolved fixed --- server/src/com/cloud/server/ManagementServerImpl.java | 3 ++- server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 1aaa36df542..6b20bc2a694 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1294,8 +1294,9 @@ public class ManagementServerImpl implements ManagementServer { } else { domain = _domainDao.findById(DomainVO.ROOT_DOMAIN); } + List hypers = null; - if( ! isIso ) { + if(!isIso) { hypers = _resourceMgr.listAvailHypervisorInZone(null, null); } Set> templateZonePairSet = new HashSet>(); diff --git a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index 5725650aa40..c1151343c1a 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -575,7 +575,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem } } else if (templateFilter == TemplateFilter.all && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { whereClause += attr; - } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN && !isIso) { return templateZonePairList; } From 5393a44c56dfae323dd259a0dc5b5307b86d1e06 Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Thu, 15 Dec 2011 19:14:15 -0800 Subject: [PATCH 13/69] bug 12290: improve antispoofing lgic handle reboot within vm correctly iptables -S missing in csp --- scripts/vm/hypervisor/xenserver/vmops | 225 ++++++++++++++++++-------- 1 file changed, 155 insertions(+), 70 deletions(-) diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index 24610ea17d2..a5a85042c0f 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -526,74 +526,119 @@ def destroy_network_rules_for_vm(session, args): @echo def destroy_ebtables_rules(vm_chain): - delcmd = "ebtables-save | grep ROUTING | grep " + vm_chain + " | sed 's/-A/-D/'" + delcmd = "ebtables-save | grep " + vm_chain + " | sed 's/-A/-D/'" delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') delcmds.pop() for cmd in delcmds: try: dc = cmd.split(' ') dc.insert(0, 'ebtables') - dc.insert(1, '-t') - dc.insert(2, 'nat') util.pread2(dc) except: util.SMlog("Ignoring failure to delete ebtables rules for vm " + vm_chain) - chains = [vm_chain+"-in", vm_chain+"-out"] - for chain in chains: - try: - util.pread2(['ebtables', '-t', 'nat', '-F', chain]) - util.pread2(['ebtables', '-t', 'nat', '-X', chain]) - except: + try: + util.pread2(['ebtables', '-F', vm_chain]) + util.pread2(['ebtables', '-X', vm_chain]) + except: util.SMlog("Ignoring failure to delete ebtables chain for vm " + vm_chain) - +@echo +def destroy_arptables_rules(vm_chain): + delcmd = "arptables -vL FORWARD | grep " + vm_chain + " | sed 's/-i any//' | sed 's/-o any//' | awk '{print $1,$2,$3,$4}' " + delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') + delcmds.pop() + for cmd in delcmds: + try: + dc = cmd.split(' ') + dc.insert(0, 'arptables') + dc.insert(1, '-D') + dc.insert(2, 'FORWARD') + util.pread2(dc) + except: + util.SMlog("Ignoring failure to delete arptables rules for vm " + vm_chain) + + try: + util.pread2(['arptables', '-F', vm_chain]) + util.pread2(['arptables', '-X', vm_chain]) + except: + util.SMlog("Ignoring failure to delete arptables chain for vm " + vm_chain) @echo -def default_ebtables_rules(vm_chain, vif, vm_ip, vm_mac): +def default_ebtables_antispoof_rules(vm_chain, vifs, vm_ip, vm_mac): + if vm_mac == 'ff:ff:ff:ff:ff:ff': + util.SMlog("Ignoring since mac address is not valid") + return 'true' - vmchain_in = vm_chain + "-in" - vmchain_out = vm_chain + "-out" - - for chain in [vmchain_in, vmchain_out]: + try: + util.pread2(['ebtables', '-N', vm_chain]) + except: try: - util.pread2(['ebtables', '-t', 'nat', '-N', chain]) + util.pread2(['ebtables', '-F', vm_chain]) except: - try: - util.pread2(['ebtables', '-t', 'nat', '-F', chain]) - except: - util.SMlog("Failed to create ebtables nat rule, skipping") - return 'true' + util.SMlog("Failed to create ebtables antispoof chain, skipping") + return 'true' try: - # -s ! 52:54:0:56:44:32 -j DROP - util.pread2(['ebtables', '-t', 'nat', '-A', 'PREROUTING', '-i', vif, '-j', vmchain_in]) - util.pread2(['ebtables', '-t', 'nat', '-A', 'POSTROUTING', '-o', vif, '-j', vmchain_out]) + for vif in vifs: + util.pread2(['ebtables', '-A', 'FORWARD', '-i', vif, '-j', vm_chain]) + util.pread2(['ebtables', '-A', 'FORWARD', '-o', vif, '-j', vm_chain]) except: - util.SMlog("Failed to program default rules") + util.SMlog("Failed to program default ebtables FORWARD rules for %s" % vm_chain) + return 'false' + + try: + for vif in vifs: + # only allow source mac that belongs to the vm + util.pread2(['ebtables', '-A', vm_chain, '-i', vif, '-s', '!', vm_mac, '-j', 'DROP']) + # do not allow fake dhcp responses + util.pread2(['ebtables', '-A', vm_chain, '-i', vif, '-p', 'IPv4', '--ip-proto', 'udp', '--ip-dport', '68', '-j', 'DROP']) + # do not allow snooping of dhcp requests + util.pread2(['ebtables', '-A', vm_chain, '-o', vif, '-p', 'IPv4', '--ip-proto', 'udp', '--ip-dport', '67', '-j', 'DROP']) + except: + util.SMlog("Failed to program default ebtables antispoof rules for %s" % vm_chain) + return 'false' + + return 'true' + +@echo +def default_arp_antispoof(vm_chain, vifs, vm_ip, vm_mac): + if vm_mac == 'ff:ff:ff:ff:ff:ff': + util.SMlog("Ignoring since mac address is not valid") + return 'true' + + try: + util.pread2(['arptables', '-N', vm_chain]) + except: + try: + util.pread2(['arptables', '-F', vm_chain]) + except: + util.SMlog("Failed to create arptables rule, skipping") + return 'true' + + try: + for vif in vifs: + util.pread2(['arptables', '-A', 'FORWARD', '-i', vif, '-j', vm_chain]) + util.pread2(['arptables', '-A', 'FORWARD', '-o', vif, '-j', vm_chain]) + except: + util.SMlog("Failed to program default arptables rules in FORWARD chain vm=" + vm_chain) return 'false' try: - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-i', vif, '-s', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '-s', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-mac-src', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-ip-src', '!', vm_ip, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '-j', 'DROP']) + for vif in vifs: + #accept arp replies into the bridge as long as the source mac and ips match the vm + util.pread2(['arptables', '-A', vm_chain, '-i', vif, '--opcode', 'Reply', '--source-mac', vm_mac, '--source-ip', vm_ip, '-j', 'ACCEPT']) + #accept any arp requests from this vm. In the future this can be restricted to deny attacks on hosts + util.pread2(['arptables', '-A', vm_chain, '-i', vif, '--opcode', 'Request', '-j', 'ACCEPT']) + #accept any arp requests to this vm as long as the request is for this vm's ip + util.pread2(['arptables', '-A', vm_chain, '-o', vif, '--opcode', 'Request', '--destination-ip', vm_ip, '-j', 'ACCEPT']) + #accept any arp replies to this vm as long as the mac and ip matches + util.pread2(['arptables', '-A', vm_chain, '-o', vif, '--opcode', 'Reply', '--destination-mac', vm_mac, '--destination-ip', vm_ip, '-j', 'ACCEPT']) + util.pread2(['arptables', '-A', vm_chain, '-j', 'DROP']) + except: - util.SMlog("Failed to program default ebtables IN rules") + util.SMlog("Failed to program default arptables rules") return 'false' - - try: - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-op', 'Reply', '--arp-mac-dst', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-ip-dst', '!', vm_ip, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '-j', 'DROP']) - except: - util.SMlog("Failed to program default ebtables OUT rules") - return 'false' - + return 'true' @echo @@ -722,15 +767,16 @@ def default_network_rules(session, args): util.SMlog("Failed to program default rules for vm " + vm_name) return 'false' - for v in vifs: - default_ebtables_rules(vmchain, v, vm_ip, vm_mac) + default_arp_antispoof(vmchain, vifs, vm_ip, vm_mac) + default_ebtables_antispoof_rules(vmchain, vifs, vm_ip, vm_mac) - if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, '_initial_', '-1') == False: + if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, '_initial_', '-1', vm_mac) == False: util.SMlog("Failed to log default network rules, ignoring") util.SMlog("Programmed default rules for vm " + vm_name) return 'true' +@echo def check_domid_changed(session, vmName): curr_domid = '-1' try: @@ -750,18 +796,22 @@ def check_domid_changed(session, vmName): lines = (line.rstrip() for line in open(logfilename)) - [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno, _vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] for line in lines: - [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = line.split(',') + try: + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno,_vmMac] = line.split(',') + except ValueError,v: + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = line.split(',') break return [curr_domid, old_domid] +@echo def delete_rules_for_vm_in_bridge_firewall_chain(vmName): vm_name = vmName vmchain = chain_name_def(vm_name) - delcmd = "iptables -S BRIDGE-FIREWALL | grep " + vmchain + " | sed 's/-A/-D/'" + delcmd = "iptables-save | grep '\-A BRIDGE-FIREWALL' | grep " + vmchain + " | sed 's/-A/-D/'" delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') delcmds.pop() for cmd in delcmds: @@ -769,11 +819,12 @@ def delete_rules_for_vm_in_bridge_firewall_chain(vmName): dc = cmd.split(' ') dc.insert(0, 'iptables') dc.pop() - util.pread2(dc) + util.pread2(filter(None, dc)) except: util.SMlog("Ignoring failure to delete rules for vm " + vmName) +@echo def network_rules_for_rebooted_vm(session, vmName): vm_name = vmName [curr_domid, old_domid] = check_domid_changed(session, vm_name) @@ -811,12 +862,15 @@ def network_rules_for_rebooted_vm(session, vmName): #change antispoof rule in vmchain try: - delcmd = "iptables -S " + vmchain_default + " | grep physdev-in | sed 's/-A/-D/'" - inscmd = "iptables -S " + vmchain_default + " | grep physdev-in | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/-A/-I/'" - inscmd2 = "iptables -S " + vmchain_default + " | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/-A/-I/'" + delcmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | sed 's/-A/-D/'" + delcmd2 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | sed 's/-A/-D/'" + inscmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/-A/-I/'" + inscmd2 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/-A/-I/'" + inscmd3 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/-A/-I/'" + inscmd4 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-out | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/-A/-I/'" ipts = [] - for cmd in [delcmd, inscmd, inscmd2]: + for cmd in [delcmd, delcmd2, inscmd, inscmd2, inscmd3, inscmd4]: cmds = util.pread2(['/bin/bash', '-c', cmd]).split('\n') cmds.pop() for c in cmds: @@ -827,12 +881,17 @@ def network_rules_for_rebooted_vm(session, vmName): for ipt in ipts: try: - util.pread2(ipt) + util.pread2(filter(None,ipt)) except: util.SMlog("Failed to rewrite antispoofing rules for vm " + vm_name) except: util.SMlog("No rules found for vm " + vm_name) + destroy_ebtables_rules(vmchain) + destroy_arptables_rules(vmchain) + [vm_ip, vm_mac] = get_vm_mac_ip_from_log(vmchain) + default_arp_antispoof(vmchain, vifs, vm_ip, vm_mac) + default_ebtables_antispoof_rules(vmchain, vifs, vm_ip, vm_mac) rewrite_rule_log_for_vm(vm_name, curr_domid) return True @@ -842,12 +901,15 @@ def rewrite_rule_log_for_vm(vm_name, new_domid): return lines = (line.rstrip() for line in open(logfilename)) - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1','ff:ff:ff:ff:ff:ff'] for line in lines: - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') - break + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') - write_rule_log_for_vm(_vmName, _vmID, '0.0.0.0', new_domid, _signature, '-1') + write_rule_log_for_vm(_vmName, _vmID, _vmIP, new_domid, _signature, '-1', _vmMac) def get_rule_log_for_vm(session, vmName): vm_name = vmName; @@ -857,13 +919,33 @@ def get_rule_log_for_vm(session, vmName): lines = (line.rstrip() for line in open(logfilename)) - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] for line in lines: - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') - break + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') return ','.join([_vmName, _vmID, _vmIP, _domID, _signature, _seqno]) +@echo +def get_vm_mac_ip_from_log(vm_name): + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '0.0.0.0', '-1', '_', '-1','ff:ff:ff:ff:ff:ff'] + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + return ['_', '_'] + + lines = (line.rstrip() for line in open(logfilename)) + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + + return [ _vmIP, _vmMac] + @echo def get_rule_logs_for_vms(session, args): host_uuid = args.pop('host_uuid') @@ -956,10 +1038,13 @@ def check_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): lines = (line.rstrip() for line in open(logfilename)) - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] try: for line in lines: - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno, _vmMac] = line.split(',') + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') break except: util.SMlog("Failed to parse log file for vm " + vmName) @@ -1002,12 +1087,12 @@ def check_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): @echo -def write_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): +def write_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno, vmMac='ff:ff:ff:ff:ff:ff'): vm_name = vmName logfilename = "/var/run/cloud/" + vm_name +".log" util.SMlog("Writing log to " + logfilename) logf = open(logfilename, 'w') - output = ','.join([vmName, vmID, vmIP, domID, signature, seqno]) + output = ','.join([vmName, vmID, vmIP, domID, signature, seqno, vmMac]) result = True try: logf.write(output) @@ -1044,6 +1129,7 @@ def network_rules(session, args): vm_name = args.get('vmName') vm_ip = args.get('vmIP') vm_id = args.get('vmID') + vm_mac = args.get('vmMAC') signature = args.pop('signature') seqno = args.pop('seqno') deflated = 'false' @@ -1083,7 +1169,7 @@ def network_rules(session, args): reason = 'seqno_same_sig_same' if rewriteLog: reason = 'seqno_increased_sig_same' - write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno) + write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno, vm_mac) util.SMlog("Programming network rules for vm %s seqno=%s signature=%s guestIp=%s,"\ " do nothing, reason=%s" % (vm_name, seqno, signature, vm_ip, reason)) return 'true' @@ -1181,7 +1267,7 @@ def network_rules(session, args): util.pread2(['iptables', '-A', vmchain, '-j', 'DROP']) - if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno) == False: + if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno, vm_mac) == False: return 'false' return 'true' @@ -1246,4 +1332,3 @@ if __name__ == "__main__": "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn, "cleanup_rules":cleanup_rules, "checkRouter":checkRouter, "bumpUpPriority":bumpUpPriority, "getDomRVersion":getDomRVersion }) - From 227847773766be3360551e9a3cf0662d1ddc9bab Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Fri, 16 Dec 2011 22:02:09 -0800 Subject: [PATCH 14/69] add stronger security to defend against attacks originating in the vm --- scripts/vm/hypervisor/xenserver/vmops | 29 +++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index a5a85042c0f..54fbb64ed56 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -385,6 +385,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') + default_ebtables_rules() privnic = get_private_nic(session, args) result = 'true' try: @@ -405,6 +406,30 @@ def can_bridge_firewall(session, args): return result +@echo +def default_ebtables_rules(): + try: + util.pread2(['ebtables', '-N', 'DEFAULT_EBTABLES']) + util.pread2(['ebtables', '-A', 'FORWARD', '-j' 'DEFAULT_EBTABLES']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '255.255.255.255', '--ip-proto', 'udp', '--ip-dport', '67', '-j', 'ACCEPT']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) + # deny mac broadcast and multicast + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-d', 'Broadcast', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-d', 'Multicast', '-j', 'DROP']) + # deny ip broadcast and multicast + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '255.255.255.255', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '224.0.0.0/4', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-j', 'RETURN']) + # deny ipv6 + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv6', '-j', 'DROP']) + # deny vlan + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', '802_1Q', '-j', 'DROP']) + # deny all other 802. frames + util.pread2(['ebtables', '-A', 'FORWARD', '-j', 'DROP']) + except: + util.SMlog('Chain DEFAULT_EBTABLES already exists') + @echo def allow_egress_traffic(session): devs = [] @@ -580,8 +605,8 @@ def default_ebtables_antispoof_rules(vm_chain, vifs, vm_ip, vm_mac): try: for vif in vifs: - util.pread2(['ebtables', '-A', 'FORWARD', '-i', vif, '-j', vm_chain]) - util.pread2(['ebtables', '-A', 'FORWARD', '-o', vif, '-j', vm_chain]) + util.pread2(['ebtables', '-I', 'FORWARD', '2', '-i', vif, '-j', vm_chain]) + util.pread2(['ebtables', '-I', 'FORWARD', '2', '-o', vif, '-j', vm_chain]) except: util.SMlog("Failed to program default ebtables FORWARD rules for %s" % vm_chain) return 'false' From 5dfa0ed1693beb8b048c7639b357269d6e670b34 Mon Sep 17 00:00:00 2001 From: Chiradeep Vittal Date: Mon, 19 Dec 2011 10:56:45 -0800 Subject: [PATCH 15/69] remove obsolete file --- scripts/vm/hypervisor/xenserver/vmops.orig | 1208 -------------------- 1 file changed, 1208 deletions(-) delete mode 100755 scripts/vm/hypervisor/xenserver/vmops.orig diff --git a/scripts/vm/hypervisor/xenserver/vmops.orig b/scripts/vm/hypervisor/xenserver/vmops.orig deleted file mode 100755 index f35de53389d..00000000000 --- a/scripts/vm/hypervisor/xenserver/vmops.orig +++ /dev/null @@ -1,1208 +0,0 @@ -#!/usr/bin/python -# Version 2.2.8.2011-08-18T08:15:52Z -# -# A plugin for executing script needed by vmops cloud - -import os, sys, time -import XenAPIPlugin -sys.path.extend(["/opt/xensource/sm/", "/usr/local/sbin/", "/sbin/"]) -import base64 -import hostvmstats -import socket -import stat -import tempfile -import util -<<<<<<< HEAD -import subprocess -======= -import zlib ->>>>>>> acfbe18... bug 11336: compression to allow number of cidrs to scale beyond 8k -from util import CommandException - -def echo(fn): - def wrapped(*v, **k): - name = fn.__name__ - util.SMlog("#### VMOPS enter %s ####" % name ) - res = fn(*v, **k) - util.SMlog("#### VMOPS exit %s ####" % name ) - return res - return wrapped - -@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(session, collect_host_stats, consolidation_function, interval, start_time) - return result - -@echo -def setup_iscsi(session, args): - uuid=args['uuid'] - try: - cmd = ["bash", "/opt/xensource/bin/setup_iscsi.sh", uuid] - txt = util.pread2(cmd) - except: - txt = '' - return txt - -@echo -def getvncport(session, args): - domid = args['domID'] - hvm = args['hvm'] - if hvm == 'true': - path1 = "/local/domain/" + domid + "/qemu-pid" - path2 = "/local/domain/" + domid + "/console/vnc-port" - else: - path1 = "/local/domain/" + domid + "/serial/0/vncterm-pid" - path2 = "/local/domain/" + domid + "/serial/0/vnc-port" - try: - cmd = ["xenstore-read", path1] - pid = util.pread2(cmd) - pid = pid.strip() - cmd = ["ps", pid] - util.pread2(cmd) - cmd = ["xenstore-read", path2] - vncport = util.pread2(cmd) - vncport = vncport.strip() - return vncport - except: - return '' - -@echo -def getgateway(session, args): - mgmt_ip = args['mgmtIP'] - try: - cmd = ["bash", "/opt/xensource/bin/network_info.sh", "-g", mgmt_ip] - txt = util.pread2(cmd) - except: - txt = '' - - return txt - -@echo -def preparemigration(session, args): - uuid = args['uuid'] - try: - cmd = ["/opt/xensource/bin/make_migratable.sh", uuid] - util.pread2(cmd) - txt = 'success' - except: - util.SMlog("Catch prepare migration exception" ) - txt = '' - - return txt - -@echo -def setIptables(session, args): - try: - cmd = ["/bin/bash", "/opt/xensource/bin/setupxenserver.sh"] - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" setIptables execution failed " ) - txt = '' - - return txt - -@echo -def pingdomr(session, args): - host = args['host'] - port = args['port'] - socket.setdefaulttimeout(3) - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - s.connect((host,int(port))) - txt = 'success' - except: - txt = '' - - s.close() - - return txt - -@echo -def pingxenserver(session, args): - txt = 'success' - return txt - -@echo -def ipassoc(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/ipassoc.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" ip associate failed " ) - txt = '' - - return txt - -@echo -def vm_data(session, args): - router_ip = args.pop('routerIP') - vm_ip = args.pop('vmIP') - - util.SMlog(" adding vmdata for VM with IP: " + vm_ip + " to router with IP: " + router_ip) - - for pair in args: - pairList = pair.split(',') - vmDataFolder = pairList[0] - vmDataFile = pairList[1] - vmDataValue = args[pair] - cmd = ["/bin/bash", "/opt/xensource/bin/vm_data.sh", "-r", router_ip, "-v", vm_ip, "-F", vmDataFolder, "-f", vmDataFile] - - fd = None - tmp_path = None - - try: - fd,tmp_path = tempfile.mkstemp() - tmpfile = open(tmp_path, 'w') - - if vmDataFolder == "userdata" and vmDataValue != "none": - vmDataValue = base64.urlsafe_b64decode(vmDataValue) - - if vmDataValue != "none": - tmpfile.write(vmDataValue) - - tmpfile.close() - cmd.append("-d") - cmd.append(tmp_path) - except: - util.SMlog(" vmdata failed to write tempfile " ) - os.close(fd) - os.remove(tmp_path) - return '' - - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" vmdata failed with folder: " + vmDataFolder + " and file: " + vmDataFile) - txt = '' - - if (fd != None): - os.close(fd) - os.remove(tmp_path) - - return txt - -def pingtest(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/pingtest.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" pingtest failed " ) - txt = '' - - return txt - -@echo -def savePassword(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/save_password_to_domr.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" save password to domr failed " ) - txt = '' - - return txt - -@echo -def saveDhcpEntry(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/dhcp_entry.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" save dhcp entry failed " ) - txt = '' - - return txt - -@echo -def lt2p_vpn(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/l2tp_vpn.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog("l2tp vpn failed " ) - txt = '' - - return txt - -@echo -def setLinkLocalIP(session, args): - brName = args['brName'] - try: - cmd = ["ip", "route", "del", "169.254.0.0/16"] - txt = util.pread2(cmd) - except: - txt = '' - try: - cmd = ["ifconfig", brName, "169.254.0.1", "netmask", "255.255.0.0"] - txt = util.pread2(cmd) - except: - txt = '' - try: - cmd = ["ip", "route", "add", "169.254.0.0/16", "dev", brName, "src", "169.254.0.1"] - txt = util.pread2(cmd) - except: - txt = '' - txt = 'success' - return txt - -@echo -def setFirewallRule(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/call_firewall.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" set firewall rule failed " ) - txt = '' - - return txt - -@echo -def setLoadBalancerRule(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/call_loadbalancer.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog(" set loadbalancer rule failed " ) - txt = '' - - return txt - -@echo -def createFile(session, args): - file_path = args['filepath'] - file_contents = args['filecontents'] - - try: - f = open(file_path, "w") - f.write(file_contents) - f.close() - txt = 'success' - except: - util.SMlog(" failed to create HA proxy cfg file ") - txt = '' - - return txt - -@echo -def deleteFile(session, args): - file_path = args["filepath"] - - try: - if os.path.isfile(file_path): - os.remove(file_path) - txt = 'success' - except: - util.SMlog(" failed to remove HA proxy cfg file ") - txt = '' - - return txt - - -@echo -def networkUsage(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/networkUsage.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - except: - util.SMlog(" network usage error " ) - txt = '' - - return txt - -def get_private_nic(session, args): - 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) - mgmtnic = 'eth0' - for pif in piflist: - pifrec = session.xenapi.PIF.get_record(pif) - network = pifrec.get('network') - nwrec = session.xenapi.network.get_record(network) - if nwrec.get('name_label') == 'cloud-guest': - return pifrec.get('device') - if pifrec.get('management'): - mgmtnic = pifrec.get('device') - - return mgmtnic - -def chain_name(vm_name): - if vm_name.startswith('i-') or vm_name.startswith('r-'): - if vm_name.endswith('untagged'): - return '-'.join(vm_name.split('-')[:-1]) - return vm_name - -def chain_name_def(vm_name): - if vm_name.startswith('i-'): - if vm_name.endswith('untagged'): - return '-'.join(vm_name.split('-')[:-2]) + "-def" - return '-'.join(vm_name.split('-')[:-1]) + "-def" - return vm_name - -@echo -def can_bridge_firewall(session, args): - host_uuid = args.get('host_uuid') - try: - util.pread2(['iptables', '-N', 'BRIDGE-FIREWALL']) - util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT']) - util.pread2(['iptables', '-D', 'FORWARD', '-j', 'RH-Firewall-1-INPUT']) - except: - util.SMlog('Chain BRIDGE-FIREWALL already exists') - privnic = get_private_nic(session, args) - result = 'true' - try: - util.pread2(['/bin/bash', '-c', 'iptables -n -L FORWARD | grep BRIDGE-FIREWALL']) - except: - try: - util.pread2(['iptables', '-I', 'FORWARD', '-m', 'physdev', '--physdev-is-bridged', '-j', 'BRIDGE-FIREWALL']) - util.pread2(['iptables', '-A', 'FORWARD', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', privnic, '-j', 'ACCEPT']) - util.pread2(['iptables', '-A', 'FORWARD', '-j', 'DROP']) - except: - result = 'false' - allow_egress_traffic(session) - if not os.path.exists('/var/run/cloud'): - os.makedirs('/var/run/cloud') - - cleanup_rules_for_dead_vms(session) - cleanup_rules(session, args) - - return result - -@echo -def allow_egress_traffic(session): - devs = [] - for pif in session.xenapi.PIF.get_all(): - pif_rec = session.xenapi.PIF.get_record(pif) - vlan = pif_rec.get('VLAN') - dev = pif_rec.get('device') - if vlan == '-1': - devs.append(dev) - else: - devs.append(dev + "." + vlan) - for d in devs: - try: - util.pread2(['/bin/bash', '-c', "iptables -n -L FORWARD | grep '%s '" % d]) - except: - try: - util.pread2(['iptables', '-I', 'FORWARD', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', d, '-j', 'ACCEPT']) - except: - util.SMlog("Failed to add FORWARD rule through to %s" % d) - return 'false' - return 'true' - - -def ipset(ipsetname, proto, start, end, ips): - try: - util.pread2(['ipset', '-N', ipsetname, 'iptreemap']) - except: - util.SMlog("ipset chain already exists" + ipsetname) - - result = True - ipsettmp = ''.join(''.join(ipsetname.split('-')).split('_')) + str(int(time.time()) % 1000) - - try: - util.pread2(['ipset', '-N', ipsettmp, 'iptreemap']) - except: - util.SMlog("Failed to create temp ipset, reusing old name= " + ipsettmp) - try: - util.pread2(['ipset', '-F', ipsettmp]) - except: - util.SMlog("Failed to clear old temp ipset name=" + ipsettmp) - return False - - try: - for ip in ips: - try: - util.pread2(['ipset', '-A', ipsettmp, ip]) - except CommandException, cex: - if cex.reason.rfind('already in set') == -1: - raise - except: - util.SMlog("Failed to program ipset " + ipsetname) - util.pread2(['ipset', '-F', ipsettmp]) - util.pread2(['ipset', '-X', ipsettmp]) - return False - - try: - util.pread2(['ipset', '-W', ipsettmp, ipsetname]) - except: - util.SMlog("Failed to swap ipset " + ipsetname) - result = False - - try: - util.pread2(['ipset', '-F', ipsettmp]) - util.pread2(['ipset', '-X', ipsettmp]) - except: - # if the temporary name clashes next time we'll just reuse it - util.SMlog("Failed to delete temp ipset " + ipsettmp) - - return result - -@echo -def destroy_network_rules_for_vm(session, args): - vm_name = args.pop('vmName') - vmchain = chain_name(vm_name) - vmchain_default = chain_name_def(vm_name) - - delete_rules_for_vm_in_bridge_firewall_chain(vm_name) - if vm_name.startswith('i-') or vm_name.startswith('r-') or vm_name.startswith('l-'): - try: - util.pread2(['iptables', '-F', vmchain_default]) - util.pread2(['iptables', '-X', vmchain_default]) - except: - util.SMlog("Ignoring failure to delete chain " + vmchain_default) - - destroy_ebtables_rules(vmchain) - - try: - util.pread2(['iptables', '-F', vmchain]) - util.pread2(['iptables', '-X', vmchain]) - except: - util.SMlog("Ignoring failure to delete chain " + vmchain) - - - - remove_rule_log_for_vm(vm_name) - - if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: - return 'true' - - try: - setscmd = "ipset --save | grep " + vmchain + " | grep '^-N' | awk '{print $2}'" - setsforvm = util.pread2(['/bin/bash', '-c', setscmd]).split('\n') - for set in setsforvm: - if set != '': - util.pread2(['ipset', '-F', set]) - util.pread2(['ipset', '-X', set]) - except: - util.SMlog("Failed to destroy ipsets for %" % vm_name) - - - return 'true' - -@echo -def destroy_ebtables_rules(vm_chain): - - delcmd = "ebtables-save | grep ROUTING | grep " + vm_chain + " | sed 's/-A/-D/'" - delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') - delcmds.pop() - for cmd in delcmds: - try: - dc = cmd.split(' ') - dc.insert(0, 'ebtables') - dc.insert(1, '-t') - dc.insert(2, 'nat') - util.pread2(dc) - except: - util.SMlog("Ignoring failure to delete ebtables rules for vm " + vm_chain) - chains = [vm_chain+"-in", vm_chain+"-out"] - for chain in chains: - try: - util.pread2(['ebtables', '-t', 'nat', '-F', chain]) - util.pread2(['ebtables', '-t', 'nat', '-X', chain]) - except: - util.SMlog("Ignoring failure to delete ebtables chain for vm " + vm_chain) - - - -@echo -def default_ebtables_rules(vm_chain, vif, vm_ip, vm_mac): - - vmchain_in = vm_chain + "-in" - vmchain_out = vm_chain + "-out" - - for chain in [vmchain_in, vmchain_out]: - try: - util.pread2(['ebtables', '-t', 'nat', '-N', chain]) - except: - try: - util.pread2(['ebtables', '-t', 'nat', '-F', chain]) - except: - util.SMlog("Failed to create ebtables nat rule, skipping") - return 'true' - - try: - # -s ! 52:54:0:56:44:32 -j DROP - util.pread2(['ebtables', '-t', 'nat', '-A', 'PREROUTING', '-i', vif, '-j', vmchain_in]) - util.pread2(['ebtables', '-t', 'nat', '-A', 'POSTROUTING', '-o', vif, '-j', vmchain_out]) - except: - util.SMlog("Failed to program default rules") - return 'false' - - try: - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-i', vif, '-s', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '-s', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-mac-src', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-ip-src', '!', vm_ip, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_in, '-p', 'ARP', '-j', 'DROP']) - except: - util.SMlog("Failed to program default ebtables IN rules") - return 'false' - - try: - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-op', 'Reply', '--arp-mac-dst', '!', vm_mac, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-ip-dst', '!', vm_ip, '-j', 'DROP']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) - util.pread2(['ebtables', '-t', 'nat', '-A', vmchain_out, '-p', 'ARP', '-j', 'DROP']) - except: - util.SMlog("Failed to program default ebtables OUT rules") - return 'false' - - return 'true' - -@echo -def default_network_rules_systemvm(session, args): - vm_name = args.pop('vmName') - try: - vm = session.xenapi.VM.get_by_name_label(vm_name) - if len(vm) != 1: - return 'false' - vm_rec = session.xenapi.VM.get_record(vm[0]) - vm_vifs = vm_rec.get('VIFs') - vifnums = [session.xenapi.VIF.get_record(vif).get('device') for vif in vm_vifs] - domid = vm_rec.get('domid') - except: - util.SMlog("### Failed to get domid or vif list for vm ##" + vm_name) - return 'false' - - if domid == '-1': - util.SMlog("### Failed to get domid for vm (-1): " + vm_name) - return 'false' - - vifs = ["vif" + domid + "." + v for v in vifnums] - #vm_name = '-'.join(vm_name.split('-')[:-1]) - vmchain = chain_name(vm_name) - - - delete_rules_for_vm_in_bridge_firewall_chain(vm_name) - - try: - util.pread2(['iptables', '-N', vmchain]) - except: - util.pread2(['iptables', '-F', vmchain]) - - allow_egress_traffic(session) - - for vif in vifs: - try: - util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', vif, '-j', vmchain]) - util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', vmchain]) - util.pread2(['iptables', '-I', vmchain, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', 'RETURN']) - except: - util.SMlog("Failed to program default rules") - return 'false' - - - util.pread2(['iptables', '-A', vmchain, '-j', 'ACCEPT']) - - if write_rule_log_for_vm(vm_name, '-1', '_ignore_', domid, '_initial_', '-1') == False: - util.SMlog("Failed to log default network rules for systemvm, ignoring") - return 'true' - - -@echo -def default_network_rules(session, args): - vm_name = args.pop('vmName') - vm_ip = args.pop('vmIP') - vm_id = args.pop('vmID') - vm_mac = args.pop('vmMAC') - - try: - vm = session.xenapi.VM.get_by_name_label(vm_name) - if len(vm) != 1: - util.SMlog("### Failed to get record for vm " + vm_name) - return 'false' - vm_rec = session.xenapi.VM.get_record(vm[0]) - domid = vm_rec.get('domid') - except: - util.SMlog("### Failed to get domid for vm " + vm_name) - return 'false' - if domid == '-1': - util.SMlog("### Failed to get domid for vm (-1): " + vm_name) - return 'false' - - vif = "vif" + domid + ".0" - tap = "tap" + domid + ".0" - vifs = [vif] - try: - util.pread2(['ifconfig', tap]) - vifs.append(tap) - except: - pass - - delete_rules_for_vm_in_bridge_firewall_chain(vm_name) - - - vmchain = chain_name(vm_name) - vmchain_default = chain_name_def(vm_name) - - destroy_ebtables_rules(vmchain) - - - try: - util.pread2(['iptables', '-N', vmchain]) - except: - util.pread2(['iptables', '-F', vmchain]) - - try: - util.pread2(['iptables', '-N', vmchain_default]) - except: - util.pread2(['iptables', '-F', vmchain_default]) - - try: - for v in vifs: - util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default]) - util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default]) - util.pread2(['iptables', '-A', vmchain_default, '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT']) - #allow dhcp - for v in vifs: - util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-p', 'udp', '--dport', '67', '--sport', '68', '-j', 'ACCEPT']) - util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-p', 'udp', '--dport', '68', '--sport', '67', '-j', 'ACCEPT']) - - #don't let vm spoof its ip address - for v in vifs: - util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip, '-j', 'RETURN']) - util.pread2(['iptables', '-A', vmchain_default, '-j', vmchain]) - except: - util.SMlog("Failed to program default rules for vm " + vm_name) - return 'false' - - for v in vifs: - default_ebtables_rules(vmchain, v, vm_ip, vm_mac) - - if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, '_initial_', '-1') == False: - util.SMlog("Failed to log default network rules, ignoring") - - util.SMlog("Programmed default rules for vm " + vm_name) - return 'true' - -def check_domid_changed(session, vmName): - curr_domid = '-1' - try: - vm = session.xenapi.VM.get_by_name_label(vmName) - if len(vm) != 1: - util.SMlog("### Could not get record for vm ## " + vmName) - else: - vm_rec = session.xenapi.VM.get_record(vm[0]) - curr_domid = vm_rec.get('domid') - except: - util.SMlog("### Failed to get domid for vm ## " + vmName) - - - logfilename = "/var/run/cloud/" + vmName +".log" - if not os.path.exists(logfilename): - return ['-1', curr_domid] - - lines = (line.rstrip() for line in open(logfilename)) - - [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] - for line in lines: - [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = line.split(',') - break - - return [curr_domid, old_domid] - -def delete_rules_for_vm_in_bridge_firewall_chain(vmName): - vm_name = vmName - vmchain = chain_name_def(vm_name) - - delcmd = "iptables -S BRIDGE-FIREWALL | grep " + vmchain + " | sed 's/-A/-D/'" - delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') - delcmds.pop() - for cmd in delcmds: - try: - dc = cmd.split(' ') - dc.insert(0, 'iptables') - dc.pop() - util.pread2(dc) - except: - util.SMlog("Ignoring failure to delete rules for vm " + vmName) - - -def network_rules_for_rebooted_vm(session, vmName): - vm_name = vmName - [curr_domid, old_domid] = check_domid_changed(session, vm_name) - - if curr_domid == old_domid: - return True - - if old_domid == '-1': - return True - - if curr_domid == '-1': - return True - - util.SMlog("Found a rebooted VM -- reprogramming rules for " + vm_name) - - delete_rules_for_vm_in_bridge_firewall_chain(vm_name) - if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: - default_network_rules_systemvm(session, {"vmName":vm_name}) - return True - - vif = "vif" + curr_domid + ".0" - tap = "tap" + curr_domid + ".0" - vifs = [vif] - try: - util.pread2(['ifconfig', tap]) - vifs.append(tap) - except: - pass - vmchain = chain_name(vm_name) - vmchain_default = chain_name_def(vm_name) - - for v in vifs: - util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default]) - util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default]) - - #change antispoof rule in vmchain - try: - delcmd = "iptables -S " + vmchain_default + " | grep physdev-in | sed 's/-A/-D/'" - inscmd = "iptables -S " + vmchain_default + " | grep physdev-in | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' | sed 's/-A/-I/'" - inscmd2 = "iptables -S " + vmchain_default + " | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' | sed 's/-A/-I/'" - - ipts = [] - for cmd in [delcmd, inscmd, inscmd2]: - cmds = util.pread2(['/bin/bash', '-c', cmd]).split('\n') - cmds.pop() - for c in cmds: - ipt = c.split(' ') - ipt.insert(0, 'iptables') - ipt.pop() - ipts.append(ipt) - - for ipt in ipts: - try: - util.pread2(ipt) - except: - util.SMlog("Failed to rewrite antispoofing rules for vm " + vm_name) - except: - util.SMlog("No rules found for vm " + vm_name) - - rewrite_rule_log_for_vm(vm_name, curr_domid) - return True - -def rewrite_rule_log_for_vm(vm_name, new_domid): - logfilename = "/var/run/cloud/" + vm_name +".log" - if not os.path.exists(logfilename): - return - lines = (line.rstrip() for line in open(logfilename)) - - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] - for line in lines: - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') - break - - write_rule_log_for_vm(_vmName, _vmID, '0.0.0.0', new_domid, _signature, '-1') - -def get_rule_log_for_vm(session, vmName): - vm_name = vmName; - logfilename = "/var/run/cloud/" + vm_name +".log" - if not os.path.exists(logfilename): - return '' - - lines = (line.rstrip() for line in open(logfilename)) - - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] - for line in lines: - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') - break - - return ','.join([_vmName, _vmID, _vmIP, _domID, _signature, _seqno]) - -@echo -def get_rule_logs_for_vms(session, args): - host_uuid = args.pop('host_uuid') - try: - thishost = session.xenapi.host.get_by_uuid(host_uuid) - hostrec = session.xenapi.host.get_record(thishost) - vms = hostrec.get('resident_VMs') - except: - util.SMlog("Failed to get host from uuid " + host_uuid) - return ' ' - - result = [] - try: - for name in [session.xenapi.VM.get_name_label(x) for x in vms]: - if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-', 'l-'] ]: - continue - network_rules_for_rebooted_vm(session, name) - if name.startswith('i-'): - log = get_rule_log_for_vm(session, name) - result.append(log) - except: - util.SMlog("Failed to get rule logs, better luck next time!") - - return ";".join(result) - -@echo -def cleanup_rules_for_dead_vms(session): - try: - vms = session.xenapi.VM.get_all() - cleaned = 0 - for vm_name in [session.xenapi.VM.get_name_label(x) for x in vms]: - if 1 in [ vm_name.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]: - vm = session.xenapi.VM.get_by_name_label(vm_name) - if len(vm) != 1: - continue - vm_rec = session.xenapi.VM.get_record(vm[0]) - state = vm_rec.get('power_state') - if state != 'Running' and state != 'Paused': - util.SMlog("vm " + vm_name + " is not running, cleaning up") - destroy_network_rules_for_vm(session, {'vmName':vm_name}) - 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, args): - instance = args.get('instance') - if not instance: - instance = 'VM' - - try: - chainscmd = "iptables-save | grep '^:' | awk '{print $1}' | cut -d':' -f2 | sed 's/-def/-%s/'|sort|uniq" % instance - chains = util.pread2(['/bin/bash', '-c', chainscmd]).split('\n') - cleaned = 0 - cleanup = [] - for chain in chains: - if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]: - vm = session.xenapi.VM.get_by_name_label(chain) - if len(vm) != 1: - vm = session.xenapi.VM.get_by_name_label(chain + "-untagged") - if len(vm) != 1: - util.SMlog("chain " + chain + " does not correspond to a vm, cleaning up") - cleanup.append(chain) - continue - vm_rec = session.xenapi.VM.get_record(vm[0]) - state = vm_rec.get('power_state') - if state != 'Running' and state != 'Paused': - util.SMlog("vm " + vm_name + " is not running, cleaning up") - cleanup.append(vm_name) - - for vm_name in cleanup: - destroy_network_rules_for_vm(session, {'vmName':vm_name}) - - util.SMlog("Cleaned up rules for " + str(len(cleanup)) + " chains") - return str(len(cleanup)) - except: - util.SMlog("Failed to cleanup rules !") - return '-1'; - -@echo -def check_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): - vm_name = vmName; - logfilename = "/var/run/cloud/" + vm_name +".log" - if not os.path.exists(logfilename): - util.SMlog("Failed to find logfile %s" %logfilename) - return [True, True, True] - - lines = (line.rstrip() for line in open(logfilename)) - - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1'] - try: - for line in lines: - [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') - break - except: - util.SMlog("Failed to parse log file for vm " + vmName) - remove_rule_log_for_vm(vmName) - return [True, True, True] - - reprogramDefault = False - if (domID != _domID) or (vmID != _vmID) or (vmIP != _vmIP): - util.SMlog("Change in default info set of vm %s" % vmName) - return [True, True, True] - else: - util.SMlog("No change in default info set of vm %s" % vmName) - - reprogramChain = False - rewriteLog = True - if (int(seqno) > int(_seqno)): - if (_signature != signature): - reprogramChain = True - util.SMlog("Seqno increased from %s to %s: reprogamming "\ - "ingress rules for vm %s" % (_seqno, seqno, vmName)) - else: - util.SMlog("Seqno increased from %s to %s: but no change "\ - "in signature for vm: skip programming ingress "\ - "rules %s" % (_seqno, seqno, vmName)) - elif (int(seqno) < int(_seqno)): - util.SMlog("Seqno decreased from %s to %s: ignoring these "\ - "ingress rules for vm %s" % (_seqno, seqno, vmName)) - rewriteLog = False - elif (signature != _signature): - util.SMlog("Seqno %s stayed the same but signature changed from "\ - "%s to %s for vm %s" % (seqno, _signature, signature, vmName)) - rewriteLog = True - reprogramChain = True - else: - util.SMlog("Seqno and signature stayed the same: %s : ignoring these "\ - "ingress rules for vm %s" % (seqno, vmName)) - rewriteLog = False - - return [reprogramDefault, reprogramChain, rewriteLog] - - -@echo -def write_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): - vm_name = vmName - logfilename = "/var/run/cloud/" + vm_name +".log" - util.SMlog("Writing log to " + logfilename) - logf = open(logfilename, 'w') - output = ','.join([vmName, vmID, vmIP, domID, signature, seqno]) - result = True - try: - logf.write(output) - logf.write('\n') - except: - util.SMlog("Failed to write to rule log file " + logfilename) - result = False - - logf.close() - - return result - -@echo -def remove_rule_log_for_vm(vmName): - vm_name = vmName - logfilename = "/var/run/cloud/" + vm_name +".log" - - result = True - try: - os.remove(logfilename) - except: - util.SMlog("Failed to delete rule log file " + logfilename) - result = False - - return result - -@echo -def inflate_rules (zipped): - return zlib.decompress(base64.b64decode(zipped)) - -@echo -def network_rules(session, args): - try: - vm_name = args.get('vmName') - vm_ip = args.get('vmIP') - vm_id = args.get('vmID') - signature = args.pop('signature') - seqno = args.pop('seqno') - deflated = 'false' - if 'deflated' in args: - deflated = args.pop('deflated') - - try: - vm = session.xenapi.VM.get_by_name_label(vm_name) - if len(vm) != 1: - util.SMlog("### Could not get record for vm ## " + vm_name) - return 'false' - vm_rec = session.xenapi.VM.get_record(vm[0]) - domid = vm_rec.get('domid') - except: - util.SMlog("### Failed to get domid for vm ## " + vm_name) - return 'false' - if domid == '-1': - util.SMlog("### Failed to get domid for vm (-1): " + vm_name) - return 'false' - - vif = "vif" + domid + ".0" - tap = "tap" + domid + ".0" - vifs = [vif] - try: - util.pread2(['ifconfig', tap]) - vifs.append(tap) - except: - pass - - vmchain = chain_name(vm_name) - reason = 'seqno_change_or_sig_change' - [reprogramDefault, reprogramChain, rewriteLog] = \ - check_rule_log_for_vm (vm_name, vm_id, vm_ip, domid, signature, seqno) - - if not reprogramDefault and not reprogramChain: - util.SMlog("No changes detected between current state and received state") - reason = 'seqno_same_sig_same' - if rewriteLog: - reason = 'seqno_increased_sig_same' - write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno) - util.SMlog("Programming network rules for vm %s seqno=%s signature=%s guestIp=%s,"\ - " do nothing, reason=%s" % (vm_name, seqno, signature, vm_ip, reason)) - return 'true' - - if not reprogramChain: - util.SMlog("###Not programming any ingress rules since no changes detected?") - return 'true' - - if reprogramDefault: - util.SMlog("Change detected in vmId or vmIp or domId, resetting default rules") - default_network_rules(session, args) - reason = 'domid_change' - - rules = args.pop('rules') - if deflated.lower() == 'true': - rules = inflate_rules (rules) - - lines = rules.split(' ') - - util.SMlog("Programming network rules for vm %s seqno=%s numrules=%s signature=%s guestIp=%s,"\ - " update iptables, reason=%s" % (vm_name, seqno, len(lines), signature, vm_ip, reason)) - util.pread2(['iptables', '-F', vmchain]) - - for line in lines: - tokens = line.split(':') - if len(tokens) != 4: - continue - protocol = tokens[0] - start = tokens[1] - end = tokens[2] - cidrs = tokens.pop(); - ips = cidrs.split(",") - ips.pop() - allow_any = False - if '0.0.0.0/0' in ips: - i = ips.index('0.0.0.0/0') - del ips[i] - allow_any = True - range = start + ":" + end - if ips: - ipsetname = vmchain + "_" + protocol + "_" + start + "_" + end - if start == "-1": - ipsetname = vmchain + "_" + protocol + "_any" - - if ipset(ipsetname, protocol, start, end, ips) == False: - util.SMlog(" failed to create ipset for rule " + str(tokens)) - - if protocol == 'all': - iptables = ['iptables', '-I', vmchain, '-m', 'state', '--state', 'NEW', '-m', 'set', '--match-set', ipsetname, 'src', '-j', 'ACCEPT'] - elif protocol != 'icmp': - iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-m', 'set', '--match-set', ipsetname, 'src', '-j', 'ACCEPT'] - else: - range = start + "/" + end - if start == "-1": - range = "any" - iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-m', 'set', '--match-set', ipsetname, 'src', '-j', 'ACCEPT'] - util.pread2(iptables) - util.SMlog(iptables) - - if allow_any and protocol != 'all': - if protocol != 'icmp': - iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-j', 'ACCEPT'] - else: - range = start + "/" + end - if start == "-1": - range = "any" - iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-j', 'ACCEPT'] - util.pread2(iptables) - util.SMlog(iptables) - - util.pread2(['iptables', '-A', vmchain, '-j', 'DROP']) - - if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno) == False: - return 'false' - - return 'true' - except: - util.SMlog("Failed to network rule !") - -@echo -def checkRouter(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/getRouterStatus.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - except: - util.SMlog(" check router status fail! ") - txt = '' - - return txt - -@echo -def bumpUpPriority(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/bumpUpPriority.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'success' - except: - util.SMlog("bump up priority fail! ") - txt = '' - - return txt - -@echo -def getDomRVersion(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/xensource/bin/getDomRVersion.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - except: - util.SMlog(" get domR version fail! ") - txt = '' - - return txt - -if __name__ == "__main__": - XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, - "getvncport": getvncport, "getgateway": getgateway, "preparemigration": preparemigration, - "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, - "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, - "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, - "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, - "networkUsage": networkUsage, "network_rules":network_rules, - "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, - "destroy_network_rules_for_vm":destroy_network_rules_for_vm, - "default_network_rules_systemvm":default_network_rules_systemvm, - "get_rule_logs_for_vms":get_rule_logs_for_vms, - "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn, - "cleanup_rules":cleanup_rules, "checkRouter":checkRouter, - "bumpUpPriority":bumpUpPriority, "getDomRVersion":getDomRVersion }) From 4cb293668dbaef3f5df55712ca26600295ad331f Mon Sep 17 00:00:00 2001 From: frank Date: Mon, 19 Dec 2011 10:59:11 -0800 Subject: [PATCH 16/69] don't check pthread before building, it is making no sense --- wscript_configure | 1 - 1 file changed, 1 deletion(-) diff --git a/wscript_configure b/wscript_configure index f2a1f9dafd7..82457247ca4 100644 --- a/wscript_configure +++ b/wscript_configure @@ -200,7 +200,6 @@ else: conf.env.MSLOGDIR = _join(conf.env.LOCALSTATEDIR,"log",conf.env.MSPATH) conf.env.MSMNTDIR = _join(conf.env.SHAREDSTATEDIR,conf.env.PACKAGE,"mnt") conf.check_tool('compiler_cc') - conf.check_cc(lib='pthread') conf.check_cc(lib='dl') conf.check_tool('usermgmt') conf.check_message_1('Determining management server user name') From 1fbff5bd05ea25b267b6595bcee190b09a495b16 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 11:16:30 -0800 Subject: [PATCH 17/69] bug 12607: fixed error message when resource limit exceeds status 12607: resolved fixed --- .../com/cloud/resourcelimit/ResourceLimitManagerImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 9eb61dc8744..557c23b32ce 100755 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -275,10 +275,10 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ long accountLimit = findCorrectResourceLimitForAccount(account, type); long potentialCount = _resourceCountDao.getResourceCount(account.getId(), ResourceOwnerType.Account, type) + numResources; if (accountLimit != Resource.RESOURCE_UNLIMITED && potentialCount > accountLimit) { - String message = "Maximum number of resources of type \"" + type + "\" for account name=" + account.getAccountName() + String message = "Maximum number of resources of type '" + type + "' for account name=" + account.getAccountName() + " in domain id=" + account.getDomainId() + " has been exceeded."; if (project != null) { - message = "Maximum number of resources of type \"" + type + "\" for project name=" + project.getName() + message = "Maximum number of resources of type '" + type + "' for project name=" + project.getName() + " in domain id=" + account.getDomainId() + " has been exceeded."; } throw new ResourceAllocationException(message, type); @@ -298,7 +298,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ if (domainLimit != null && domainLimit.getMax().longValue() != Resource.RESOURCE_UNLIMITED) { long domainCount = _resourceCountDao.getResourceCount(domainId, ResourceOwnerType.Domain, type); if ((domainCount + numResources) > domainLimit.getMax().longValue()) { - throw new ResourceAllocationException("Maximum number of resources of type \"" + type + "\" for domain id=" + domainId + " has been exceeded.", type); + throw new ResourceAllocationException("Maximum number of resources of type '" + type + "' for domain id=" + domainId + " has been exceeded.", type); } } From e816b3a80b3e64b22c15c9d6749da3a9621f2fa6 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 19 Dec 2011 11:27:36 -0800 Subject: [PATCH 18/69] bug 12650: cloudStack 3.0 new UI - system - management - IP ranges tab - list pods info instead of VlanIpRange info. --- ui/scripts/system.js | 141 +++++++------------------------------------ 1 file changed, 23 insertions(+), 118 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 90f4d393156..0bc4da50c5f 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -258,31 +258,7 @@ }, 'management': { - detailView: { - viewAll: { path: '_zone.pods', label: 'Pods' }, - actions: { - edit: { - label: 'Edit', - action: function(args) { - var array1 = []; - array1.push("&name=" +todb(args.data.name)); - array1.push("&dns1=" + todb(args.data.dns1)); - array1.push("&dns2=" + todb(args.data.dns2)); //dns2 can be empty ("") when passed to API - array1.push("&internaldns1=" + todb(args.data.internaldns1)); - array1.push("&internaldns2=" + todb(args.data.internaldns2)); //internaldns2 can be empty ("") when passed to API - array1.push("&domain=" + todb(args.data.domain)); - $.ajax({ - url: createURL("updateZone&id=" + args.context.zones[0].id + array1.join("")), - dataType: "json", - async: false, - success: function(json) { - selectedZoneObj = json.updatezoneresponse.zone; //override selectedZoneObj after update zone - args.response.success({data: selectedZoneObj}); - } - }); - } - } - }, + detailView: { tabs: { details: { title: 'Details', @@ -303,99 +279,28 @@ }); } }, - - ipAddresses: { - title: 'IP Ranges', - custom: function(args) { - return $('
').multiEdit({ - context: args.context, - noSelect: true, - fields: { - 'gateway': { edit: true, label: 'Gateway' }, - 'netmask': { edit: true, label: 'Netmask' }, - 'vlan': { edit: true, label: 'VLAN', isOptional: true }, - 'startip': { edit: true, label: 'Start IP' }, - 'endip': { edit: true, label: 'End IP' }, - 'add-rule': { label: 'Add', addButton: true } - }, - add: { - label: 'Add', - action: function(args) { - var array1 = []; - array1.push("&zoneId=" + args.context.zones[0].id); - - if (args.data.vlan != null && args.data.vlan.length > 0) - array1.push("&vlan=" + todb(args.data.vlan)); - else - array1.push("&vlan=untagged"); - - array1.push("&gateway=" + args.data.gateway); - array1.push("&netmask=" + args.data.netmask); - array1.push("&startip=" + args.data.startip); - if(args.data.endip != null && args.data.endip.length > 0) - array1.push("&endip=" + args.data.endip); - - if(args.context.zones[0].securitygroupsenabled == false) - array1.push("&forVirtualNetwork=true"); - else - array1.push("&forVirtualNetwork=false"); - - $.ajax({ - url: createURL("createVlanIpRange" + array1.join("")), - dataType: "json", - success: function(json) { - var item = json.createvlaniprangeresponse.vlan; - args.response.success({ - data: item, - notification: { - label: 'IP range is added', - poll: function(args) { - args.complete(); - } - } - }); - }, - error: function(XMLHttpResponse) { - var errorMsg = parseXMLHttpResponse(XMLHttpResponse); - args.response.error(errorMsg); - } - }); - } - }, - actions: { - destroy: { - label: 'Delete', - action: function(args) { - $.ajax({ - url: createURL('deleteVlanIpRange&id=' + args.context.multiRule[0].id), - dataType: 'json', - async: true, - success: function(json) { - args.response.success({ - notification: { - label: 'Remove IP range ' + args.context.multiRule[0].id, - poll: function(args) { - args.complete(); - } - } - }); - } - }); - } - } - }, - dataProvider: function(args) { - $.ajax({ - url: createURL("listVlanIpRanges&zoneid=" + args.context.zones[0].id + "&networkId=" + selectedManagementNetworkObj.id), - dataType: "json", - success: function(json) { - var items = json.listvlaniprangesresponse.vlaniprange; - args.response.success({data: items}); - } - }); - } - }); - } + ipAddresses: { //read-only listView (no actions) filled with pod info (not VlanIpRange info)??? + title: 'IP Ranges', + listView: { + fields: { + name: { label: 'Pod name' }, + gateway: { label: 'Gateway' }, + netmask: { label: 'Netmask' }, + startip: { label: 'Start IP' }, + endip: { label: 'End IP' } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL("listPods&zoneid=" + selectedZoneObj.id + "&page=" + args.page + "&pagesize=" + pageSize), + dataType: "json", + async: true, + success: function(json) { + var items = json.listpodsresponse.pod; + args.response.success({ data:items }); + } + }); + } + } } } } From 07ed925ab14afb046cb5de40c35bd2111ea12692 Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 11:35:26 -0800 Subject: [PATCH 19/69] bug 12614: Zone wizard update -Add support to filter network offerings based on whether security groups is checked; options then come from a separate 'securityGroupNetworkOfferings' object: args.response.success({ domains: domainObjs, // Non-security-group-enabled offerings networkOfferings: networkOfferingObjs, // Security group-enabled offerings securityGroupNetworkOfferings: [] }); -Remove old/unused fields from wizard --- ui/index-test.html | 39 ++++++++++++------------------ ui/index.jsp | 25 +++++++------------ ui/scripts/system.js | 10 +++++++- ui/scripts/ui-custom/zoneWizard.js | 34 +++++++++++++++++++++++--- 4 files changed, 65 insertions(+), 43 deletions(-) diff --git a/ui/index-test.html b/ui/index-test.html index 6f3219b9a72..8f90da40ceb 100644 --- a/ui/index-test.html +++ b/ui/index-test.html @@ -1,5 +1,5 @@ +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> CloudStack @@ -433,22 +433,6 @@
Choose this network model if you wish to enable VLAN support. This network model provides the most flexibility in allowing administrators to provide custom network offerings such as providing firewall, vpn, or load balancer support as well as enabling direct vs virtual networking.
- -
-

Isolation mode

-
- - -
Choose this if you wish to use zone-wide VLANs to provide guest VM isolation.
-
-
- - -
Choose this if you wish to use security groups to provide guest VM isolation.
-
-
@@ -544,13 +528,22 @@
+ +
+
+ Enable security groups +
+
+ +
+
Network Offering
- +
@@ -571,7 +564,7 @@ Name
- +
@@ -581,7 +574,7 @@ Gateway
- +
@@ -591,7 +584,7 @@ Netmask
- +
@@ -601,9 +594,9 @@ Reserved IP
- + - - +
diff --git a/ui/index.jsp b/ui/index.jsp index 359c63d9ca9..699f2522f94 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -433,22 +433,6 @@
Choose this network model if you wish to enable VLAN support. This network model provides the most flexibility in allowing administrators to provide custom network offerings such as providing firewall, vpn, or load balancer support as well as enabling direct vs virtual networking.
- -
-

Isolation mode

-
- - -
Choose this if you wish to use zone-wide VLANs to provide guest VM isolation.
-
-
- - -
Choose this if you wish to use security groups to provide guest VM isolation.
-
-
@@ -544,6 +528,15 @@
+ +
+
+ Enable security groups +
+
+ +
+
diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 0bc4da50c5f..387b5e2250e 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -2852,7 +2852,15 @@ } }); - args.response.success({domains: domainObjs, networkOfferings: networkOfferingObjs}); + args.response.success({ + domains: domainObjs, + + // Non-security-group-enabled offerings + networkOfferings: networkOfferingObjs, + + // Security group-enabled offerings + securityGroupNetworkOfferings: [] + }); }, // Step 3: Setup Pod diff --git a/ui/scripts/ui-custom/zoneWizard.js b/ui/scripts/ui-custom/zoneWizard.js index e2b41d116f1..1ffddb5cada 100644 --- a/ui/scripts/ui-custom/zoneWizard.js +++ b/ui/scripts/ui-custom/zoneWizard.js @@ -110,8 +110,9 @@ return $(this).index() <= targetIndex; }).toggleClass('active'); - // Load data provider for domain dropdowns - if (!$targetStep.hasClass('loaded') && (index == 2 || index == 4)) { + var loadData = function(options) { + if (!options) options = {}; + args.steps[targetIndex]({ response: { success: function(args) { @@ -121,14 +122,41 @@ }); $(args.networkOfferings).each(function() { - $('').val(this.id).html(this.name) + $('') + .val(this.id) + .html(this.name) .appendTo($targetStep.find('select.network-offering')); }); $targetStep.addClass('loaded'); + + // Security groups checkbox filters offering drop-down + var $securityGroupsEnabled = $wizard.find( + 'input[name=security-groups-enabled]' + ); + $securityGroupsEnabled.data('target-index', targetIndex); + $securityGroupsEnabled.change(function() { + var $check = $(this); + var $select = $targetStep.find('select.network-offering'); + var objs = $check.is(':checked') ? + args.securityGroupNetworkOfferings : args.networkOfferings; + + $select.children().remove(); + $(objs).each(function() { + $('') + .val(this.id) + .html(this.name) + .appendTo($select); + }); + }); } } }); + }; + + // Load data provider for domain dropdowns + if (!$targetStep.hasClass('loaded') && (index == 2 || index == 4)) { + loadData(); } setTimeout(function() { From a12c358842839dba805f7a3cad16067d43912240 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 12:02:02 -0800 Subject: [PATCH 20/69] bug 12624: don't allow to delete the account when he is the owner for project(s) status 12624: resolved fixed --- api/src/com/cloud/acl/SecurityChecker.java | 1 - .../cloud/projects/dao/ProjectAccountDao.java | 2 + .../projects/dao/ProjectAccountDaoImpl.java | 39 ++++++++++++------- .../com/cloud/user/AccountManagerImpl.java | 14 +++++++ 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/api/src/com/cloud/acl/SecurityChecker.java b/api/src/com/cloud/acl/SecurityChecker.java index e0438610a3e..3d5c7c9d3a3 100644 --- a/api/src/com/cloud/acl/SecurityChecker.java +++ b/api/src/com/cloud/acl/SecurityChecker.java @@ -21,7 +21,6 @@ */ package com.cloud.acl; -import com.cloud.acl.SecurityChecker.AccessType; import com.cloud.dc.DataCenter; import com.cloud.domain.Domain; import com.cloud.exception.PermissionDeniedException; diff --git a/server/src/com/cloud/projects/dao/ProjectAccountDao.java b/server/src/com/cloud/projects/dao/ProjectAccountDao.java index 97606174c06..658ec8fbf9f 100644 --- a/server/src/com/cloud/projects/dao/ProjectAccountDao.java +++ b/server/src/com/cloud/projects/dao/ProjectAccountDao.java @@ -32,4 +32,6 @@ public interface ProjectAccountDao extends GenericDao{ boolean canModifyProjectAccount(long accountId, long projectAccountId); List listPermittedAccountIds(long accountId); + + List listAdministratedProjects(long adminAccountId); } diff --git a/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java b/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java index 8555aca9ab4..802f3fe9a61 100644 --- a/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java +++ b/server/src/com/cloud/projects/dao/ProjectAccountDaoImpl.java @@ -17,23 +17,23 @@ */ package com.cloud.projects.dao; -import java.util.ArrayList; import java.util.List; import javax.ejb.Local; -import org.apache.log4j.Logger; - import com.cloud.projects.ProjectAccount; import com.cloud.projects.ProjectAccountVO; import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; @Local(value={ProjectAccountDao.class}) public class ProjectAccountDaoImpl extends GenericDaoBase implements ProjectAccountDao { - private static final Logger s_logger = Logger.getLogger(ProjectAccountDaoImpl.class); protected final SearchBuilder AllFieldsSearch; + final GenericSearchBuilder AdminSearch; + final GenericSearchBuilder ProjectAccountSearch; protected ProjectAccountDaoImpl() { AllFieldsSearch = createSearchBuilder(); @@ -42,6 +42,17 @@ public class ProjectAccountDaoImpl extends GenericDaoBase listPermittedAccountIds(long accountId) { - List permittedAccounts = new ArrayList(); - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = ProjectAccountSearch.create(); sc.setParameters("accountId", accountId); - - List records = listBy(sc); - - for (ProjectAccountVO record : records) { - permittedAccounts.add(record.getProjectAccountId()); - } - - return permittedAccounts; + return customSearch(sc, null); + } + + @Override + public List listAdministratedProjects(long adminAccountId) { + SearchCriteria sc = AdminSearch.create(); + sc.setParameters("role", ProjectAccount.Role.Admin); + sc.setParameters("accountId", adminAccountId); + return customSearch(sc, null); } } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 295b96eff19..a834f932a74 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -83,6 +83,7 @@ import com.cloud.network.security.dao.SecurityGroupDao; import com.cloud.network.vpn.RemoteAccessVpnService; import com.cloud.projects.Project; import com.cloud.projects.ProjectManager; +import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; import com.cloud.server.auth.UserAuthenticator; import com.cloud.storage.StorageManager; @@ -194,6 +195,8 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag private AccountDetailsDao _accountDetailsDao; @Inject private DomainDao _domainDao; + @Inject + private ProjectAccountDao _projectAccountDao; private Adapters _userAuthenticators; @@ -962,6 +965,17 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag throw new PermissionDeniedException("Account id : " + accountId + " is a system account, delete is not allowed"); } + //Account that manages project(s) can't be removed + List managedProjectIds = _projectAccountDao.listAdministratedProjects(accountId); + if (!managedProjectIds.isEmpty()) { + StringBuilder projectIds = new StringBuilder(); + for (Long projectId : managedProjectIds) { + projectIds.append(projectId + ", "); + } + + throw new InvalidParameterValueException("The account id=" + accountId + " manages project(s) with ids " + projectIds + "and can't be removed"); + } + return deleteAccount(account, callerUserId, caller); } From bb9886af2983c1f994258c97609a1c7588e0730d Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 19 Dec 2011 12:15:32 -0800 Subject: [PATCH 21/69] cloudStack 3.0 new UI - system - guest - IP Ranges tab (only shown in basic zone) - implement Add IP Range. --- ui/scripts/system.js | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 387b5e2250e..78ad52947e4 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -401,39 +401,46 @@ context: args.context, noSelect: true, fields: { + 'podid': { + edit: true, + label: 'Pod', + select: function(args) { + $.ajax({ + url: createURL("listPods&zoneid=" + selectedZoneObj.id), + dataType: "json", + success: function(json) { + var items = []; + var pods = json.listpodsresponse.pod; + $(pods).each(function(){ + items.push({name: this.id, description: this.name}); //should be "{id: this.id, description: this.name}" (to be consistent with dropdown in createFrom and edit mode) (Brian will fix widget later) + }); + args.response.success({ data: items }); + } + }); + } + }, 'gateway': { edit: true, label: 'Gateway' }, - 'netmask': { edit: true, label: 'Netmask' }, - 'vlan': { edit: true, label: 'VLAN', isOptional: true }, + 'netmask': { edit: true, label: 'Netmask' }, 'startip': { edit: true, label: 'Start IP' }, 'endip': { edit: true, label: 'End IP' }, 'add-rule': { label: 'Add', addButton: true } }, add: { label: 'Add', - action: function(args) { - var array1 = []; - array1.push("&zoneId=" + args.context.zones[0].id); - - if (args.data.vlan != null && args.data.vlan.length > 0) - array1.push("&vlan=" + todb(args.data.vlan)); - else - array1.push("&vlan=untagged"); - + action: function(args) { + var array1 = []; + array1.push("&podid=" + args.data.podid); //args.data.podId shouldn't be undefined (wait for Brian to fix it) + array1.push("&networkid=" + selectedGuestNetworkObj.id) array1.push("&gateway=" + args.data.gateway); array1.push("&netmask=" + args.data.netmask); array1.push("&startip=" + args.data.startip); if(args.data.endip != null && args.data.endip.length > 0) array1.push("&endip=" + args.data.endip); - if(args.context.zones[0].securitygroupsenabled == false) - array1.push("&forVirtualNetwork=true"); - else - array1.push("&forVirtualNetwork=false"); - $.ajax({ url: createURL("createVlanIpRange" + array1.join("")), dataType: "json", - success: function(json) { + success: function(json) { var item = json.createvlaniprangeresponse.vlan; args.response.success({ data: item, From 8d27ecf4de14a3f2b999d053cf94da8000492a1e Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 12:23:07 -0800 Subject: [PATCH 22/69] bug 12635: enable project account when activate the project status 12635: resolved fixed --- .../src/com/cloud/projects/ProjectManagerImpl.java | 13 +++++++++++-- server/src/com/cloud/user/AccountManager.java | 2 ++ server/src/com/cloud/user/AccountManagerImpl.java | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index e62a00be9ba..7eb5a268b11 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -916,6 +916,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ @Override @ActionEvent(eventType = EventTypes.EVENT_PROJECT_ACTIVATE, eventDescription = "activating project") + @DB public Project activateProject(long projectId) { Account caller = UserContext.current().getCaller(); @@ -941,9 +942,16 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ throw new InvalidParameterValueException("Can't activate the project in " + currentState + " state"); } + Transaction txn = Transaction.currentTxn(); + txn.start(); + project.setState(Project.State.Active); _projectDao.update(projectId, project); + _accountMgr.enableAccount(project.getProjectAccountId()); + + txn.commit(); + return _projectDao.findById(projectId); } @@ -970,7 +978,8 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } - private boolean suspendProject(ProjectVO project) throws ConcurrentOperationException, ResourceUnavailableException{ + private boolean suspendProject(ProjectVO project) throws ConcurrentOperationException, ResourceUnavailableException { + s_logger.debug("Marking project " + project + " with state " + State.Suspended + " as a part of project suspend..."); project.setState(State.Suspended); boolean updateResult = _projectDao.update(project.getId(), project); @@ -979,7 +988,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ long projectAccountId = project.getProjectAccountId(); if (!_accountMgr.disableAccount(projectAccountId)) { s_logger.warn("Failed to suspend all project's " + project + " resources; the resources will be suspended later by background thread"); - } + } } else { throw new CloudRuntimeException("Failed to mark the project " + project + " with state " + State.Suspended); } diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java index 978c938aaf1..589c33e7f86 100755 --- a/server/src/com/cloud/user/AccountManager.java +++ b/server/src/com/cloud/user/AccountManager.java @@ -88,5 +88,7 @@ public interface AccountManager extends AccountService { Pair findUserByApiKey(String apiKey); boolean lockAccount(long accountId); + + boolean enableAccount(long accountId); } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index a834f932a74..0baa2cdd70a 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -379,6 +379,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag return _userDao.update(Long.valueOf(userId), userForUpdate); } + @Override public boolean enableAccount(long accountId) { boolean success = false; AccountVO acctForUpdate = _accountDao.createForUpdate(); From a2cc66ce419522a78d63dfc2ca11e2ec49f4450d Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 19 Dec 2011 12:53:17 -0800 Subject: [PATCH 23/69] cloudStack 3.0 new UI - system - guest - IP Ranges tab (only shown in basic zone) - Add IP Range - pass forVirtualNetwork=false to indicate it's for guest network, not for public network. --- ui/scripts/system.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 78ad52947e4..9c8e88d190a 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -429,14 +429,15 @@ label: 'Add', action: function(args) { var array1 = []; - array1.push("&podid=" + args.data.podid); //args.data.podId shouldn't be undefined (wait for Brian to fix it) + array1.push("&podid=" + args.data.podid); array1.push("&networkid=" + selectedGuestNetworkObj.id) array1.push("&gateway=" + args.data.gateway); array1.push("&netmask=" + args.data.netmask); array1.push("&startip=" + args.data.startip); if(args.data.endip != null && args.data.endip.length > 0) array1.push("&endip=" + args.data.endip); - + array1.push("&forVirtualNetwork=false"); //indicates this new IP range is for guest network, not public network + $.ajax({ url: createURL("createVlanIpRange" + array1.join("")), dataType: "json", From a269b089ae38d0d04db2fa0f4c8e839480476ddc Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Fri, 16 Dec 2011 18:52:59 -0800 Subject: [PATCH 24/69] bug 12608: NaaS: Don't shutdown elements if cleanup=false We can use the restartNetwork mechanism to recover the disconnected redundant router. Also disable HA for redundant router. Admin would take responsibilty to recover the failure router, because redundant routers themselves are one layer HA. status 12608: resolved fixed --- .../com/cloud/network/NetworkManagerImpl.java | 17 +++++++++++------ .../VirtualNetworkApplianceManagerImpl.java | 8 +++++++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 57bd3cb5768..d4ba860f947 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2820,14 +2820,19 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag s_logger.debug("Restarting network " + networkId + "..."); - //shutdown the network ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount); - s_logger.debug("Shutting down the network id=" + networkId + " as a part of network restart"); + + if (cleanup) { + //shutdown the network + s_logger.debug("Shutting down the network id=" + networkId + " as a part of network restart"); - if (!shutdownNetworkElementsAndResources(context, cleanup, network)) { - s_logger.debug("Failed to shutdown the network elements and resources as a part of network restart: " + network.getState()); - setRestartRequired(network, true); - return false; + if (!shutdownNetworkElementsAndResources(context, true, network)) { + s_logger.debug("Failed to shutdown the network elements and resources as a part of network restart: " + network.getState()); + setRestartRequired(network, true); + return false; + } + } else { + s_logger.debug("Skip the shutting down of network id=" + networkId); } //implement the network elements and rules again diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index f862798f435..de2bcd24d9d 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1346,9 +1346,15 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian s_logger.debug(hType + " won't support system vm, skip it"); continue; } + + boolean offerHA = routerOffering.getOfferHA(); + /* We don't provide HA to redundant router VMs, admin should own it all, and redundant router themselves are HA */ + if (isRedundant) { + offerHA = false; + } router = new DomainRouterVO(id, routerOffering.getId(), vrProvider.getId(), VirtualMachineName.getRouterName(id, _instance), template.getId(), template.getHypervisorType(), - template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestNetwork.getId(), isRedundant, 0, false, RedundantState.UNKNOWN, routerOffering.getOfferHA(), false); + template.getGuestOSId(), owner.getDomainId(), owner.getId(), guestNetwork.getId(), isRedundant, 0, false, RedundantState.UNKNOWN, offerHA, false); router.setRole(Role.VIRTUAL_ROUTER); router = _itMgr.allocate(router, template, routerOffering, networks, plan, null, owner); break; From b4e1af394322364aa344307f61403414323d560b Mon Sep 17 00:00:00 2001 From: frank Date: Mon, 19 Dec 2011 13:38:45 -0800 Subject: [PATCH 25/69] Update INSTALL.txt --- INSTALL.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/INSTALL.txt b/INSTALL.txt index 081d1ace2e8..564dd5727d4 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -11,6 +11,16 @@ yum install ant ant-devel openjdk openjdk-devel mysql mysql-server tomcat Dependencies: yum install jakarta-commons-collections jakarta-commons-dbcp.noarch apache-commons-logging.noarch jakarta-commons-pool jakarta-commons-httpclient.noarch ws-commons-util.noarch glibc-devel gcc python MySQL-python openssh-clients +Tomcat: +Download tomcat6.0.33 from http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.33/bin/ instead of using distribution's default tomcat. Set CATALINA_HOME and CATALINA_BASE to path where you extract tomcat in environment variable, it would be better off setting them in .bashrc as it will take effect every time you log in. + +Note: Tomcat6.0.35 has some known issue with CloudStack, please avoid it + +SSHKEY: +Run: +sh-keygen -t rsa -q +to create sshkey for your account if you don't have one + Step 2: Configuration Start the MySQL service : From 3169a5426315d1621d499793bc7a05dc2cf7b1ee Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 13:41:32 -0800 Subject: [PATCH 26/69] bug 12644: don't allow to add new users to suspended/disabled projects status 12644: resolved fixed --- api/src/com/cloud/api/BaseCmd.java | 1 - server/src/com/cloud/projects/ProjectManagerImpl.java | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/api/src/com/cloud/api/BaseCmd.java b/api/src/com/cloud/api/BaseCmd.java index 25c2b1cebd4..3b97d6bb970 100755 --- a/api/src/com/cloud/api/BaseCmd.java +++ b/api/src/com/cloud/api/BaseCmd.java @@ -479,7 +479,6 @@ public abstract class BaseCmd { } if (projectId != null) { - Project project = _projectService.getProject(projectId); if (project != null) { if (project.getState() == Project.State.Active) { diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index 7eb5a268b11..950f1f9a0b4 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -546,6 +546,11 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ if (project == null) { throw new InvalidParameterValueException("Unable to find the project id=" + projectId); } + + //User can be added to Active project only + if (project.getState() != Project.State.Active) { + throw new InvalidParameterValueException("Can't add account to the project id=" + projectId + " in state=" + project.getState() + " as it's no longer active"); + } //check that account-to-add exists Account account = null; From 134b38bb2ddd460e86be32bb02bb70cb9f66d682 Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 14:12:01 -0800 Subject: [PATCH 27/69] bug 12211 Add system resources, users, alerts to project dashboard --- ui/css/cloudstack3.css | 5 +- ui/index.jsp | 111 ++++--------------------------- ui/scripts/projects.js | 108 ++++++++++++++++++++++++++++++ ui/scripts/ui-custom/projects.js | 62 +++++++++++++---- 4 files changed, 174 insertions(+), 112 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 156746c1bc2..07b0ecd17f0 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -6837,6 +6837,8 @@ div.panel.ui-dialog div.list-view div.fixed-header { .info-boxes .info-box.events { margin-top: 4px; + min-height: 100px; + width: 228px; } .info-boxes .info-box.events ul { @@ -6854,7 +6856,7 @@ div.panel.ui-dialog div.list-view div.fixed-header { .info-boxes .info-box ul li { width: 224px; margin: 0 2px 0 0; - height: 36px; + display: inline-block; border-bottom: 1px solid #BDD2DF; border-top: 1px solid #FFFFFF; } @@ -6895,6 +6897,7 @@ div.panel.ui-dialog div.list-view div.fixed-header { position: relative; left: 0px; top: 2px; + float: left; } .info-boxes .info-box .title .button { diff --git a/ui/index.jsp b/ui/index.jsp index 699f2522f94..e6a600d75c1 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -772,13 +772,13 @@
-
12
+
5
Running
-
2
+
10
Stopped
@@ -789,27 +789,18 @@ Storage
-
171
-
GB/mo
+
10
+
volumes
-
  • +
  • Bandwidth
    - -
    -
    2.3
    -
    In GB
    -
    - - -
    -
    1.5
    -
    Out GB
    -
    +
    200
    +
    mb/s
  • @@ -822,47 +813,9 @@
    Users
    -
      +
      • - Will -
        -
      • - -
      • - Brian -
        -
      • - -
      • - Sonny -
        -
      • -
      • - Will -
        -
      • - -
      • - Brian -
        -
      • - -
      • - Sonny -
        -
      • -
      • - Will -
        -
      • - -
      • - Brian -
        -
      • - -
      • - Sonny +
      @@ -923,50 +876,10 @@
    -
      +
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        -
      • -
      • -
        12/01
        -
        Event
        +
        +
    diff --git a/ui/scripts/projects.js b/ui/scripts/projects.js index 3947ba7b965..59f7e20b683 100644 --- a/ui/scripts/projects.js +++ b/ui/scripts/projects.js @@ -4,6 +4,114 @@ return window.g_projectsInviteRequired; }, + dashboard: function(args) { + var dataFns = { + instances: function(data) { + $.ajax({ + url: createURL('listVirtualMachines'), + success: function(json) { + var instances = json.listvirtualmachinesresponse.virtualmachine ? + json.listvirtualmachinesresponse.virtualmachine : []; + + dataFns.storage($.extend(data, { + runningInstances: $.grep(instances, function(instance) { + return instance.state == 'Running'; + }).length, + stoppedInstances: $.grep(instances, function(instance) { + return instance.state == 'Stopped'; + }).length, + totalInstances: instances.length + })); + } + }); + }, + + storage: function(data) { + $.ajax({ + url: createURL('listVolumes'), + success: function(json) { + dataFns.bandwidth($.extend(data, { + totalVolumes: json.listvolumesresponse.volume ? + json.listvolumesresponse.volume.count : 0 + })); + } + }); + }, + + bandwidth: function(data) { + var totalBandwidth = 0; + $.ajax({ + url: createURL('listNetworks'), + success: function(json) { + var networks = json.listnetworksresponse.network ? + json.listnetworksresponse.network : []; + $(networks).each(function() { + var network = this; + $.ajax({ + url: createURL('listNetworkOfferings'), + async: false, + data: { + id: network.networkofferingid + }, + success: function(json) { + totalBandwidth += + json.listnetworkofferingsresponse.networkoffering[0].networkrate; + } + }); + }); + + dataFns.users($.extend(data, { + totalBandwidth: totalBandwidth + })); + } + }); + }, + + users: function(data) { + $.ajax({ + url: createURL('listProjectAccounts'), + success: function(json) { + var users = json.listprojectaccountsresponse.projectaccount; + + dataFns.events($.extend(data, { + users: $.map(users, function(user) { + return { + account: user.account + }; + }) + })); + } + }); + }, + + events: function(data) { + $.ajax({ + url: createURL('listEvents', { ignoreProject: true }), + success: function(json) { + var events = json.listeventsresponse.event; + + complete($.extend(data, { + events: $.map(events, function(event) { + return { + date: event.created.substr(5, 2) + '/' + event.created.substr(8, 2) + '/' + event.created.substr(2, 2), + desc: event.description + }; + }) + })); + } + }); + } + }; + + var complete = function(data) { + args.response.success({ + data: data + }); + }; + + dataFns.instances(); + }, + add: function(args) { setTimeout(function() { $.ajax({ diff --git a/ui/scripts/ui-custom/projects.js b/ui/scripts/ui-custom/projects.js index a5132411b76..91f9c0c0872 100644 --- a/ui/scripts/ui-custom/projects.js +++ b/ui/scripts/ui-custom/projects.js @@ -20,8 +20,55 @@ var tabs = { overview: function() { var $dashboard = $('#template').find('.project-dashboard-view').clone(); + $dashboard.data('tab-title', 'Dashboard'); - $dashboard.data('tab-title', 'Dashboard') + var getData = function() { + // Populate data + $dashboard.find('[data-item]').hide(); + cloudStack.projects.dashboard({ + response: { + success: function(args) { + var data = args.data; + + // Iterate over data; populate corresponding DOM elements + $.each(data, function(key, value) { + var $elem = $dashboard.find('[data-item=' + key + ']'); + + // This assumes an array of data + if ($elem.is('ul')) { + $elem.show(); + var $liTmpl = $elem.find('li').remove(); + $(value).each(function() { + var item = this; + var $li = $liTmpl.clone().appendTo($elem).hide(); + + $.each(item, function(arrayKey, arrayValue) { + var $arrayElem = $li.find('[data-list-item=' + arrayKey + ']'); + + $arrayElem.html(arrayValue); + }); + + $li.attr({ title: item.description }); + + $li.fadeIn(); + }); + } else { + $elem.each(function() { + var $item = $(this); + if ($item.hasClass('chart-line')) { + $item.show().animate({ width: value + '%' }); + } else { + $item.hide().html(value).fadeIn(); + } + }); + } + }); + } + } + }); + }; + + getData(); return $dashboard; } @@ -397,7 +444,6 @@ dialogClass: 'project-selector-dialog', width: 420 }).closest('.ui-dialog').overlay(); - showDashboard(); } }); @@ -416,6 +462,8 @@ .filter(function() { return $(this).data('json-obj').name == cloudStack.context.projects[0].name; }).attr('selected', 'selected'); + showDashboard(); + //// // Hidden for now @@ -473,7 +521,6 @@ */ cloudStack.uiCustom.projects = function(args) { var $dashboardNavItem = $('#navigation li.navigation-item.dashboard'); - var $projectSelect = args.$projectSelect; // Use project dashboard var event = function() { @@ -494,15 +541,6 @@ }; $dashboardNavItem.bind('click', event); - // Project selector event - $projectSelect.change(function() { - cloudStack.context.projects = [ - $projectSelect.find('option:selected').data('json-obj') - ]; - - $(window).trigger('cloudStack.fullRefresh'); - }); - pageElems.selector(args); }; From 3de22e41aa9128f1a3fce1a9058141cf82a78709 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 19 Dec 2011 14:12:17 -0800 Subject: [PATCH 28/69] bug 12614: cloudStack 3.0 new UI - system - Add Zone Wizard - basic zone - when securityGroupsEnabled checkbox is unchecked, exclude network offerings that has securityGroup service. --- ui/scripts/system.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 9c8e88d190a..07b99021586 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -2851,23 +2851,37 @@ } }); + var networkOfferingObjsWithoutSG = []; $.ajax({ url: createURL("listNetworkOfferings&state=Enabled&guestiptype=Shared"), dataType: "json", async: false, success: function(json) { networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; + + $(networkOfferingObjs).each(function() { + var includingSGP = false; + var serviceObjArray = this.service; + for(var k = 0; k < serviceObjArray.length; k++) { + if(serviceObjArray[k].name == "SecurityGroup") { + includingSGP = true; + break; + } + } + if(includingSGP == false) //withoutSG + networkOfferingObjsWithoutSG.push(this); + }); } }); - + args.response.success({ domains: domainObjs, // Non-security-group-enabled offerings - networkOfferings: networkOfferingObjs, + networkOfferings: networkOfferingObjsWithoutSG, // Security group-enabled offerings - securityGroupNetworkOfferings: [] + securityGroupNetworkOfferings: networkOfferingObjs }); }, From a19b1d92ceeaae9e878f96082cd5d362eb0ea520 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 14:24:19 -0800 Subject: [PATCH 29/69] Do services validation when create PF/LB/Firewall rules --- .../src/com/cloud/network/firewall/FirewallManagerImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index 46e4a7fc7ec..e0a9ee373d0 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -55,8 +55,8 @@ import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.rules.FirewallManager; import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRule.FirewallRuleType; +import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRule.State; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.PortForwardingRuleVO; @@ -375,8 +375,10 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ma if (!_elbEnabled) { protocolCapabilities = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Lb); } - } else { + } else if (purpose == Purpose.Firewall){ protocolCapabilities = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.Firewall); + } else if (purpose == Purpose.PortForwarding) { + protocolCapabilities = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.PortForwarding); } if (protocolCapabilities != null) { From 2a2d424bcc929b8c2fc972fa9f1d15fa664e912d Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 14:37:23 -0800 Subject: [PATCH 30/69] bug 12661: Fix select showing ID instead of value --- ui/scripts/system.js | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 07b99021586..c41a1a8289a 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -402,7 +402,6 @@ noSelect: true, fields: { 'podid': { - edit: true, label: 'Pod', select: function(args) { $.ajax({ From 55175fb2fd945b1c043e7b986d31a083be5a5bc9 Mon Sep 17 00:00:00 2001 From: Kelven Yang Date: Mon, 19 Dec 2011 14:48:47 -0800 Subject: [PATCH 31/69] bug 12653: add default gateway support for multiple networks under VMware --- .../vmware/resource/VmwareResource.java | 19 ++++++++++++++++--- .../cloud/hypervisor/vmware/mo/HostMO.java | 4 ++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 3d2fcfaf40a..857fc565630 100755 --- a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -933,11 +933,24 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.info("Executing resource DhcpEntryCommand: " + _gson.toJson(cmd)); } + // ssh -p 3922 -o StrictHostKeyChecking=no -i $cert root@$domr "/root/edithosts.sh $mac $ip $vm $dfltrt $ns $staticrt" >/dev/null String args = " " + cmd.getVmMac(); args += " " + cmd.getVmIpAddress(); - args += " " + cmd.getVmName(); - - if (s_logger.isDebugEnabled()) { + args += " " + cmd.getVmName(); + + if (cmd.getDefaultRouter() != null) { + args += " " + cmd.getDefaultRouter(); + } + + if (cmd.getDefaultDns() != null) { + args += " " + cmd.getDefaultDns(); + } + + if (cmd.getStaticRoutes() != null) { + args += " " + cmd.getStaticRoutes(); + } + + if (s_logger.isDebugEnabled()) { s_logger.debug("Run command on domR " + cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP) + ", /root/edithosts.sh " + args); } diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java index 1b512c36eca..1c3d2a6aa1b 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java @@ -469,8 +469,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { for(ObjectContent oc : ocs) { String vmName = oc.getPropSet()[0].getVal().toString(); - if(s_logger.isDebugEnabled()) - s_logger.debug("put " + vmName + " into host cache"); + if(s_logger.isTraceEnabled()) + s_logger.trace("put " + vmName + " into host cache"); _vmCache.put(vmName, new VirtualMachineMO(_context, oc.getObj())); } From 761069440e625d32be6517e17c6706411cd65257 Mon Sep 17 00:00:00 2001 From: frank Date: Mon, 19 Dec 2011 14:48:53 -0800 Subject: [PATCH 32/69] Bug 12194 - Ubuntu init script can fall into infinite loop Bug 11723 - (Ubuntu Install) Management Server service won't restart patch from community status 11723: resolved fixed --- agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in b/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in index 0c09f1e3b94..099df35c43a 100755 --- a/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in +++ b/agent/distro/ubuntu/SYSCONFDIR/init.d/cloud-agent.in @@ -37,10 +37,10 @@ wait_for_network() { if ip addr show cloudbr0 |grep -w inet > /dev/null 2>&1; then break else + sleep 1 + let i=$i+1 continue fi - sleep 1 - let i=$i+1 done } From aac9c540af761b5e9d203dbc05007695df1ef5b6 Mon Sep 17 00:00:00 2001 From: Edison Su Date: Mon, 19 Dec 2011 15:18:12 -0800 Subject: [PATCH 33/69] bug 12625: don't put volume into snapshotting state if we are taking snapshot on it status 12625: resolved fixed --- .../src/com/cloud/storage/snapshot/SnapshotManagerImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 5203ec7a513..fc12c2e064f 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -432,6 +432,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma //when taking snapshot, make sure nobody can delete/move the volume boolean stateTransit = false; + /* try { stateTransit = _storageMgr.stateTransitTo(volume, Volume.Event.SnapshotRequested); } catch (NoTransitionException e) { @@ -441,7 +442,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma _snapshotDao.expunge(snapshotId); throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volumeId + " is being used, try it later "); } - } + }*/ snapshot = createSnapshotOnPrimary(volume, policyId, snapshotId); if (snapshot != null) { @@ -489,11 +490,12 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma } } + /* try { _storageMgr.stateTransitTo(volume, Volume.Event.OperationSucceeded); } catch (NoTransitionException e) { s_logger.debug("Failed to transit volume state: " + e.toString()); - } + }*/ } From d33a23cca63d79de8d356339eff687eb938c97ea Mon Sep 17 00:00:00 2001 From: Edison Su Date: Mon, 19 Dec 2011 15:24:31 -0800 Subject: [PATCH 34/69] bug 12628: add default route in dhcpentrycommand status 12628: resolved fixed --- .../virtualnetwork/VirtualRoutingResource.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index d10e25da40b..65bc8d69fbc 100755 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -462,6 +462,17 @@ public class VirtualRoutingResource implements Manager { command.add("-v", cmd.getVmIpAddress()); command.add("-m", cmd.getVmMac()); command.add("-n", cmd.getVmName()); + + if (cmd.getDefaultRouter() != null) { + command.add(" -d " + cmd.getDefaultRouter()); + } + if (cmd.getStaticRoutes() != null) { + command.add(" -s " + cmd.getStaticRoutes()); + } + + if (cmd.getDefaultDns() != null) { + command.add(" -N " + cmd.getDefaultDns()); + } final String result = command.execute(); return new Answer(cmd, result==null, result); From b33c6f6de4ee1099be9e2bf18452152f37edf1ba Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 18:29:49 -0500 Subject: [PATCH 35/69] bug 12211: Implement project dashboard status 12211: resolved fixed --- ui/index.jsp | 10 ++++---- ui/scripts/projects.js | 42 +++++++++++++++++++++++++++++--- ui/scripts/ui-custom/projects.js | 14 ++++++++--- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/ui/index.jsp b/ui/index.jsp index e6a600d75c1..eb809e126cd 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -832,20 +832,20 @@
    • -
      171
      +
      IP addresses
    • -
      04
      +
      Load balancing policies
    • - +
    • -
      23
      -
      Security groups
      +
      +
      Port forwarding policies
    • diff --git a/ui/scripts/projects.js b/ui/scripts/projects.js index 59f7e20b683..30e204168f5 100644 --- a/ui/scripts/projects.js +++ b/ui/scripts/projects.js @@ -18,7 +18,7 @@ return instance.state == 'Running'; }).length, stoppedInstances: $.grep(instances, function(instance) { - return instance.state == 'Stopped'; + return instance.state != 'Running'; }).length, totalInstances: instances.length })); @@ -32,7 +32,7 @@ success: function(json) { dataFns.bandwidth($.extend(data, { totalVolumes: json.listvolumesresponse.volume ? - json.listvolumesresponse.volume.count : 0 + json.listvolumesresponse.count : 0 })); } }); @@ -60,13 +60,49 @@ }); }); - dataFns.users($.extend(data, { + dataFns.ipAddresses($.extend(data, { totalBandwidth: totalBandwidth })); } }); }, + ipAddresses: function(data) { + $.ajax({ + url: createURL('listPublicIpAddresses'), + success: function(json) { + dataFns.loadBalancingRules($.extend(data, { + totalIPAddresses: json.listpublicipaddressesresponse ? + json.listpublicipaddressesresponse.count : 0 + })); + } + }); + }, + + loadBalancingRules: function(data) { + $.ajax({ + url: createURL('listLoadBalancerRules'), + success: function(json) { + dataFns.portForwardingRules($.extend(data, { + totalLoadBalancers: json.listloadbalancerrulesresponse ? + json.listloadbalancerrulesresponse.count : 0 + })); + } + }); + }, + + portForwardingRules: function(data) { + $.ajax({ + url: createURL('listPortForwardingRules'), + success: function(json) { + dataFns.users($.extend(data, { + totalPortForwards: json.listportforwardingrulesresponse ? + json.listportforwardingrulesresponse.count : 0 + })); + } + }); + }, + users: function(data) { $.ajax({ url: createURL('listProjectAccounts'), diff --git a/ui/scripts/ui-custom/projects.js b/ui/scripts/ui-custom/projects.js index 91f9c0c0872..73b9e2162ff 100644 --- a/ui/scripts/ui-custom/projects.js +++ b/ui/scripts/ui-custom/projects.js @@ -25,9 +25,11 @@ var getData = function() { // Populate data $dashboard.find('[data-item]').hide(); + var $loading = $('
      ').addClass('loading-overlay').prependTo($dashboard); cloudStack.projects.dashboard({ response: { success: function(args) { + $loading.remove(); var data = args.data; // Iterate over data; populate corresponding DOM elements @@ -70,6 +72,14 @@ getData(); + $dashboard.find('.button.manage-resources').click(function() { + $('.navigation-item.network').click(); + }); + + $dashboard.find('.info-box.events .button').click(function() { + $('.navigation-item.events').click(); + }); + return $dashboard; } }; @@ -101,7 +111,7 @@ var $content = $('
      ') .appendTo($tabs) .attr({ id: 'project-view-dashboard-' + tabName }) - .append(tab()); + .append(tab); }); $tabs.find('ul li:first').addClass('first'); @@ -462,8 +472,6 @@ .filter(function() { return $(this).data('json-obj').name == cloudStack.context.projects[0].name; }).attr('selected', 'selected'); - showDashboard(); - //// // Hidden for now From bdd0e8f86052ec3301a78c554d1c510e3b80d229 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 15:32:16 -0800 Subject: [PATCH 36/69] bug 12642: removed restriction on project state from listResourceLimits command status 12642: resolved fixed --- api/src/com/cloud/api/BaseCmd.java | 10 +++++++--- api/src/com/cloud/api/commands/AddVpnUserCmd.java | 2 +- api/src/com/cloud/api/commands/AssociateIPAddrCmd.java | 2 +- .../api/commands/AuthorizeSecurityGroupEgressCmd.java | 2 +- .../api/commands/AuthorizeSecurityGroupIngressCmd.java | 2 +- api/src/com/cloud/api/commands/CreateNetworkCmd.java | 2 +- .../com/cloud/api/commands/CreateSSHKeyPairCmd.java | 2 +- api/src/com/cloud/api/commands/CreateVMGroupCmd.java | 2 +- api/src/com/cloud/api/commands/CreateVolumeCmd.java | 2 +- .../com/cloud/api/commands/DeleteSecurityGroupCmd.java | 2 +- api/src/com/cloud/api/commands/DeployVMCmd.java | 2 +- .../com/cloud/api/commands/ListResourceLimitsCmd.java | 2 +- api/src/com/cloud/api/commands/RegisterIsoCmd.java | 2 +- .../com/cloud/api/commands/RegisterSSHKeyPairCmd.java | 2 +- .../com/cloud/api/commands/RegisterTemplateCmd.java | 2 +- api/src/com/cloud/api/commands/RemoveVpnUserCmd.java | 2 +- .../com/cloud/api/commands/UpdateResourceCountCmd.java | 2 +- .../com/cloud/api/commands/UpdateResourceLimitCmd.java | 4 ++-- 18 files changed, 25 insertions(+), 21 deletions(-) diff --git a/api/src/com/cloud/api/BaseCmd.java b/api/src/com/cloud/api/BaseCmd.java index 3b97d6bb970..d520d4a589f 100755 --- a/api/src/com/cloud/api/BaseCmd.java +++ b/api/src/com/cloud/api/BaseCmd.java @@ -459,7 +459,7 @@ public abstract class BaseCmd { return this.fullUrlParams; } - public Long getAccountId(String accountName, Long domainId, Long projectId) { + public Long getAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { if (accountName != null) { if (domainId == null) { throw new InvalidParameterValueException("Account must be specified with domainId parameter"); @@ -472,7 +472,11 @@ public abstract class BaseCmd { Account account = _accountService.getActiveAccountByName(accountName, domainId); if (account != null && account.getType() != Account.ACCOUNT_TYPE_PROJECT) { - return account.getId(); + if (!enabledOnly || account.getState() == Account.State.enabled) { + return account.getId(); + } else { + throw new InvalidParameterValueException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active"); + } } else { throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain id=" + domainId); } @@ -481,7 +485,7 @@ public abstract class BaseCmd { if (projectId != null) { Project project = _projectService.getProject(projectId); if (project != null) { - if (project.getState() == Project.State.Active) { + if (!enabledOnly || project.getState() == Project.State.Active) { return project.getProjectAccountId(); } else { throw new InvalidParameterValueException("Can't add resources to the project id=" + projectId + " in state=" + project.getState() + " as it's no longer active"); diff --git a/api/src/com/cloud/api/commands/AddVpnUserCmd.java b/api/src/com/cloud/api/commands/AddVpnUserCmd.java index c605b328af1..7d2ca5df5f6 100644 --- a/api/src/com/cloud/api/commands/AddVpnUserCmd.java +++ b/api/src/com/cloud/api/commands/AddVpnUserCmd.java @@ -96,7 +96,7 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java index 234c17be3e2..64761a3fc51 100644 --- a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java +++ b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java @@ -129,7 +129,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java index be522ccff34..f37da382479 100644 --- a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java @@ -164,7 +164,7 @@ public class AuthorizeSecurityGroupEgressCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java index c95cb5b7e1d..2f10eb32ad8 100644 --- a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java @@ -166,7 +166,7 @@ public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateNetworkCmd.java b/api/src/com/cloud/api/commands/CreateNetworkCmd.java index c7ff560c50c..8b5c6b4bcb1 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkCmd.java @@ -199,7 +199,7 @@ public class CreateNetworkCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java b/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java index b51c510e46d..5cbf4eee59c 100644 --- a/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java +++ b/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java @@ -80,7 +80,7 @@ public class CreateSSHKeyPairCmd extends BaseCmd { ///////////////////////////////////////////////////// @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateVMGroupCmd.java b/api/src/com/cloud/api/commands/CreateVMGroupCmd.java index 1593a98939b..fa5b680bb63 100644 --- a/api/src/com/cloud/api/commands/CreateVMGroupCmd.java +++ b/api/src/com/cloud/api/commands/CreateVMGroupCmd.java @@ -84,7 +84,7 @@ public class CreateVMGroupCmd extends BaseCmd{ @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateVolumeCmd.java b/api/src/com/cloud/api/commands/CreateVolumeCmd.java index 75713fdfe24..ee3a4041a70 100644 --- a/api/src/com/cloud/api/commands/CreateVolumeCmd.java +++ b/api/src/com/cloud/api/commands/CreateVolumeCmd.java @@ -131,7 +131,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java b/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java index 70cc1322438..4acc9d26a6d 100644 --- a/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java +++ b/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java @@ -89,7 +89,7 @@ public class DeleteSecurityGroupCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/DeployVMCmd.java b/api/src/com/cloud/api/commands/DeployVMCmd.java index 71b59995180..c5bbf4c9819 100644 --- a/api/src/com/cloud/api/commands/DeployVMCmd.java +++ b/api/src/com/cloud/api/commands/DeployVMCmd.java @@ -281,7 +281,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java b/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java index 06dc81506c0..76a030bdd39 100644 --- a/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java +++ b/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java @@ -94,7 +94,7 @@ public class ListResourceLimitsCmd extends BaseListCmd { @Override public void execute(){ - List result = _resourceLimitService.searchForLimits(id, getAccountId(accountName, domainId, projectId), domainId, resourceType, this.getStartIndex(), this.getPageSizeVal()); + List result = _resourceLimitService.searchForLimits(id, getAccountId(accountName, domainId, projectId, false), domainId, resourceType, this.getStartIndex(), this.getPageSizeVal()); ListResponse response = new ListResponse(); List limitResponses = new ArrayList(); for (ResourceLimit limit : result) { diff --git a/api/src/com/cloud/api/commands/RegisterIsoCmd.java b/api/src/com/cloud/api/commands/RegisterIsoCmd.java index 16b72a39950..2b66dfef938 100755 --- a/api/src/com/cloud/api/commands/RegisterIsoCmd.java +++ b/api/src/com/cloud/api/commands/RegisterIsoCmd.java @@ -152,7 +152,7 @@ public class RegisterIsoCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java b/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java index 8240d3af3eb..73720f18cd1 100644 --- a/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java +++ b/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java @@ -87,7 +87,7 @@ public class RegisterSSHKeyPairCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/RegisterTemplateCmd.java b/api/src/com/cloud/api/commands/RegisterTemplateCmd.java index 6b098149d17..ef8411ad57c 100755 --- a/api/src/com/cloud/api/commands/RegisterTemplateCmd.java +++ b/api/src/com/cloud/api/commands/RegisterTemplateCmd.java @@ -213,7 +213,7 @@ public class RegisterTemplateCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java b/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java index cca05ed947e..b656ed14112 100644 --- a/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java +++ b/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java @@ -88,7 +88,7 @@ public class RemoveVpnUserCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java b/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java index a5797382dec..f47611cfa84 100644 --- a/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java +++ b/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java @@ -112,7 +112,7 @@ public class UpdateResourceCountCmd extends BaseCmd { @Override public void execute(){ - List result = _resourceLimitService.recalculateResourceCount(getAccountId(accountName, domainId, projectId), getDomainId(), getResourceType()); + List result = _resourceLimitService.recalculateResourceCount(getAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType()); if ((result != null) && (result.size()>0)){ ListResponse response = new ListResponse(); diff --git a/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java b/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java index e150f587f87..35091f39df4 100644 --- a/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java +++ b/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java @@ -89,7 +89,7 @@ public class UpdateResourceLimitCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId); + Long accountId = getAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } @@ -99,7 +99,7 @@ public class UpdateResourceLimitCmd extends BaseCmd { @Override public void execute(){ - ResourceLimit result = _resourceLimitService.updateResourceLimit(getAccountId(accountName, domainId, projectId), getDomainId(), resourceType, max); + ResourceLimit result = _resourceLimitService.updateResourceLimit(getAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max); if (result != null || (result == null && max != null && max.longValue() == -1L)){ ResourceLimitResponse response = _responseGenerator.createResourceLimitResponse(result); response.setResponseName(getCommandName()); From bb11bf9efd6c902615de7c87b050db42fc7e6e02 Mon Sep 17 00:00:00 2001 From: anthony Date: Mon, 19 Dec 2011 15:36:59 -0800 Subject: [PATCH 37/69] SWIFT : fixed create template from snapshot --- .../resource/NfsSecondaryStorageResource.java | 1 + .../storage/snapshot/SnapshotManager.java | 2 -- .../storage/snapshot/SnapshotManagerImpl.java | 34 ++----------------- 3 files changed, 3 insertions(+), 34 deletions(-) diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index 20584a2efb1..b77edd9e948 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -393,6 +393,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } } } + return new Answer(cmd, true, "success"); } catch (Exception e) { String msg = cmd + " Command failed due to " + e.toString(); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java index ad78e75874f..0aa53fe0250 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java @@ -111,8 +111,6 @@ public interface SnapshotManager { */ boolean deleteSnapshotDirsForAccount(long accountId); - void validateSnapshot(Long userId, SnapshotVO snapshot); - SnapshotPolicyVO getPolicyForVolume(long volumeId); boolean destroySnapshotBackUp(long snapshotId); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index fc12c2e064f..86f45595309 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -81,7 +81,6 @@ import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolVO; -import com.cloud.storage.SwiftVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; @@ -300,6 +299,8 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma s_logger.debug("CreateSnapshot: this is empty snapshot "); snapshot.setPath(preSnapshotPath); snapshot.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId()); + snapshot.setSwiftId(preSnapshotVO.getSwiftId()); + snapshot.setStatus(Snapshot.Status.BackedUp); snapshot.setPrevSnapshotId(preId); snapshot.setSecHostId(preSnapshotVO.getSecHostId()); @@ -511,34 +512,6 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma return createdSnapshot; } - @Override - @DB - @SuppressWarnings("fallthrough") - public void validateSnapshot(Long userId, SnapshotVO snapshot) { - assert snapshot != null; - Long id = snapshot.getId(); - Status status = snapshot.getStatus(); - s_logger.debug("Snapshot scheduler found a snapshot whose actual status is not clear. Snapshot id:" + id + " with DB status: " + status); - - switch (status) { - case Creating: - // else continue to the next case. - case CreatedOnPrimary: - // The snapshot has been created on the primary and the DB has been updated. - // However, it hasn't entered the backupSnapshotToSecondaryStorage, else - // status would have been backing up. - // So call backupSnapshotToSecondaryStorage without any fear. - case BackingUp: - // It has entered backupSnapshotToSecondaryStorage. - // But we have no idea whether it was backed up or not. - // So call backupSnapshotToSecondaryStorage again. - backupSnapshotToSecondaryStorage(snapshot); - break; - case BackedUp: - // No need to do anything as snapshot has already been backed up. - } - } - @Override public void deleteSnapshotsForVolume (String secondaryStoragePoolUrl, Long dcId, Long accountId, Long volumeId ){ @@ -605,9 +578,6 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma } - private SwiftTO toSwiftTO(SwiftVO swift) { - return new SwiftTO(swift.getId(), swift.getUrl(), swift.getAccount(), swift.getUserName(), swift.getKey()); - } @Override @DB From 6d320507fd57c89574673876a327d6322a8c5edd Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Mon, 19 Dec 2011 15:31:36 -0800 Subject: [PATCH 38/69] bug 12667: Use gateway ip for redundant router as DNS status 12667: resolved fixed --- .../network/router/VirtualNetworkApplianceManagerImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index de2bcd24d9d..ee2938c8058 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -2161,6 +2161,11 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian return null; } + NetworkOfferingVO offering = _networkOfferingDao.findById(_networkDao.findById(defaultNic.getNetworkId()).getNetworkOfferingId()); + if (offering.getRedundantRouter()) { + return findGatewayIp(userVmId); + } + //find domR's nic in the network NicVO domrDefaultNic = _nicDao.findByNetworkIdAndType(defaultNic.getNetworkId(), VirtualMachine.Type.DomainRouter); return domrDefaultNic.getIp4Address(); From 8ef2724c263381d78cc9d14e1cdb926e293b6cf7 Mon Sep 17 00:00:00 2001 From: frank Date: Mon, 19 Dec 2011 15:49:56 -0800 Subject: [PATCH 39/69] better log when deploy vm failed --- server/src/com/cloud/vm/VirtualMachineManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 26cbb48ad9a..fd0533c970c 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -825,7 +825,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene } } catch (Exception e) { s_logger.error("Failed to start instance " + vm, e); - throw new AgentUnavailableException("Unable to start instance", destHostId, e); + throw new AgentUnavailableException("Unable to start instance due to " + e.getMessage(), destHostId, e); } finally { if (startedVm == null && canRetry) { _workDao.updateStep(work, Step.Release); From e081dd3c91a4298f5e57f1e31551c9f628b687f4 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 19 Dec 2011 15:52:41 -0800 Subject: [PATCH 40/69] bug 12614: cloudStack 3.0 new UI - system - Add Zone Wizard - basic zone - when securityGroupsEnabled checkbox is checked, enable security groups provider before create network. --- ui/scripts/system.js | 214 +++++++++++++++++++++++++++++++++---------- 1 file changed, 166 insertions(+), 48 deletions(-) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index c41a1a8289a..cd6ec2bd47b 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -279,7 +279,7 @@ }); } }, - ipAddresses: { //read-only listView (no actions) filled with pod info (not VlanIpRange info)??? + ipAddresses: { //read-only listView (no actions) filled with pod info (not VlanIpRange info) title: 'IP Ranges', listView: { fields: { @@ -2974,7 +2974,7 @@ //alert("updatePhysicalNetwork succeeded."); // get network service provider ID of Virtual Router - var networkServiceProviderId; + var virtualRouterProviderId; $.ajax({ url: createURL("listNetworkServiceProviders&name=VirtualRouter&physicalNetworkId=" + physicalNetworkId), dataType: "json", @@ -2982,18 +2982,18 @@ success: function(json) { var items = json.listnetworkserviceprovidersresponse.networkserviceprovider; if(items != null && items.length > 0) { - networkServiceProviderId = items[0].id; + virtualRouterProviderId = items[0].id; } } }); - if(networkServiceProviderId == null) { - alert("error: listNetworkServiceProviders API doesn't return Network Service Provider ID"); + if(virtualRouterProviderId == null) { + alert("error: listNetworkServiceProviders API doesn't return VirtualRouter provider ID"); return; } var virtualRouterElementId; $.ajax({ - url: createURL("listVirtualRouterElements&nspid=" + networkServiceProviderId), + url: createURL("listVirtualRouterElements&nspid=" + virtualRouterProviderId), dataType: "json", async: false, success: function(json) { @@ -3030,7 +3030,7 @@ //alert("configureVirtualRouterElement succeeded."); $.ajax({ - url: createURL("updateNetworkServiceProvider&state=Enabled&id=" + networkServiceProviderId), + url: createURL("updateNetworkServiceProvider&state=Enabled&id=" + virtualRouterProviderId), dataType: "json", async: false, success: function(json) { @@ -3048,52 +3048,170 @@ else { $("body").stopTime(timerKey); if (result.jobstatus == 1) { - //alert("updateNetworkServiceProvider succeeded."); - - //create network if it's basic zone - if(newZoneObj.networktype == "Basic") { - var array2 = []; - array2.push("&zoneid=" + newZoneObj.id); - array2.push("&name=guestNetworkForBasicZone"); - array2.push("&displaytext=guestNetworkForBasicZone"); - array2.push("&networkofferingid=" + args.data.networkOfferingId); - $.ajax({ - url: createURL("createNetwork" + array2.join("")), - dataType: "json", - async: false, - success: function(json) { - - } - }); - } + //alert("Virtual Router Provider is enabled"); - //create pod - var array3 = []; - array3.push("&zoneId=" + newZoneObj.id); - array3.push("&name=" + todb(args.data.podName)); - array3.push("&gateway=" + todb(args.data.podGateway)); - array3.push("&netmask=" + todb(args.data.podNetmask)); - array3.push("&startIp=" + todb(args.data.podStartIp)); + if(newZoneObj.networktype == "Basic") { + if(args.data["security-groups-enabled"] == "on") { //need to Enable security group provider first + // get network service provider ID of Security Group + var securityGroupProviderId; + $.ajax({ + url: createURL("listNetworkServiceProviders&name=SecurityGroupProvider&physicalNetworkId=" + physicalNetworkId), + dataType: "json", + async: false, + success: function(json) { + var items = json.listnetworkserviceprovidersresponse.networkserviceprovider; + if(items != null && items.length > 0) { + securityGroupProviderId = items[0].id; + } + } + }); + if(securityGroupProviderId == null) { + alert("error: listNetworkServiceProviders API doesn't return security group provider ID"); + return; + } + + $.ajax({ + url: createURL("updateNetworkServiceProvider&state=Enabled&id=" + securityGroupProviderId), + dataType: "json", + async: false, + success: function(json) { + var jobId = json.updatenetworkserviceproviderresponse.jobid; + var timerKey = "updateNetworkServiceProviderJob_"+jobId; + $("body").everyTime(2000, timerKey, function() { + $.ajax({ + url: createURL("queryAsyncJobResult&jobId="+jobId), + dataType: "json", + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + $("body").stopTime(timerKey); + if (result.jobstatus == 1) { + //alert("Security group provider is enabled"); - var endip = args.data.podEndIp; //optional - if (endip != null && endip.length > 0) - array3.push("&endIp=" + todb(endip)); + //create network (for basic zone only) + var array2 = []; + array2.push("&zoneid=" + newZoneObj.id); + array2.push("&name=guestNetworkForBasicZone"); + array2.push("&displaytext=guestNetworkForBasicZone"); + array2.push("&networkofferingid=" + args.data.networkOfferingId); + $.ajax({ + url: createURL("createNetwork" + array2.join("")), + dataType: "json", + async: false, + success: function(json) { + //create pod + var array3 = []; + array3.push("&zoneId=" + newZoneObj.id); + array3.push("&name=" + todb(args.data.podName)); + array3.push("&gateway=" + todb(args.data.podGateway)); + array3.push("&netmask=" + todb(args.data.podNetmask)); + array3.push("&startIp=" + todb(args.data.podStartIp)); - $.ajax({ - url: createURL("createPod" + array3.join("")), - dataType: "json", - async: false, - success: function(json) { - - }, - error: function(XMLHttpResponse) { - var errorMsg = parseXMLHttpResponse(XMLHttpResponse); - alert("createPod failed. Error: " + errorMsg); - } - }); + var endip = args.data.podEndIp; //optional + if (endip != null && endip.length > 0) + array3.push("&endIp=" + todb(endip)); + + $.ajax({ + url: createURL("createPod" + array3.join("")), + dataType: "json", + async: false, + success: function(json) { + + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + alert("createPod failed. Error: " + errorMsg); + } + }); + } + }); + } + else if (result.jobstatus == 2) { + alert("failed to enable security group provider. Error: " + fromdb(result.jobresult.errortext)); + } + } + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + alert("updateNetworkServiceProvider failed. Error: " + errorMsg); + } + }); + }); + } + }); + } + else { + //create network (for basic zone only) + var array2 = []; + array2.push("&zoneid=" + newZoneObj.id); + array2.push("&name=guestNetworkForBasicZone"); + array2.push("&displaytext=guestNetworkForBasicZone"); + array2.push("&networkofferingid=" + args.data.networkOfferingId); + $.ajax({ + url: createURL("createNetwork" + array2.join("")), + dataType: "json", + async: false, + success: function(json) { + //create pod + var array3 = []; + array3.push("&zoneId=" + newZoneObj.id); + array3.push("&name=" + todb(args.data.podName)); + array3.push("&gateway=" + todb(args.data.podGateway)); + array3.push("&netmask=" + todb(args.data.podNetmask)); + array3.push("&startIp=" + todb(args.data.podStartIp)); + + var endip = args.data.podEndIp; //optional + if (endip != null && endip.length > 0) + array3.push("&endIp=" + todb(endip)); + + $.ajax({ + url: createURL("createPod" + array3.join("")), + dataType: "json", + async: false, + success: function(json) { + + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + alert("createPod failed. Error: " + errorMsg); + } + }); + } + }); + } + } + else { //Advanced zone + //create pod + var array3 = []; + array3.push("&zoneId=" + newZoneObj.id); + array3.push("&name=" + todb(args.data.podName)); + array3.push("&gateway=" + todb(args.data.podGateway)); + array3.push("&netmask=" + todb(args.data.podNetmask)); + array3.push("&startIp=" + todb(args.data.podStartIp)); + + var endip = args.data.podEndIp; //optional + if (endip != null && endip.length > 0) + array3.push("&endIp=" + todb(endip)); + + $.ajax({ + url: createURL("createPod" + array3.join("")), + dataType: "json", + async: false, + success: function(json) { + + }, + error: function(XMLHttpResponse) { + var errorMsg = parseXMLHttpResponse(XMLHttpResponse); + alert("createPod failed. Error: " + errorMsg); + } + }); + } } else if (result.jobstatus == 2) { - alert("updateNetworkServiceProvider failed. Error: " + fromdb(result.jobresult.errortext)); + alert("failed to enable Virtual Router Provider. Error: " + fromdb(result.jobresult.errortext)); } } }, From ceb0a918a11f7b8cf5719c904ac5d500f0f6fde5 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 16:20:10 -0800 Subject: [PATCH 41/69] createTemplate/createSnapshot for project - allow to execute for Projects in Active state only --- api/src/com/cloud/api/BaseCmd.java | 9 +++-- .../com/cloud/api/commands/AddVpnUserCmd.java | 2 +- .../api/commands/AssociateIPAddrCmd.java | 2 +- .../AuthorizeSecurityGroupEgressCmd.java | 2 +- .../AuthorizeSecurityGroupIngressCmd.java | 2 +- .../cloud/api/commands/CreateNetworkCmd.java | 2 +- .../api/commands/CreateSSHKeyPairCmd.java | 2 +- .../cloud/api/commands/CreateSnapshotCmd.java | 33 ++++++++++++++---- .../cloud/api/commands/CreateTemplateCmd.java | 33 +++++++++++++----- .../cloud/api/commands/CreateVMGroupCmd.java | 2 +- .../cloud/api/commands/CreateVolumeCmd.java | 2 +- .../api/commands/DeleteSecurityGroupCmd.java | 2 +- .../com/cloud/api/commands/DeployVMCmd.java | 2 +- .../api/commands/ListResourceLimitsCmd.java | 2 +- .../cloud/api/commands/RegisterIsoCmd.java | 2 +- .../api/commands/RegisterSSHKeyPairCmd.java | 2 +- .../api/commands/RegisterTemplateCmd.java | 2 +- .../cloud/api/commands/RemoveVpnUserCmd.java | 2 +- .../api/commands/UpdateResourceCountCmd.java | 2 +- .../api/commands/UpdateResourceLimitCmd.java | 4 +-- .../storage/snapshot/SnapshotService.java | 6 ++-- api/src/com/cloud/vm/UserVmService.java | 3 +- .../baremetal/BareMetalVmManagerImpl.java | 2 +- .../storage/snapshot/SnapshotManagerImpl.java | 9 ++--- .../src/com/cloud/vm/UserVmManagerImpl.java | 34 ++++++------------- .../com/cloud/vm/MockUserVmManagerImpl.java | 2 +- 26 files changed, 95 insertions(+), 72 deletions(-) diff --git a/api/src/com/cloud/api/BaseCmd.java b/api/src/com/cloud/api/BaseCmd.java index d520d4a589f..14f3b59ce5d 100755 --- a/api/src/com/cloud/api/BaseCmd.java +++ b/api/src/com/cloud/api/BaseCmd.java @@ -35,6 +35,7 @@ import com.cloud.domain.Domain; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.NetworkService; @@ -459,7 +460,7 @@ public abstract class BaseCmd { return this.fullUrlParams; } - public Long getAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { + public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { if (accountName != null) { if (domainId == null) { throw new InvalidParameterValueException("Account must be specified with domainId parameter"); @@ -475,7 +476,7 @@ public abstract class BaseCmd { if (!enabledOnly || account.getState() == Account.State.enabled) { return account.getId(); } else { - throw new InvalidParameterValueException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active"); + throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active"); } } else { throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain id=" + domainId); @@ -488,14 +489,12 @@ public abstract class BaseCmd { if (!enabledOnly || project.getState() == Project.State.Active) { return project.getProjectAccountId(); } else { - throw new InvalidParameterValueException("Can't add resources to the project id=" + projectId + " in state=" + project.getState() + " as it's no longer active"); + throw new PermissionDeniedException("Can't add resources to the project id=" + projectId + " in state=" + project.getState() + " as it's no longer active"); } - } else { throw new InvalidParameterValueException("Unable to find project by id " + projectId); } } - return null; } } diff --git a/api/src/com/cloud/api/commands/AddVpnUserCmd.java b/api/src/com/cloud/api/commands/AddVpnUserCmd.java index 7d2ca5df5f6..6336b98bf89 100644 --- a/api/src/com/cloud/api/commands/AddVpnUserCmd.java +++ b/api/src/com/cloud/api/commands/AddVpnUserCmd.java @@ -96,7 +96,7 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java index 64761a3fc51..6f454388fd2 100644 --- a/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java +++ b/api/src/com/cloud/api/commands/AssociateIPAddrCmd.java @@ -129,7 +129,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java index f37da382479..c840bb3fe17 100644 --- a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupEgressCmd.java @@ -164,7 +164,7 @@ public class AuthorizeSecurityGroupEgressCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java index 2f10eb32ad8..32f20ca91b0 100644 --- a/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/com/cloud/api/commands/AuthorizeSecurityGroupIngressCmd.java @@ -166,7 +166,7 @@ public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateNetworkCmd.java b/api/src/com/cloud/api/commands/CreateNetworkCmd.java index 8b5c6b4bcb1..87e5a2d3aad 100644 --- a/api/src/com/cloud/api/commands/CreateNetworkCmd.java +++ b/api/src/com/cloud/api/commands/CreateNetworkCmd.java @@ -199,7 +199,7 @@ public class CreateNetworkCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java b/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java index 5cbf4eee59c..5645aa8dfa2 100644 --- a/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java +++ b/api/src/com/cloud/api/commands/CreateSSHKeyPairCmd.java @@ -80,7 +80,7 @@ public class CreateSSHKeyPairCmd extends BaseCmd { ///////////////////////////////////////////////////// @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateSnapshotCmd.java b/api/src/com/cloud/api/commands/CreateSnapshotCmd.java index d10ae4899be..7ed9f7810e5 100755 --- a/api/src/com/cloud/api/commands/CreateSnapshotCmd.java +++ b/api/src/com/cloud/api/commands/CreateSnapshotCmd.java @@ -30,7 +30,10 @@ import com.cloud.api.ServerApiException; import com.cloud.api.response.SnapshotResponse; import com.cloud.async.AsyncJob; import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; +import com.cloud.projects.Project; import com.cloud.storage.Snapshot; import com.cloud.storage.Volume; import com.cloud.user.Account; @@ -103,13 +106,29 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Volume volume = _entityMgr.findById(Volume.class, getVolumeId()); - if (volume != null) { - return volume.getAccountId(); - } + Long volumeId = getVolumeId(); + Long accountId = null; - // bad id given, parent this command to SYSTEM so ERROR events are tracked - return Account.ACCOUNT_ID_SYSTEM; + Volume volume = _entityMgr.findById(Volume.class, volumeId); + if (volume != null) { + accountId = volume.getAccountId(); + } else { + throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId); + } + + + Account account = _accountService.getAccount(accountId); + //Can create templates for enabled projects/accounts only + if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { + Project project = _projectService.findByProjectAccountId(accountId); + if (project.getState() != Project.State.Active) { + throw new PermissionDeniedException("Can't add resources to the project id=" + project.getId() + " in state=" + project.getState() + " as it's no longer active"); + } + } else if (account.getState() == Account.State.disabled) { + throw new PermissionDeniedException("The owner of template is disabled: " + account); + } + + return accountId; } @Override @@ -140,7 +159,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { @Override public void execute() { UserContext.current().setEventDetails("Volume Id: "+getVolumeId()); - Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId()); + Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId())); if (snapshot != null) { SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot); response.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/api/commands/CreateTemplateCmd.java b/api/src/com/cloud/api/commands/CreateTemplateCmd.java index 397f868346a..287d757f2b9 100755 --- a/api/src/com/cloud/api/commands/CreateTemplateCmd.java +++ b/api/src/com/cloud/api/commands/CreateTemplateCmd.java @@ -35,7 +35,10 @@ import com.cloud.api.response.StoragePoolResponse; import com.cloud.api.response.TemplateResponse; import com.cloud.async.AsyncJob; import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; +import com.cloud.projects.Project; import com.cloud.storage.Snapshot; import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate; @@ -185,20 +188,35 @@ import com.cloud.user.UserContext; public long getEntityOwnerId() { Long volumeId = getVolumeId(); Long snapshotId = getSnapshotId(); + Long accountId = null; if (volumeId != null) { Volume volume = _entityMgr.findById(Volume.class, volumeId); if (volume != null) { - return volume.getAccountId(); + accountId = volume.getAccountId(); + } else { + throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId); } } else { Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId); if (snapshot != null) { - return snapshot.getAccountId(); + accountId = snapshot.getAccountId(); + } else { + throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId); } } - - // bad id given, parent this command to SYSTEM so ERROR events are tracked - return Account.ACCOUNT_ID_SYSTEM; + + Account account = _accountService.getAccount(accountId); + //Can create templates for enabled projects/accounts only + if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { + Project project = _projectService.findByProjectAccountId(accountId); + if (project.getState() != Project.State.Active) { + throw new PermissionDeniedException("Can't add resources to the project id=" + project.getId() + " in state=" + project.getState() + " as it's no longer active"); + } + } else if (account.getState() == Account.State.disabled) { + throw new PermissionDeniedException("The owner of template is disabled: " + account); + } + + return accountId; } @Override @@ -223,13 +241,12 @@ import com.cloud.user.UserContext; @Override public void create() throws ResourceAllocationException { if (isBareMetal()) { - _bareMetalVmService.createPrivateTemplateRecord(this); + _bareMetalVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId())); /*Baremetal creates template record after taking image proceeded, use vmId as entity id here*/ this.setEntityId(vmId); } else { VirtualMachineTemplate template = null; - template = _userVmService.createPrivateTemplateRecord(this); - + template = _userVmService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId())); if (template != null) { this.setEntityId(template.getId()); } else { diff --git a/api/src/com/cloud/api/commands/CreateVMGroupCmd.java b/api/src/com/cloud/api/commands/CreateVMGroupCmd.java index fa5b680bb63..a760612f7cc 100644 --- a/api/src/com/cloud/api/commands/CreateVMGroupCmd.java +++ b/api/src/com/cloud/api/commands/CreateVMGroupCmd.java @@ -84,7 +84,7 @@ public class CreateVMGroupCmd extends BaseCmd{ @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/CreateVolumeCmd.java b/api/src/com/cloud/api/commands/CreateVolumeCmd.java index ee3a4041a70..83924d0adf0 100644 --- a/api/src/com/cloud/api/commands/CreateVolumeCmd.java +++ b/api/src/com/cloud/api/commands/CreateVolumeCmd.java @@ -131,7 +131,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java b/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java index 4acc9d26a6d..7c6788a29e9 100644 --- a/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java +++ b/api/src/com/cloud/api/commands/DeleteSecurityGroupCmd.java @@ -89,7 +89,7 @@ public class DeleteSecurityGroupCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/DeployVMCmd.java b/api/src/com/cloud/api/commands/DeployVMCmd.java index c5bbf4c9819..56301acf8dc 100644 --- a/api/src/com/cloud/api/commands/DeployVMCmd.java +++ b/api/src/com/cloud/api/commands/DeployVMCmd.java @@ -281,7 +281,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java b/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java index 76a030bdd39..45e6d11dfdb 100644 --- a/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java +++ b/api/src/com/cloud/api/commands/ListResourceLimitsCmd.java @@ -94,7 +94,7 @@ public class ListResourceLimitsCmd extends BaseListCmd { @Override public void execute(){ - List result = _resourceLimitService.searchForLimits(id, getAccountId(accountName, domainId, projectId, false), domainId, resourceType, this.getStartIndex(), this.getPageSizeVal()); + List result = _resourceLimitService.searchForLimits(id, finalyzeAccountId(accountName, domainId, projectId, false), domainId, resourceType, this.getStartIndex(), this.getPageSizeVal()); ListResponse response = new ListResponse(); List limitResponses = new ArrayList(); for (ResourceLimit limit : result) { diff --git a/api/src/com/cloud/api/commands/RegisterIsoCmd.java b/api/src/com/cloud/api/commands/RegisterIsoCmd.java index 2b66dfef938..47365e558c1 100755 --- a/api/src/com/cloud/api/commands/RegisterIsoCmd.java +++ b/api/src/com/cloud/api/commands/RegisterIsoCmd.java @@ -152,7 +152,7 @@ public class RegisterIsoCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java b/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java index 73720f18cd1..87c81f895f0 100644 --- a/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java +++ b/api/src/com/cloud/api/commands/RegisterSSHKeyPairCmd.java @@ -87,7 +87,7 @@ public class RegisterSSHKeyPairCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/RegisterTemplateCmd.java b/api/src/com/cloud/api/commands/RegisterTemplateCmd.java index ef8411ad57c..dc4a2be7045 100755 --- a/api/src/com/cloud/api/commands/RegisterTemplateCmd.java +++ b/api/src/com/cloud/api/commands/RegisterTemplateCmd.java @@ -213,7 +213,7 @@ public class RegisterTemplateCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java b/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java index b656ed14112..d6370fc3115 100644 --- a/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java +++ b/api/src/com/cloud/api/commands/RemoveVpnUserCmd.java @@ -88,7 +88,7 @@ public class RemoveVpnUserCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java b/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java index f47611cfa84..05a52b5b9db 100644 --- a/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java +++ b/api/src/com/cloud/api/commands/UpdateResourceCountCmd.java @@ -112,7 +112,7 @@ public class UpdateResourceCountCmd extends BaseCmd { @Override public void execute(){ - List result = _resourceLimitService.recalculateResourceCount(getAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType()); + List result = _resourceLimitService.recalculateResourceCount(finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType()); if ((result != null) && (result.size()>0)){ ListResponse response = new ListResponse(); diff --git a/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java b/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java index 35091f39df4..984cd31b746 100644 --- a/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java +++ b/api/src/com/cloud/api/commands/UpdateResourceLimitCmd.java @@ -89,7 +89,7 @@ public class UpdateResourceLimitCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = getAccountId(accountName, domainId, projectId, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } @@ -99,7 +99,7 @@ public class UpdateResourceLimitCmd extends BaseCmd { @Override public void execute(){ - ResourceLimit result = _resourceLimitService.updateResourceLimit(getAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max); + ResourceLimit result = _resourceLimitService.updateResourceLimit(finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max); if (result != null || (result == null && max != null && max.longValue() == -1L)){ ResourceLimitResponse response = _responseGenerator.createResourceLimitResponse(result); response.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/storage/snapshot/SnapshotService.java b/api/src/com/cloud/storage/snapshot/SnapshotService.java index 371396c5498..1d8da9b8ca0 100644 --- a/api/src/com/cloud/storage/snapshot/SnapshotService.java +++ b/api/src/com/cloud/storage/snapshot/SnapshotService.java @@ -27,6 +27,7 @@ import com.cloud.api.commands.ListSnapshotsCmd; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.storage.Snapshot; +import com.cloud.user.Account; public interface SnapshotService { @@ -82,10 +83,11 @@ public interface SnapshotService { /** * Create a snapshot of a volume - * + * @param snapshotOwner TODO * @param cmd * the API command wrapping the parameters for creating the snapshot (mainly volumeId) + * * @return the Snapshot that was created */ - Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId); + Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId, Account snapshotOwner); } diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java index 1cf2d3a012e..f8f2c7aafe7 100755 --- a/api/src/com/cloud/vm/UserVmService.java +++ b/api/src/com/cloud/vm/UserVmService.java @@ -123,10 +123,11 @@ public interface UserVmService { * @param cmd * the command object that defines the name, display text, snapshot/volume, bits, public/private, etc. for the * private template + * @param templateOwner TODO * @return the vm template object if successful, null otherwise * @throws ResourceAllocationException */ - VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException; + VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException; /** * Creates a private template from a snapshot of a VM diff --git a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java index 6da3422afdf..fa2987a319d 100755 --- a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java +++ b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java @@ -140,7 +140,7 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet } @Override - public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException { + public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException { /*Baremetal creates record after host rebooting for imaging, in createPrivateTemplate*/ return null; } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 86f45595309..226feb7c672 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -117,7 +117,6 @@ import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.fsm.NoTransitionException; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine.State; @@ -369,14 +368,12 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma @Override @DB @ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_CREATE, eventDescription = "creating snapshot", async = true) - public SnapshotVO createSnapshot(Long volumeId, Long policyId, Long snapshotId) { - VolumeVO volume = _volsDao.findById(volumeId); - + public SnapshotVO createSnapshot(Long volumeId, Long policyId, Long snapshotId, Account snapshotOwner) { + VolumeVO volume = _volsDao.findById(volumeId); if (volume == null) { throw new InvalidParameterValueException("No such volume exist"); } - Account owner = _accountMgr.getAccount(volume.getAccountId()); SnapshotVO snapshot = null; boolean backedUp = false; @@ -481,7 +478,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma snapshot.setStatus(Status.Error); _snapshotDao.update(snapshot.getId(), snapshot); } else { - _resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.snapshot); + _resourceLimitMgr.incrementResourceCount(snapshotOwner.getId(), ResourceType.snapshot); } } else { snapshot = _snapshotDao.findById(snapshotId); diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 0fc1e529f1a..4d92fa865f0 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -1287,19 +1287,13 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Override @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template", create = true) - public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException { + public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException { Long userId = UserContext.current().getCallerUserId(); Account caller = UserContext.current().getCaller(); - boolean isAdmin = ((caller == null) || isAdmin(caller.getType())); + boolean isAdmin = (isAdmin(caller.getType())); - VMTemplateVO privateTemplate = null; - - UserVO user = _userDao.findById(userId); - - if (user == null) { - throw new InvalidParameterValueException("User " + userId + " does not exist"); - } + _accountMgr.checkAccess(caller, null, templateOwner); String name = cmd.getTemplateName(); if ((name == null) || (name.length() > 32)) { @@ -1307,7 +1301,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } if(cmd.getTemplateTag() != null){ - if(!_accountService.isRootAdmin(caller.getType())){ + if (!_accountService.isRootAdmin(caller.getType())){ throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied"); } } @@ -1338,10 +1332,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId + ") and snapshot ID (" + snapshotId + ")"); } - long domainId; - long accountId; HypervisorType hyperType; VolumeVO volume = null; + VMTemplateVO privateTemplate = null; if (volumeId != null) { // create template from volume volume = _volsDao.findById(volumeId); if (volume == null) { @@ -1359,17 +1352,15 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } throw new CloudRuntimeException(msg); } - domainId = volume.getDomainId(); - accountId = volume.getAccountId(); hyperType = _volsDao.getHypervisorType(volumeId); } else { // create template from snapshot SnapshotVO snapshot = _snapshotDao.findById(snapshotId); - volume = _volsDao.findById(snapshot.getVolumeId()); - VolumeVO snapshotVolume = _volsDao.findByIdIncludingRemoved(snapshot.getVolumeId()); - if (snapshot == null) { throw new InvalidParameterValueException("Failed to create private template record, unable to find snapshot " + snapshotId); } + + volume = _volsDao.findById(snapshot.getVolumeId()); + VolumeVO snapshotVolume = _volsDao.findByIdIncludingRemoved(snapshot.getVolumeId()); //check permissions _accountMgr.checkAccess(caller, null, snapshot); @@ -1383,13 +1374,10 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager throw new UnsupportedServiceException("operation not supported, snapshot with id " + snapshotId + " is created from Data Disk"); } - domainId = snapshot.getDomainId(); - accountId = snapshot.getAccountId(); hyperType = snapshot.getHypervisorType(); } - AccountVO ownerAccount = _accountDao.findById(accountId); - _resourceLimitMgr.checkResourceLimit(ownerAccount, ResourceType.template); + _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template); if (!isAdmin || featured == null) { featured = Boolean.FALSE; @@ -1421,7 +1409,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager s_logger.debug("Adding template tag: "+templateTag); } } - privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, ImageFormat.RAW, isPublic, featured, isExtractable, TemplateType.USER, null, null, requiresHvmValue, bitsValue, accountId, + privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, ImageFormat.RAW, isPublic, featured, isExtractable, TemplateType.USER, null, null, requiresHvmValue, bitsValue, templateOwner.getId(), null, description, passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails()); if(sourceTemplateId != null){ if(s_logger.isDebugEnabled()){ @@ -1437,7 +1425,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager _templateDetailsDao.persist(template.getId(), cmd.getDetails()); } - _resourceLimitMgr.incrementResourceCount(accountId, ResourceType.template); + _resourceLimitMgr.incrementResourceCount(templateOwner.getId(), ResourceType.template); } if (template != null){ diff --git a/server/test/com/cloud/vm/MockUserVmManagerImpl.java b/server/test/com/cloud/vm/MockUserVmManagerImpl.java index 8f411249041..f38f2a0d51a 100644 --- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java +++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java @@ -260,7 +260,7 @@ public class MockUserVmManagerImpl implements UserVmManager, UserVmService, Mana } @Override - public VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd) throws ResourceAllocationException { + public VirtualMachineTemplate createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException { // TODO Auto-generated method stub return null; } From 42a460023e004df2a7e47dd390b7b82cedf9f05a Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Mon, 19 Dec 2011 16:30:46 -0800 Subject: [PATCH 42/69] Don't allow to create snapshotPolicy for disabled account and suspended/inactive project --- .../cloud/api/commands/CreateSnapshotCmd.java | 17 +++++-------- .../api/commands/CreateSnapshotPolicyCmd.java | 24 +++++++++++++++---- .../storage/snapshot/SnapshotService.java | 3 ++- .../storage/snapshot/SnapshotManagerImpl.java | 4 ++-- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/api/src/com/cloud/api/commands/CreateSnapshotCmd.java b/api/src/com/cloud/api/commands/CreateSnapshotCmd.java index 7ed9f7810e5..4186072d003 100755 --- a/api/src/com/cloud/api/commands/CreateSnapshotCmd.java +++ b/api/src/com/cloud/api/commands/CreateSnapshotCmd.java @@ -106,21 +106,16 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Long volumeId = getVolumeId(); - Long accountId = null; - - Volume volume = _entityMgr.findById(Volume.class, volumeId); - if (volume != null) { - accountId = volume.getAccountId(); - } else { + + Volume volume = _entityMgr.findById(Volume.class, getVolumeId()); + if (volume == null) { throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId); } - - Account account = _accountService.getAccount(accountId); + Account account = _accountService.getAccount(volume.getAccountId()); //Can create templates for enabled projects/accounts only if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { - Project project = _projectService.findByProjectAccountId(accountId); + Project project = _projectService.findByProjectAccountId(volume.getAccountId()); if (project.getState() != Project.State.Active) { throw new PermissionDeniedException("Can't add resources to the project id=" + project.getId() + " in state=" + project.getState() + " as it's no longer active"); } @@ -128,7 +123,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { throw new PermissionDeniedException("The owner of template is disabled: " + account); } - return accountId; + return volume.getAccountId(); } @Override diff --git a/api/src/com/cloud/api/commands/CreateSnapshotPolicyCmd.java b/api/src/com/cloud/api/commands/CreateSnapshotPolicyCmd.java index 23bfa1f0ca8..6052ab115df 100644 --- a/api/src/com/cloud/api/commands/CreateSnapshotPolicyCmd.java +++ b/api/src/com/cloud/api/commands/CreateSnapshotPolicyCmd.java @@ -27,6 +27,9 @@ import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; import com.cloud.api.response.SnapshotPolicyResponse; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.projects.Project; import com.cloud.storage.Volume; import com.cloud.storage.snapshot.SnapshotPolicy; import com.cloud.user.Account; @@ -100,16 +103,27 @@ public class CreateSnapshotPolicyCmd extends BaseCmd { @Override public long getEntityOwnerId() { Volume volume = _entityMgr.findById(Volume.class, getVolumeId()); - if (volume != null) { - return volume.getAccountId(); + if (volume == null) { + throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId); } - - return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + + Account account = _accountService.getAccount(volume.getAccountId()); + //Can create templates for enabled projects/accounts only + if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { + Project project = _projectService.findByProjectAccountId(volume.getAccountId()); + if (project.getState() != Project.State.Active) { + throw new PermissionDeniedException("Can't add resources to the project id=" + project.getId() + " in state=" + project.getState() + " as it's no longer active"); + } + } else if (account.getState() == Account.State.disabled) { + throw new PermissionDeniedException("The owner of template is disabled: " + account); + } + + return volume.getAccountId(); } @Override public void execute(){ - SnapshotPolicy result = _snapshotService.createPolicy(this); + SnapshotPolicy result = _snapshotService.createPolicy(this, _accountService.getAccount(getEntityOwnerId())); if (result != null) { SnapshotPolicyResponse response = _responseGenerator.createSnapshotPolicyResponse(result); response.setResponseName(getCommandName()); diff --git a/api/src/com/cloud/storage/snapshot/SnapshotService.java b/api/src/com/cloud/storage/snapshot/SnapshotService.java index 1d8da9b8ca0..dbe84151034 100644 --- a/api/src/com/cloud/storage/snapshot/SnapshotService.java +++ b/api/src/com/cloud/storage/snapshot/SnapshotService.java @@ -54,9 +54,10 @@ public interface SnapshotService { * * @param cmd * the command that + * @param policyOwner TODO * @return the newly created snapshot policy if success, null otherwise */ - SnapshotPolicy createPolicy(CreateSnapshotPolicyCmd cmd); + SnapshotPolicy createPolicy(CreateSnapshotPolicyCmd cmd, Account policyOwner); /** * Get the recurring snapshots scheduled for this volume currently along with the time at which they are scheduled diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 226feb7c672..4fe9b0a4526 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -1126,7 +1126,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma @Override @DB - public SnapshotPolicyVO createPolicy(CreateSnapshotPolicyCmd cmd) { + public SnapshotPolicyVO createPolicy(CreateSnapshotPolicyCmd cmd, Account policyOwner) { Long volumeId = cmd.getVolumeId(); VolumeVO volume = _volsDao.findById(cmd.getVolumeId()); if (volume == null) { @@ -1139,7 +1139,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot."); } - if ( volume.getTemplateId() != null ) { + if (volume.getTemplateId() != null ) { VMTemplateVO template = _templateDao.findById(volume.getTemplateId()); if( template != null && template.getTemplateType() == Storage.TemplateType.SYSTEM ) { throw new InvalidParameterValueException("VolumeId: " + volumeId + " is for System VM , Creating snapshot against System VM volumes is not supported"); From 568db1fdb720fbc426ec0027fabe5eab9bd84d12 Mon Sep 17 00:00:00 2001 From: Jessica Wang Date: Mon, 19 Dec 2011 16:37:42 -0800 Subject: [PATCH 43/69] bug 12504: cloudstack 3.0 new UI - system - zone chart - guest - network tabs - network detail - add Restart Network action. --- ui/scripts/system.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/ui/scripts/system.js b/ui/scripts/system.js index cd6ec2bd47b..bda755eb38d 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -1010,6 +1010,47 @@ poll: pollAsyncJobResult } }, + + 'restart': { + label: 'Restart network', + action: function(args) { + $.ajax({ + url: createURL("restartNetwork&id=" + args.context.networks[0].id), + dataType: "json", + async: true, + success: function(json) { + var jid = json.restartnetworkresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.network; + } + } + } + ); + } + }); + }, + messages: { + confirm: function(args) { + return 'Please confirm that you want to restart network'; + }, + success: function(args) { + return 'Network is being restarted'; + }, + notification: function(args) { + return 'Restarting network'; + }, + complete: function(args) { + return 'Network has been restarted'; + } + }, + notification: { + poll: pollAsyncJobResult + } + }, + 'delete': { label: 'Delete network', messages: { From 8e075b38c3c2cdc7f71fd73890cb418469f373a2 Mon Sep 17 00:00:00 2001 From: bfederle Date: Mon, 19 Dec 2011 19:42:15 -0500 Subject: [PATCH 44/69] bug 12273: Add project resource management status 12273: resolved fixed --- ui/scripts/projects.js | 70 ++++++++++++++++++++++++++++++++ ui/scripts/ui-custom/projects.js | 63 ++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+) diff --git a/ui/scripts/projects.js b/ui/scripts/projects.js index 30e204168f5..7fcd805c283 100644 --- a/ui/scripts/projects.js +++ b/ui/scripts/projects.js @@ -4,6 +4,76 @@ return window.g_projectsInviteRequired; }, + resourceManagement: { + update: function(args) { + var totalResources = 5; + var updatedResources = 0; + $.each(args.data, function(key, value) { + $.ajax({ + url: createURL('updateResourceLimit'), + data: { + resourcetype: key, + max: args.data[key] + }, + success: function(json) { + updatedResources++; + if (updatedResources == totalResources) { + args.response.success(); + } + } + }); + }); + }, + + dataProvider: function(args) { + $.ajax({ + url: createURL('listResourceLimits'), + success: function(json) { + args.response.success({ + data: $.map( + json.listresourcelimitsresponse.resourcelimit, + function(resource) { + var resourceMap = { + 0: { + id: 'user_vm', + label: 'Max. User VMs' + }, + 1: { + id: 'public_ip', + label: 'Max. Public IPs' + }, + 2: { + id: 'volume', + label: 'Max. Volumes' + }, + 3: { + id: 'snapshot', + label: 'Max. Snapshots' + }, + 4: { + id: 'template', + label: 'Max. Templates' + }, + 5: { + id: 'project', + label: 'Max. Projects' + } + }; + return { + id: resourceMap[resource.resourcetype].id, + label: resourceMap[resource.resourcetype].label, + type: resource.resourcetype, + value: resource.max + }; + } + ) + }); + } + }); + + } + }, + dashboard: function(args) { var dataFns = { instances: function(data) { diff --git a/ui/scripts/ui-custom/projects.js b/ui/scripts/ui-custom/projects.js index 73b9e2162ff..72afa1685f6 100644 --- a/ui/scripts/ui-custom/projects.js +++ b/ui/scripts/ui-custom/projects.js @@ -96,6 +96,69 @@ return $('
      ').addClass('management-invite').data('tab-title', 'Invitations'); }; } + + tabs.resources = function() { + var $resources = $('
      ').addClass('resources').data('tab-title', 'Resources'); + var $form = $('
      '); + var $submit = $('').attr({ + type: 'submit' + }).val('Apply'); + + cloudStack.projects.resourceManagement.dataProvider({ + response: { + success: function(args) { + $(args.data).each(function() { + var resource = this; + var $field = $('
      ').addClass('field'); + var $label = $('