Merge ~andreserl/maas:request_stats into maas:master

Proposed by Andres Rodriguez
Status: Merged
Approved by: Andres Rodriguez
Approved revision: 0f27ae52f8e046f609b4a4aff07380e9b929ee02
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~andreserl/maas:request_stats
Merge into: maas:master
Diff against target: 178 lines (+137/-0)
4 files modified
src/maasserver/bootresources.py (+3/-0)
src/maasserver/tests/test_bootresources.py (+24/-0)
src/maasserver/utils/stats.py (+52/-0)
src/maasserver/utils/tests/test_stats.py (+58/-0)
Reviewer Review Type Date Requested Status
Blake Rouse (community) Approve
Review via email: mp+331583@code.launchpad.net

Commit message

Send MAAS stats if it analytics are enabled.

To post a comment you must log in.
Revision history for this message
Blake Rouse (blake-rouse) :
Revision history for this message
Blake Rouse (blake-rouse) wrote :

Some code suggestions and it needs tests.

review: Needs Fixing
~andreserl/maas:request_stats updated
3d09d76... by Andres Rodriguez

Address code review requests

adad2ab... by Andres Rodriguez

remove comment

b275f31... by Andres Rodriguez

updates

b548410... by Andres Rodriguez

Add tests

8bfda83... by Andres Rodriguez

Add tests

828d917... by Andres Rodriguez

Update tests

a0a8ce3... by Andres Rodriguez

Test

1685a3a... by Andres Rodriguez

Tests

0f27ae5... by Andres Rodriguez

Update tests

Revision history for this message
Blake Rouse (blake-rouse) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/bootresources.py b/src/maasserver/bootresources.py
2index 41f5743..f5833d1 100644
3--- a/src/maasserver/bootresources.py
4+++ b/src/maasserver/bootresources.py
5@@ -77,6 +77,7 @@ from maasserver.utils.orm import (
6 transactional,
7 with_connection,
8 )
9+from maasserver.utils.stats import make_maas_user_agent_request
10 from maasserver.utils.threads import deferToDatabase
11 from provisioningserver.config import is_dev_environment
12 from provisioningserver.events import EVENT_TYPES
13@@ -1429,6 +1430,8 @@ class ImportResourcesService(TimerService, object):
14
15 def maybe_import_resources(self):
16 def determine_auto():
17+ if Config.objects.get_config('enable_analytics'):
18+ make_maas_user_agent_request()
19 auto = Config.objects.get_config('boot_images_auto_import')
20 if not auto:
21 return auto
22diff --git a/src/maasserver/tests/test_bootresources.py b/src/maasserver/tests/test_bootresources.py
23index 4763178..4790000 100644
24--- a/src/maasserver/tests/test_bootresources.py
25+++ b/src/maasserver/tests/test_bootresources.py
26@@ -1945,6 +1945,30 @@ class TestImportResourcesServiceAsync(MAASTransactionServerTestCase):
27 bootresources._import_resources_in_thread,
28 MockNotCalled())
29
30+ def test_maybe_import_resources_makes_maas_user_agent_request(self):
31+ mock_call = self.patch(bootresources, "make_maas_user_agent_request")
32+
33+ with transaction.atomic():
34+ Config.objects.set_config('enable_analytics', True)
35+
36+ service = bootresources.ImportResourcesService()
37+ maybe_import_resources = asynchronous(service.maybe_import_resources)
38+ maybe_import_resources().wait(5)
39+
40+ self.assertThat(mock_call, MockCalledOnce())
41+
42+ def test_maybe_import_resources_doesnt_make_maas_user_agent_request(self):
43+ mock_call = self.patch(bootresources, "make_maas_user_agent_request")
44+
45+ with transaction.atomic():
46+ Config.objects.set_config('enable_analytics', False)
47+
48+ service = bootresources.ImportResourcesService()
49+ maybe_import_resources = asynchronous(service.maybe_import_resources)
50+ maybe_import_resources().wait(5)
51+
52+ self.assertThat(mock_call, MockNotCalled())
53+
54
55 class TestImportResourcesProgressService(MAASServerTestCase):
56 """Tests for `ImportResourcesProgressService`."""
57diff --git a/src/maasserver/utils/stats.py b/src/maasserver/utils/stats.py
58new file mode 100644
59index 0000000..ef1fb3b
60--- /dev/null
61+++ b/src/maasserver/utils/stats.py
62@@ -0,0 +1,52 @@
63+# Copyright 2017 Canonical Ltd. This software is licensed under the
64+# GNU Affero General Public License version 3 (see the file LICENSE).
65+
66+"""Stats related utility functions."""
67+
68+import base64
69+from collections import Counter
70+import json
71+
72+from maasserver.enum import NODE_TYPE
73+from maasserver.models import Node
74+from maasserver.utils import get_maas_user_agent
75+import requests
76+
77+
78+def get_maas_stats():
79+ node_types = Node.objects.values_list('node_type', flat=True)
80+ node_types = Counter(node_types)
81+
82+ return json.dumps({
83+ "controllers": {
84+ "regionracks": node_types.get(
85+ NODE_TYPE.REGION_AND_RACK_CONTROLLER, 0),
86+ "regions": node_types.get(NODE_TYPE.REGION_CONTROLLER, 0),
87+ "racks": node_types.get(NODE_TYPE.RACK_CONTROLLER, 0),
88+ },
89+ "nodes": {
90+ "machines": node_types.get(NODE_TYPE.MACHINE, 0),
91+ "devices": node_types.get(NODE_TYPE.DEVICE, 0),
92+ }
93+ })
94+
95+
96+def get_request_params():
97+ return {
98+ "data": base64.b64encode(
99+ json.dumps(get_maas_stats()).encode()).decode(),
100+ }
101+
102+
103+def make_maas_user_agent_request():
104+ headers = {
105+ 'User-Agent': get_maas_user_agent(),
106+ }
107+ params = get_request_params()
108+ try:
109+ requests.get(
110+ 'https://stats.images.maas.io/',
111+ params=params, headers=headers)
112+ except:
113+ # Do not fail if for any reason requests does.
114+ pass
115diff --git a/src/maasserver/utils/tests/test_stats.py b/src/maasserver/utils/tests/test_stats.py
116new file mode 100644
117index 0000000..3eb82cb
118--- /dev/null
119+++ b/src/maasserver/utils/tests/test_stats.py
120@@ -0,0 +1,58 @@
121+# Copyright 2017 Canonical Ltd. This software is licensed under the
122+# GNU Affero General Public License version 3 (see the file LICENSE).
123+
124+"""Test stats utilities."""
125+
126+__all__ = []
127+
128+import base64
129+import json
130+
131+from maasserver.testing.factory import factory
132+from maasserver.testing.testcase import MAASServerTestCase
133+from maasserver.utils.stats import (
134+ get_maas_stats,
135+ get_request_params,
136+ make_maas_user_agent_request,
137+)
138+from maastesting.matchers import MockCalledOnce
139+import requests as requests_module
140+
141+
142+class TestMAASStats(MAASServerTestCase):
143+
144+ def test_get_maas_stats(self):
145+ # Make one component of everything
146+ factory.make_RegionRackController()
147+ factory.make_RegionController()
148+ factory.make_RackController()
149+ factory.make_Machine()
150+ factory.make_Device()
151+
152+ stats = get_maas_stats()
153+ compare = {
154+ "controllers": {
155+ "regionracks": 1,
156+ "regions": 1,
157+ "racks": 1,
158+ },
159+ "nodes": {
160+ "machines": 1,
161+ "devices": 1,
162+ },
163+ }
164+ self.assertEquals(stats, json.dumps(compare))
165+
166+ def test_get_request_params_returns_params(self):
167+ factory.make_RegionRackController()
168+ params = {
169+ "data": base64.b64encode(
170+ json.dumps(get_maas_stats()).encode()).decode()
171+ }
172+ self.assertEquals(params, get_request_params())
173+
174+ def test_make_user_agent_request(self):
175+ factory.make_RegionRackController()
176+ mock = self.patch(requests_module, "get")
177+ make_maas_user_agent_request()
178+ self.assertThat(mock, MockCalledOnce())

Subscribers

People subscribed via source and target branches