Skip to content

Commit f6e600e

Browse files
bwswyadvr
authored andcommitted
CLOUDSTACK-3009: Fix resource calculation CPU, RAM for accounts. (#3012)
The view "service_offering_view" doesn't include removed SOs, as a result when SO is removed, the bug happens. The PR introduces a change for resource calculation changing "service_offering_view" to "service_offering" table which has all service offerings. Must be fixed in: 4.12 4.11 Fixes: #3009
1 parent f95aec4 commit f6e600e

File tree

6 files changed

+273
-6
lines changed

6 files changed

+273
-6
lines changed

.dockerignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
cloudstack/tools/docker/Dockerfile
19+
.dockerignore
20+
.idea
21+
.git
22+
venv

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,4 @@ plugins/hypervisors/kvm/.pydevproject
9999
scripts/.pydevproject
100100
*.qcow2
101101
*.raw
102+
venv

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ env:
7878
smoke/test_pvlan
7979
smoke/test_regions
8080
smoke/test_reset_vm_on_reboot
81+
smoke/test_resource_accounting
8182
smoke/test_resource_detail
8283
smoke/test_router_dhcphosts
8384
smoke/test_router_dns

engine/schema/src/com/cloud/configuration/dao/ResourceCountDaoImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public long removeEntriesByOwner(long ownerId, ResourceOwnerType ownerType) {
258258
+ " ELSE CONVERT(vmd.value, UNSIGNED INTEGER) "
259259
+ " END)) as total "
260260
+ " from vm_instance vm "
261-
+ " join service_offering_view so on so.id = vm.service_offering_id "
261+
+ " join service_offering so on so.id = vm.service_offering_id "
262262
+ " left join user_vm_details vmd on vmd.vm_id = vm.id and vmd.name = '%s' "
263263
+ " where vm.type = 'User' and state not in ('Destroyed', 'Error', 'Expunging') and display_vm = true and account_id = ? ";
264264

test/integration/component/test_browse_templates.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def gettemplatelimts(self):
230230

231231
return(totaltemplates)
232232

233-
def getstoragelimts(self,rtype):
233+
def getstoragelimits(self, rtype):
234234

235235
cmd=updateResourceCount.updateResourceCountCmd()
236236
cmd.account=self.account.name
@@ -1652,7 +1652,7 @@ def test_07_Browser_Upload_template_secondary_storage_resource_limits(self):
16521652

16531653
self.debug("========================= Test 22 Upload template and verify secondary storage limits========================")
16541654

1655-
initialsecondarystoragelimit=self.getstoragelimts(11)
1655+
initialsecondarystoragelimit=self.getstoragelimits(11)
16561656
browseup_template1=self.browse_upload_template()
16571657

16581658
tmpldetails=Template.list(
@@ -1662,7 +1662,7 @@ def test_07_Browser_Upload_template_secondary_storage_resource_limits(self):
16621662
zoneid=self.zone.id)
16631663

16641664

1665-
afteruploadsecondarystoragelimit=self.getstoragelimts(11)
1665+
afteruploadsecondarystoragelimit=self.getstoragelimits(11)
16661666

16671667
if afteruploadsecondarystoragelimit!=(initialsecondarystoragelimit+tmpldetails[0].size):
16681668
self.fail("Secondary Storage Resouce Count is not updated")
@@ -1709,10 +1709,10 @@ def test_09_Browser_Upload_Volume_secondary_storage_resource_limits_after_deleti
17091709
templatefilter="all",
17101710
zoneid=self.zone.id)
17111711

1712-
initialuploadprimarystoragelimit=self.getstoragelimts(11)
1712+
initialuploadprimarystoragelimit=self.getstoragelimits(11)
17131713
self.delete_template(browseup_template1)
17141714

1715-
afteruploadprimarystoragelimit=self.getstoragelimts(11)
1715+
afteruploadprimarystoragelimit=self.getstoragelimits(11)
17161716

17171717
if afteruploadprimarystoragelimit!=(initialuploadprimarystoragelimit-tmpldetails[0].size):
17181718
self.fail("Secondary Storage Resource Count is not updated after deletion")
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
from nose.plugins.attrib import attr
19+
20+
# Import Local Modules
21+
from marvin.cloudstackTestCase import cloudstackTestCase
22+
from marvin.lib.base import (Domain,
23+
Account,
24+
ServiceOffering,
25+
VirtualMachine, updateResourceCount)
26+
from marvin.lib.common import (get_zone,
27+
get_test_template)
28+
from marvin.lib.utils import (cleanup_resources)
29+
30+
31+
class Services:
32+
"""Test Account Services
33+
"""
34+
35+
def __init__(self):
36+
self.services = {
37+
"domain": {
38+
"name": "Domain",
39+
},
40+
"account": {
41+
"email": "[email protected]",
42+
"firstname": "Test",
43+
"lastname": "User",
44+
"username": "test",
45+
# Random characters are appended for unique
46+
# username
47+
"password": "fr3sca",
48+
},
49+
"user": {
50+
"email": "[email protected]",
51+
"firstname": "User",
52+
"lastname": "User",
53+
"username": "User",
54+
# Random characters are appended for unique
55+
# username
56+
"password": "fr3sca",
57+
},
58+
"service_offering_it_1": {
59+
"name": "InstanceType-1",
60+
"displaytext": "Tiny Instance",
61+
"cpunumber": 1,
62+
"cpuspeed": 100,
63+
"memory": 128,
64+
},
65+
"service_offering_it_2": {
66+
"name": "InstanceType-2",
67+
"displaytext": "Tiny Instance",
68+
"cpunumber": 2,
69+
"cpuspeed": 100,
70+
"memory": 512,
71+
},
72+
"virtual_machine_1": {
73+
"displayname": "Test VM1",
74+
"username": "root",
75+
"password": "password",
76+
"ssh_port": 22,
77+
"hypervisor": 'XenServer',
78+
"privateport": 22,
79+
"publicport": 22,
80+
"protocol": 'TCP',
81+
},
82+
"virtual_machine_2": {
83+
"displayname": "Test VM2",
84+
"username": "root",
85+
"password": "password",
86+
"ssh_port": 22,
87+
"hypervisor": 'XenServer',
88+
"privateport": 22,
89+
"publicport": 22,
90+
"protocol": 'TCP',
91+
},
92+
"template": {
93+
"displaytext": "Public Template",
94+
"name": "Public template",
95+
"ostype": 'CentOS 5.6 (64-bit)',
96+
"url": "",
97+
"hypervisor": '',
98+
"format": '',
99+
"isfeatured": True,
100+
"ispublic": True,
101+
"isextractable": True,
102+
"templatefilter": "self"
103+
},
104+
"natrule": {
105+
"publicport": 22,
106+
"privateport": 22,
107+
"protocol": 'TCP',
108+
},
109+
"ostype": 'CentOS 5.6 (64-bit)',
110+
"sleep": 60,
111+
"timeout": 10,
112+
}
113+
114+
115+
class TestRAMCPUResourceAccounting(cloudstackTestCase):
116+
117+
@classmethod
118+
def setUpClass(cls):
119+
cls.testClient = super(
120+
TestRAMCPUResourceAccounting,
121+
cls).getClsTestClient()
122+
cls.api_client = cls.testClient.getApiClient()
123+
124+
cls.services = Services().services
125+
cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
126+
cls.services['mode'] = cls.zone.networktype
127+
cls.hypervisor = cls.testClient.getHypervisorInfo()
128+
# Create an account, domain etc
129+
cls.domain = Domain.create(
130+
cls.api_client,
131+
cls.services["domain"],
132+
)
133+
cls.account = Account.create(
134+
cls.api_client,
135+
cls.services["account"],
136+
admin=True,
137+
domainid=cls.domain.id
138+
)
139+
140+
cls.template = get_test_template(
141+
cls.api_client,
142+
cls.zone.id,
143+
cls.hypervisor)
144+
145+
cls.services["virtual_machine_1"]["zoneid"] = cls.zone.id
146+
cls.services["virtual_machine_1"]["template"] = cls.template.id
147+
148+
cls.services["virtual_machine_2"]["zoneid"] = cls.zone.id
149+
cls.services["virtual_machine_2"]["template"] = cls.template.id
150+
151+
cls._cleanup = [
152+
cls.account,
153+
cls.domain
154+
]
155+
156+
@classmethod
157+
def tearDownClass(cls):
158+
try:
159+
# Cleanup resources used
160+
cleanup_resources(cls.api_client, cls._cleanup)
161+
except Exception as e:
162+
raise Exception("Warning: Exception during cleanup : %s" % e)
163+
164+
def setUp(self):
165+
self.apiclient = self.testClient.getApiClient()
166+
self.dbclient = self.testClient.getDbConnection()
167+
self.cleanup = []
168+
169+
def tearDown(self):
170+
try:
171+
# Clean up, terminate the created accounts
172+
cleanup_resources(self.apiclient, self.cleanup)
173+
except Exception as e:
174+
raise Exception("Warning: Exception during cleanup : %s" % e)
175+
176+
def get_resource_amount(self, resource_type):
177+
cmd = updateResourceCount.updateResourceCountCmd()
178+
cmd.account = self.account.name
179+
cmd.domainid = self.domain.id
180+
cmd.resourcetype = resource_type
181+
response = self.apiclient.updateResourceCount(cmd)
182+
amount = response[0].resourcecount
183+
return amount
184+
185+
@attr(tags=["advanced", "basic"], required_hardware="false")
186+
def test_01_so_removal_resource_update(self):
187+
188+
self.service_offering_it_1 = ServiceOffering.create(
189+
self.api_client,
190+
self.services["service_offering_it_1"],
191+
domainid=self.domain.id
192+
)
193+
194+
self.cleanup.append(self.service_offering_it_1)
195+
196+
self.service_offering_it_2 = ServiceOffering.create(
197+
self.api_client,
198+
self.services["service_offering_it_2"],
199+
domainid=self.domain.id
200+
)
201+
202+
self.cleanup.append(self.service_offering_it_2)
203+
204+
vm_1 = VirtualMachine.create(
205+
self.apiclient,
206+
self.services["virtual_machine_1"],
207+
accountid=self.account.name,
208+
domainid=self.account.domainid,
209+
serviceofferingid=self.service_offering_it_1.id
210+
)
211+
212+
self.debug("Deployed VM in account: %s, ID: %s" % (self.account.name, vm_1.id))
213+
self.cleanup.append(vm_1)
214+
215+
vm_2 = VirtualMachine.create(
216+
self.apiclient,
217+
self.services["virtual_machine_2"],
218+
accountid=self.account.name,
219+
domainid=self.account.domainid,
220+
serviceofferingid=self.service_offering_it_2.id
221+
)
222+
223+
self.debug("Deployed VM in account: %s, ID: %s" % (self.account.name, vm_2.id))
224+
self.cleanup.append(vm_2)
225+
226+
CPU_RESOURCE_ID = 8
227+
RAM_RESOURCE_ID = 9
228+
229+
cores = int(self.get_resource_amount(CPU_RESOURCE_ID))
230+
ram = int(self.get_resource_amount(RAM_RESOURCE_ID))
231+
232+
self.assertEqual(cores, self.services['service_offering_it_1']['cpunumber'] + self.services['service_offering_it_2']['cpunumber'])
233+
self.assertEqual(ram, self.services['service_offering_it_1']['memory'] + self.services['service_offering_it_2']['memory'])
234+
235+
self.service_offering_it_2.delete(self.apiclient)
236+
237+
self.cleanup = self.cleanup[0:-1]
238+
239+
cores = int(self.get_resource_amount(CPU_RESOURCE_ID))
240+
ram = int(self.get_resource_amount(RAM_RESOURCE_ID))
241+
242+
self.assertEqual(cores, self.services['service_offering_it_1']['cpunumber'] + self.services['service_offering_it_2']['cpunumber'])
243+
self.assertEqual(ram, self.services['service_offering_it_1']['memory'] + self.services['service_offering_it_2']['memory'])

0 commit comments

Comments
 (0)