]>
git.proxmox.com Git - ceph.git/blob - ceph/qa/tasks/mgr/dashboard/test_cephfs.py
1 # -*- coding: utf-8 -*-
2 from __future__
import absolute_import
5 from contextlib
import contextmanager
7 from .helper
import DashboardTestCase
, JObj
, JList
, JLeaf
10 class CephfsTest(DashboardTestCase
):
13 AUTH_ROLES
= ['cephfs-manager']
15 QUOTA_PATH
= '/quotas'
17 def assertToHave(self
, data
, key
):
18 self
.assertIn(key
, data
)
19 self
.assertIsNotNone(data
[key
])
22 return self
.fs
.get_namespace_id()
24 def mk_dirs(self
, path
, expectedStatus
=200):
25 self
._post
("/api/cephfs/{}/mk_dirs".format(self
.get_fs_id()),
26 params
={'path': path
})
27 self
.assertStatus(expectedStatus
)
29 def rm_dir(self
, path
, expectedStatus
=200):
30 self
._post
("/api/cephfs/{}/rm_dir".format(self
.get_fs_id()),
31 params
={'path': path
})
32 self
.assertStatus(expectedStatus
)
34 def get_root_directory(self
, expectedStatus
=200):
35 data
= self
._get
("/api/cephfs/{}/get_root_directory".format(self
.get_fs_id()))
36 self
.assertStatus(expectedStatus
)
37 self
.assertIsInstance(data
, dict)
40 def ls_dir(self
, path
, expectedLength
, depth
= None):
41 return self
._ls
_dir
(path
, expectedLength
, depth
, "api")
43 def ui_ls_dir(self
, path
, expectedLength
, depth
= None):
44 return self
._ls
_dir
(path
, expectedLength
, depth
, "ui-api")
46 def _ls_dir(self
, path
, expectedLength
, depth
, baseApiPath
):
47 params
= {'path': path
}
49 params
['depth'] = depth
50 data
= self
._get
("/{}/cephfs/{}/ls_dir".format(baseApiPath
, self
.get_fs_id()),
52 self
.assertStatus(200)
53 self
.assertIsInstance(data
, list)
54 self
.assertEqual(len(data
), expectedLength
)
57 def setQuotas(self
, bytes
=None, files
=None):
62 self
._post
("/api/cephfs/{}/set_quotas".format(self
.get_fs_id()), data
=quotas
,
63 params
={'path': self
.QUOTA_PATH
})
64 self
.assertStatus(200)
66 def assertQuotas(self
, bytes
, files
):
67 data
= self
.ls_dir('/', 1)[0]
68 self
.assertEqual(data
['quotas']['max_bytes'], bytes
)
69 self
.assertEqual(data
['quotas']['max_files'], files
)
72 def new_quota_dir(self
):
73 self
.mk_dirs(self
.QUOTA_PATH
)
74 self
.setQuotas(1024**3, 1024)
76 self
.rm_dir(self
.QUOTA_PATH
)
78 @DashboardTestCase.RunAs('test', 'test', ['block-manager'])
79 def test_access_permissions(self
):
80 fs_id
= self
.get_fs_id()
81 self
._get
("/api/cephfs/{}/clients".format(fs_id
))
82 self
.assertStatus(403)
83 self
._get
("/api/cephfs/{}".format(fs_id
))
84 self
.assertStatus(403)
85 self
._get
("/api/cephfs/{}/mds_counters".format(fs_id
))
86 self
.assertStatus(403)
87 self
._get
("/ui-api/cephfs/{}/tabs".format(fs_id
))
88 self
.assertStatus(403)
90 def test_cephfs_clients(self
):
91 fs_id
= self
.get_fs_id()
92 data
= self
._get
("/api/cephfs/{}/clients".format(fs_id
))
93 self
.assertStatus(200)
95 self
.assertIn('status', data
)
96 self
.assertIn('data', data
)
98 def test_cephfs_evict_client_does_not_exist(self
):
99 fs_id
= self
.get_fs_id()
100 self
._delete
("/api/cephfs/{}/client/1234".format(fs_id
))
101 self
.assertStatus(404)
103 def test_cephfs_get(self
):
104 fs_id
= self
.get_fs_id()
105 data
= self
._get
("/api/cephfs/{}/".format(fs_id
))
106 self
.assertStatus(200)
108 self
.assertToHave(data
, 'cephfs')
109 self
.assertToHave(data
, 'standbys')
110 self
.assertToHave(data
, 'versions')
112 def test_cephfs_mds_counters(self
):
113 fs_id
= self
.get_fs_id()
114 data
= self
._get
("/api/cephfs/{}/mds_counters".format(fs_id
))
115 self
.assertStatus(200)
117 self
.assertIsInstance(data
, dict)
118 self
.assertIsNotNone(data
)
120 def test_cephfs_mds_counters_wrong(self
):
121 self
._get
("/api/cephfs/baadbaad/mds_counters")
122 self
.assertStatus(400)
123 self
.assertJsonBody({
124 "component": 'cephfs',
125 "code": "invalid_cephfs_id",
126 "detail": "Invalid cephfs ID baadbaad"
129 def test_cephfs_list(self
):
130 data
= self
._get
("/api/cephfs/")
131 self
.assertStatus(200)
133 self
.assertIsInstance(data
, list)
135 self
.assertToHave(cephfs
, 'id')
136 self
.assertToHave(cephfs
, 'mdsmap')
138 def test_cephfs_tabs(self
):
139 fs_id
= self
.get_fs_id()
140 data
= self
._get
("/ui-api/cephfs/{}/tabs".format(fs_id
))
141 self
.assertStatus(200)
142 self
.assertIsInstance(data
, dict)
145 pools
= data
['pools']
146 self
.assertIsInstance(pools
, list)
147 self
.assertGreater(len(pools
), 0)
149 self
.assertEqual(pool
['size'], pool
['used'] + pool
['avail'])
152 self
.assertToHave(data
, 'ranks')
153 self
.assertIsInstance(data
['ranks'], list)
156 self
.assertToHave(data
, 'name')
157 self
.assertIsInstance(data
['name'], six
.string_types
)
160 self
.assertToHave(data
, 'standbys')
161 self
.assertIsInstance(data
['standbys'], six
.string_types
)
164 counters
= data
['mds_counters']
165 self
.assertIsInstance(counters
, dict)
166 self
.assertGreater(len(counters
.keys()), 0)
167 for k
, v
in counters
.items():
168 self
.assertEqual(v
['name'], k
)
171 self
.assertToHave(data
, 'clients')
172 clients
= data
['clients']
173 self
.assertToHave(clients
, 'data')
174 self
.assertIsInstance(clients
['data'], list)
175 self
.assertToHave(clients
, 'status')
176 self
.assertIsInstance(clients
['status'], int)
178 def test_ls_mk_rm_dir(self
):
181 self
.mk_dirs('/pictures/birds')
182 self
.ls_dir('/', 2, 3)
183 self
.ls_dir('/pictures', 1)
185 self
.rm_dir('/pictures', 500)
186 self
.rm_dir('/pictures/birds')
187 self
.rm_dir('/pictures')
191 def test_snapshots(self
):
192 fs_id
= self
.get_fs_id()
193 self
.mk_dirs('/movies/dune/extended_version')
195 self
._post
("/api/cephfs/{}/mk_snapshot".format(fs_id
),
196 params
={'path': '/movies/dune', 'name': 'test'})
197 self
.assertStatus(200)
199 data
= self
.ls_dir('/movies', 1)
200 self
.assertSchema(data
[0], JObj(sub_elems
={
203 'parent': JLeaf(str),
204 'snapshots': JList(JObj(sub_elems
={
207 'created': JLeaf(str)
209 'quotas': JObj(sub_elems
={
210 'max_bytes': JLeaf(int),
211 'max_files': JLeaf(int)
214 snapshots
= data
[0]['snapshots']
215 self
.assertEqual(len(snapshots
), 1)
216 snapshot
= snapshots
[0]
217 self
.assertEqual(snapshot
['name'], "test")
218 self
.assertEqual(snapshot
['path'], "/movies/dune/.snap/test")
220 # Should have filtered out "_test_$timestamp"
221 data
= self
.ls_dir('/movies/dune', 1)
222 snapshots
= data
[0]['snapshots']
223 self
.assertEqual(len(snapshots
), 0)
225 self
._post
("/api/cephfs/{}/rm_snapshot".format(fs_id
),
226 params
={'path': '/movies/dune', 'name': 'test'})
227 self
.assertStatus(200)
229 data
= self
.ls_dir('/movies', 1)
230 self
.assertEqual(len(data
[0]['snapshots']), 0)
232 # Cleanup. Note, the CephFS Python extension (and therefor the Dashboard
233 # REST API) does not support recursive deletion of a directory.
234 self
.rm_dir('/movies/dune/extended_version')
235 self
.rm_dir('/movies/dune')
236 self
.rm_dir('/movies')
238 def test_quotas_default(self
):
239 self
.mk_dirs(self
.QUOTA_PATH
)
240 self
.assertQuotas(0, 0)
241 self
.rm_dir(self
.QUOTA_PATH
)
243 def test_quotas_set_both(self
):
244 with self
.new_quota_dir():
245 self
.assertQuotas(1024**3, 1024)
247 def test_quotas_set_only_bytes(self
):
248 with self
.new_quota_dir():
249 self
.setQuotas(2048**3)
250 self
.assertQuotas(2048**3, 1024)
252 def test_quotas_set_only_files(self
):
253 with self
.new_quota_dir():
254 self
.setQuotas(None, 2048)
255 self
.assertQuotas(1024**3, 2048)
257 def test_quotas_unset_both(self
):
258 with self
.new_quota_dir():
260 self
.assertQuotas(0, 0)
262 def test_listing_of_root_dir(self
):
263 self
.ls_dir('/', 0) # Should not list root
264 ui_root
= self
.ui_ls_dir('/', 1)[0] # Should list root by default
265 root
= self
.get_root_directory()
266 self
.assertEqual(ui_root
, root
)
268 def test_listing_of_ui_api_ls_on_deeper_levels(self
):
269 # The UI-API and API ls_dir methods should behave the same way on deeper levels
270 self
.mk_dirs('/pictures')
271 api_ls
= self
.ls_dir('/pictures', 0)
272 ui_api_ls
= self
.ui_ls_dir('/pictures', 0)
273 self
.assertEqual(api_ls
, ui_api_ls
)
274 self
.rm_dir('/pictures')