summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2017-06-19 14:32:02 +0000
committerGerrit Code Review <review@openstack.org>2017-06-19 14:32:02 +0000
commit49e7658ef2b61f491f7f40e413036cca49d9bf88 (patch)
treec8ea1b4c420b44f0d47b12ff614192e344e898c1
parentc411e712f30b29febe08d2daaba1166d44671f7c (diff)
parent9de31168d305fda345f2018916740cce27a4fe6d (diff)
Merge "cephfs/driver: add nfs protocol support"
-rw-r--r--doc/source/devref/cephfs_driver.rst333
-rw-r--r--doc/source/devref/share_back_ends_feature_support_mapping.rst2
-rw-r--r--manila/share/drivers/cephfs/conf/cephfs-export-template.conf5
-rw-r--r--manila/share/drivers/cephfs/driver.py117
-rw-r--r--manila/share/drivers/ganesha/__init__.py5
-rw-r--r--manila/share/drivers/ganesha/manager.py10
-rw-r--r--manila/tests/share/drivers/cephfs/test_driver.py177
-rw-r--r--manila/tests/share/drivers/ganesha/test_manager.py4
-rw-r--r--manila/tests/share/drivers/test_ganesha.py10
-rw-r--r--releasenotes/notes/cephfs-add-nfs-protocol-support-44764094c9d784d8.yaml3
10 files changed, 566 insertions, 100 deletions
diff --git a/doc/source/devref/cephfs_driver.rst b/doc/source/devref/cephfs_driver.rst
index 22c614a..decadf7 100644
--- a/doc/source/devref/cephfs_driver.rst
+++ b/doc/source/devref/cephfs_driver.rst
@@ -14,39 +14,52 @@
14 License for the specific language governing permissions and limitations 14 License for the specific language governing permissions and limitations
15 under the License. 15 under the License.
16 16
17=============
17CephFS driver 18CephFS driver
18============= 19=============
19 20
20The CephFS driver enables manila to export shared filesystems to guests 21The CephFS driver enables manila to export shared filesystems backed by Ceph's
21using the Ceph network protocol. Guests require a Ceph client in order to 22File System (CephFS) using either the Ceph network protocol or NFS protocol.
22mount the filesystem. 23Guests require a native Ceph client or an NFS client in order to mount the
24filesystem.
25
26When guests access CephFS using the native Ceph protocol, access is
27controlled via Ceph's cephx authentication system. If a user requests
28share access for an ID, Ceph creates a corresponding Ceph auth ID and a secret
29key, if they do not already exist, and authorizes the ID to access the share.
30The client can then mount the share using the ID and the secret key. To learn
31more about configuring Ceph clients to access the shares created using this
32driver, please see the Ceph documentation (http://docs.ceph.com/docs/master/cephfs/).
33If you choose to use the kernel client rather than the FUSE client, the share
34size limits set in manila may not be obeyed.
23 35
24Access is controlled via Ceph's cephx authentication system. When a user 36And when guests access CephFS through NFS, an NFS-Ganesha server mediates
25requests share access for an ID, Ceph creates a corresponding Ceph auth ID 37access to CephFS. The driver enables access control by managing the NFS-Ganesha
26and a secret key, if they do not already exist, and authorizes the ID to access 38server's exports.
27the share. The client can then mount the share using the ID and the secret
28key.
29 39
30To learn more about configuring Ceph clients to access the shares created
31using this driver, please see the Ceph documentation(
32http://docs.ceph.com/docs/master/cephfs/). If you choose to use the kernel
33client rather than the FUSE client, the share size limits set in manila
34may not be obeyed.
35 40
36Supported Operations 41Supported Operations
37-------------------- 42~~~~~~~~~~~~~~~~~~~~
38 43
39The following operations are supported with CephFS backend: 44The following operations are supported with CephFS backend:
40 45
41- Create/delete CephFS share 46- Create/delete share
42- Allow/deny CephFS share access 47- Allow/deny CephFS native protocol access to share
43 48
44 * Only ``cephx`` access type is supported for CephFS protocol. 49 * Only ``cephx`` access type is supported for CephFS native protocol.
45 * ``read-only`` access level is supported in Newton or later versions 50 * ``read-only`` access level is supported in Newton or later versions
46 of manila. 51 of manila.
47 * ``read-write`` access level is supported in Mitaka or later versions 52 * ``read-write`` access level is supported in Mitaka or later versions
48 of manila. 53 of manila.
49 54
55 (or)
56
57 Allow/deny NFS access to share
58
59 * Only ``ip`` access type is supported for NFS protocol.
60 * ``read-only`` and ``read-write`` access levels are supported in Pike or
61 later versions of manila.
62
50- Extend/shrink share 63- Extend/shrink share
51- Create/delete snapshot 64- Create/delete snapshot
52- Create/delete consistency group (CG) 65- Create/delete consistency group (CG)
@@ -60,8 +73,18 @@ The following operations are supported with CephFS backend:
60 see 73 see
61 (http://docs.ceph.com/docs/master/cephfs/experimental-features/#snapshots). 74 (http://docs.ceph.com/docs/master/cephfs/experimental-features/#snapshots).
62 75
76
63Prerequisites 77Prerequisites
64------------- 78~~~~~~~~~~~~~
79
80.. important:: A manila share backed by CephFS is only as good as the
81 underlying filesystem. Take care when configuring your Ceph
82 cluster, and consult the latest guidance on the use of
83 CephFS in the Ceph documentation (
84 http://docs.ceph.com/docs/master/cephfs/)
85
86For CephFS native shares
87------------------------
65 88
66- Mitaka or later versions of manila. 89- Mitaka or later versions of manila.
67- Jewel or later versions of Ceph. 90- Jewel or later versions of Ceph.
@@ -74,17 +97,33 @@ Prerequisites
74- Network connectivity between your Ceph cluster's public network and the 97- Network connectivity between your Ceph cluster's public network and the
75 servers running the :term:`manila-share` service. 98 servers running the :term:`manila-share` service.
76- Network connectivity between your Ceph cluster's public network and guests. 99- Network connectivity between your Ceph cluster's public network and guests.
100 See :ref:security_cephfs_native
77 101
78.. important:: A manila share backed onto CephFS is only as good as the 102For CephFS NFS shares
79 underlying filesystem. Take care when configuring your Ceph 103---------------------
80 cluster, and consult the latest guidance on the use of
81 CephFS in the Ceph documentation (
82 http://docs.ceph.com/docs/master/cephfs/)
83 104
84Authorize the driver to communicate with Ceph 105- Pike or later versions of manila.
85--------------------------------------------- 106- Kraken or later versions of Ceph.
107- 2.5 or later versions of NFS-Ganesha.
108- A Ceph cluster with a filesystem configured (
109 http://docs.ceph.com/docs/master/cephfs/createfs/)
110- ``ceph-common`` package installed in the servers running the
111 :term:`manila-share` service.
112- NFS client installed in the guest.
113- Network connectivity between your Ceph cluster's public network and the
114 servers running the :term:`manila-share` service.
115- Network connectivity between your Ceph cluster's public network and
116 NFS-Ganesha server.
117- Network connectivity between your NFS-Ganesha server and the manila
118 guest.
86 119
87Run the following commands to create a Ceph identity for manila to use: 120.. _authorize_ceph_driver:
121
122Authorizing the driver to communicate with Ceph
123~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124
125Run the following commands to create a Ceph identity for a driver instance
126to use:
88 127
89.. code-block:: console 128.. code-block:: console
90 129
@@ -105,23 +144,17 @@ Run the following commands to create a Ceph identity for manila to use:
105``manila.keyring``, along with your ``ceph.conf`` file, will then need to be 144``manila.keyring``, along with your ``ceph.conf`` file, will then need to be
106placed on the server running the :term:`manila-share` service. 145placed on the server running the :term:`manila-share` service.
107 146
108Enable snapshots in Ceph if you want to use them in manila: 147.. important::
109 148
110.. code-block:: console 149 To communicate with the Ceph backend, a CephFS driver instance
111 150 (represented as a backend driver section in manila.conf) requires its own
112 ceph mds set allow_new_snaps true --yes-i-really-mean-it 151 Ceph auth ID that is not used by other CephFS driver instances running in
113 152 the same controller node.
114.. warning::
115 Note that the snapshot support for the CephFS Native driver is experimental
116 and is known to have several caveats for use. Only enable this and the
117 equivalent ``manila.conf`` option if you understand these risks. See
118 (http://docs.ceph.com/docs/master/cephfs/experimental-features/#snapshots)
119 for more details.
120 153
121In the server running the :term:`manila-share` service, you can place the 154In the server running the :term:`manila-share` service, you can place the
122``ceph.conf`` and ``manila.keyring`` files in the /etc/ceph directory. Set the 155``ceph.conf`` and ``manila.keyring`` files in the /etc/ceph directory. Set the
123same owner for the :term:`manila-share` process and the ``manila.keyring`` 156same owner for the :term:`manila-share` process and the ``manila.keyring``
124file. Add the following section to the ``ceph.conf`` file. 157file. Add the following section to the ``ceph.conf`` file.
125 158
126.. code-block:: ini 159.. code-block:: ini
127 160
@@ -137,10 +170,30 @@ locations so that they are co-located with manila services's pid files and
137log files respectively. 170log files respectively.
138 171
139 172
140Configure CephFS backend in manila.conf 173Enabling snapshot support in Ceph backend
141--------------------------------------- 174~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
175
176Enable snapshots in Ceph if you want to use them in manila:
142 177
143Add CephFS to ``enabled_share_protocols`` (enforced at manila api layer). In 178.. code-block:: console
179
180 ceph mds set allow_new_snaps true --yes-i-really-mean-it
181
182.. warning::
183 Note that the snapshot support for the CephFS driver is experimental and is
184 known to have several caveats for use. Only enable this and the
185 equivalent ``manila.conf`` option if you understand these risks. See
186 (http://docs.ceph.com/docs/master/cephfs/experimental-features/#snapshots)
187 for more details.
188
189
190Configuring CephFS backend in manila.conf
191~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192
193Configure CephFS native share backend in manila.conf
194----------------------------------------------------
195
196Add CephFS to ``enabled_share_protocols`` (enforced at manila api layer). In
144this example we leave NFS and CIFS enabled, although you can remove these 197this example we leave NFS and CIFS enabled, although you can remove these
145if you will only use CephFS: 198if you will only use CephFS:
146 199
@@ -148,25 +201,28 @@ if you will only use CephFS:
148 201
149 enabled_share_protocols = NFS,CIFS,CEPHFS 202 enabled_share_protocols = NFS,CIFS,CEPHFS
150 203
151Create a section like this to define a CephFS backend: 204Create a section like this to define a CephFS native backend:
152 205
153.. code-block:: ini 206.. code-block:: ini
154 207
155 [cephfs1] 208 [cephfsnative1]
156 driver_handles_share_servers = False 209 driver_handles_share_servers = False
157 share_backend_name = CEPHFS1 210 share_backend_name = CEPHFSNATIVE1
158 share_driver = manila.share.drivers.cephfs.driver.CephFSDriver 211 share_driver = manila.share.drivers.cephfs.driver.CephFSDriver
159 cephfs_conf_path = /etc/ceph/ceph.conf 212 cephfs_conf_path = /etc/ceph/ceph.conf
213 cephfs_protocol_helper_type = CEPHFS
160 cephfs_auth_id = manila 214 cephfs_auth_id = manila
161 cephfs_cluster_name = ceph 215 cephfs_cluster_name = ceph
162 cephfs_enable_snapshots = false 216 cephfs_enable_snapshots = false
163 217
164Set ``driver-handles-share-servers`` to ``False`` as the driver does not 218Set ``driver-handles-share-servers`` to ``False`` as the driver does not
165manage the lifecycle of ``share-servers``. To let the driver perform snapshot 219manage the lifecycle of ``share-servers``. To let the driver perform snapshot
166related operations, set ``cephfs_enable_snapshots`` to True. 220related operations, set ``cephfs_enable_snapshots`` to True. For the driver
221backend to expose shares via the the native Ceph protocol, set
222``cephfs_protocol_helper_type`` to ``CEPHFS``.
167 223
168Then edit ``enabled_share_backends`` to point to the driver's backend section 224Then edit ``enabled_share_backends`` to point to the driver's backend section
169using the section name. In this example we are also including another backend 225using the section name. In this example we are also including another backend
170("generic1"), you would include whatever other backends you have configured. 226("generic1"), you would include whatever other backends you have configured.
171 227
172 228
@@ -178,61 +234,150 @@ using the section name. In this example we are also including another backend
178 234
179.. code-block:: ini 235.. code-block:: ini
180 236
181 enabled_share_backends = generic1, cephfs1 237 enabled_share_backends = generic1, cephfsnative1
238
239
240Configure CephFS NFS share backend in manila.conf
241-------------------------------------------------
242
243Add NFS to ``enabled_share_protocols`` if it's not already there:
244
245.. code-block:: ini
246
247 enabled_share_protocols = NFS,CIFS,CEPHFS
248
249
250Create a section to define a CephFS NFS share backend:
251
252.. code-block:: ini
253
254 [cephfsnfs1]
255 driver_handles_share_servers = False
256 share_backend_name = CEPHFSNFS1
257 share_driver = manila.share.drivers.cephfs.driver.CephFSDriver
258 cephfs_protocol_helper_type = NFS
259 cephfs_conf_path = /etc/ceph/ceph.conf
260 cephfs_auth_id = manila1
261 cephfs_cluster_name = ceph
262 cephfs_enable_snapshots = False
263 cephfs_ganesha_server_is_remote= False
264 cephfs_ganesha_server_ip = 172.24.4.3
265
266
267The following options are set in the driver backend section above:
268
269* ``driver-handles-share-servers`` to ``False`` as the driver does not
270 manage the lifecycle of ``share-servers``.
271
272* ``cephfs_protocol_helper_type`` to ``NFS`` to allow NFS protocol access to
273 the CephFS backed shares.
274
275* ``ceph_auth_id`` to the ceph auth ID created in :ref:`authorize_ceph_driver`.
276
277* ``cephfs_ganesha_server_is_remote`` to False if the NFS-ganesha server is
278 co-located with the :term:`manila-share` service. If the NFS-Ganesha
279 server is remote, then set the options to ``True``, and set other options
280 such as ``cephfs_ganesha_server_ip``, ``cephfs_ganesha_server_username``,
281 and ``cephfs_ganesha_server_password`` (or ``cephfs_ganesha_path_to_private_key``)
282 to allow the driver to manage the NFS-Ganesha export entries over SSH.
283
284* ``cephfs_ganesha_server_ip`` to the ganesha server IP address. It is
285 recommended to set this option even if the ganesha server is co-located
286 with the :term:`manila-share` service.
287
288Edit ``enabled_share_backends`` to point to the driver's backend section
289using the section name, ``cephfnfs1``.
290
291.. code-block:: ini
292
293 enabled_share_backends = generic1, cephfsnfs1
182 294
183 295
184Creating shares 296Creating shares
185--------------- 297~~~~~~~~~~~~~~~
298
299Create CephFS native share
300--------------------------
186 301
187The default share type may have ``driver_handles_share_servers`` set to True. 302The default share type may have ``driver_handles_share_servers`` set to True.
188Configure a share type suitable for cephfs: 303Configure a share type suitable for CephFS native share:
189 304
190.. code-block:: console 305.. code-block:: console
191 306
192 manila type-create cephfstype false 307 manila type-create cephfsnativetype false
308 manila type-key cephfsnativetype set vendor_name=Ceph storage_protocol=CEPHFS
193 309
194Then create yourself a share: 310Then create yourself a share:
195 311
196.. code-block:: console 312.. code-block:: console
197 313
198 manila create --share-type cephfstype --name cephshare1 cephfs 1 314 manila create --share-type cephfsnativetype --name cephnativeshare1 cephfs 1
199 315
200Note the export location of the share: 316Note the export location of the share:
201 317
202.. code-block:: console 318.. code-block:: console
203 319
204 manila share-export-location-list cephshare1 320 manila share-export-location-list cephnativeshare1
205 321
206The export location of the share contains the Ceph monitor (mon) addresses and 322The export location of the share contains the Ceph monitor (mon) addresses and
207ports, and the path to be mounted. It is of the form, 323ports, and the path to be mounted. It is of the form,
208``{mon ip addr:port}[,{mon ip addr:port}]:{path to be mounted}`` 324``{mon ip addr:port}[,{mon ip addr:port}]:{path to be mounted}``
209 325
326Create CephFS NFS share
327-----------------------
328
329Configure a share type suitable for CephFS NFS share:
330
331.. code-block:: console
332
333 manila type-create cephfsnfstype false
334 manila type-key cephfsnfstype set vendor_name=Ceph storage_protocol=NFS
335
336Then create a share:
337
338.. code-block:: console
339
340 manila create --share-type cephfsnfstype --name cephnfsshare1 nfs 1
341
342Note the export location of the share:
343
344.. code-block:: console
345
346 manila share-export-location-list cephnfsshare1
347
348The export location of the share contains the IP address of the NFS-Ganesha
349server and the path to be mounted. It is of the form,
350``{NFS-Ganesha server address}:{path to be mounted}``
351
210 352
211Allowing access to shares 353Allowing access to shares
212-------------------------- 354~~~~~~~~~~~~~~~~~~~~~~~~~
355
356Allow access to CephFS native share
357-----------------------------------
213 358
214Allow Ceph auth ID ``alice`` access to the share using ``cephx`` access type. 359Allow Ceph auth ID ``alice`` access to the share using ``cephx`` access type.
215 360
216.. code-block:: console 361.. code-block:: console
217 362
218 manila access-allow cephshare1 cephx alice 363 manila access-allow cephnativeshare1 cephx alice
219 364
220Note the access status, and the access/secret key of ``alice``. 365Note the access status, and the access/secret key of ``alice``.
221 366
222.. code-block:: console 367.. code-block:: console
223 368
224 manila access-list cephshare1 369 manila access-list cephnativeshare1
225 370
226.. note:: 371.. note::
227 372
228 In Mitaka release, the secret key is not exposed by any manila API. The 373 In Mitaka release, the secret key is not exposed by any manila API. The
229 Ceph storage admin needs to pass the secret key to the guest out of band of 374 Ceph storage admin needs to pass the secret key to the guest out of band of
230 manila. You can refer to the link below to see how the storage admin 375 manila. You can refer to the link below to see how the storage admin
231 could obtain the secret key of an ID. 376 could obtain the secret key of an ID.
232 http://docs.ceph.com/docs/jewel/rados/operations/user-management/#get-a-user 377 http://docs.ceph.com/docs/jewel/rados/operations/user-management/#get-a-user
233 378
234 Alternatively, the cloud admin can create Ceph auth IDs for each of the 379 Alternatively, the cloud admin can create Ceph auth IDs for each of the
235 tenants. The users can then request manila to authorize the pre-created 380 tenants. The users can then request manila to authorize the pre-created
236 Ceph auth IDs, whose secret keys are already shared with them out of band 381 Ceph auth IDs, whose secret keys are already shared with them out of band
237 of manila, to access the shares. 382 of manila, to access the shares.
238 383
@@ -248,9 +393,21 @@ Note the access status, and the access/secret key of ``alice``.
248 For more details, please see the Ceph documentation. 393 For more details, please see the Ceph documentation.
249 http://docs.ceph.com/docs/jewel/rados/operations/user-management/#add-a-user 394 http://docs.ceph.com/docs/jewel/rados/operations/user-management/#add-a-user
250 395
396Allow access to CephFS NFS share
397--------------------------------
398
399Allow a guest access to the share using ``ip`` access type.
400
401.. code-block:: console
402
403 manila access-allow cephnfsshare1 ip 172.24.4.225
251 404
252Mounting shares using FUSE client 405
253--------------------------------- 406Mounting CephFS shares
407~~~~~~~~~~~~~~~~~~~~~~
408
409Mounting CephFS native share using FUSE client
410----------------------------------------------
254 411
255Using the secret key of the authorized ID ``alice`` create a keyring file, 412Using the secret key of the authorized ID ``alice`` create a keyring file,
256``alice.keyring`` like: 413``alice.keyring`` like:
@@ -282,56 +439,72 @@ from the share's export location:
282 --keyring=./alice.keyring \ 439 --keyring=./alice.keyring \
283 --client-mountpoint=/volumes/_nogroup/4c55ad20-9c55-4a5e-9233-8ac64566b98c 440 --client-mountpoint=/volumes/_nogroup/4c55ad20-9c55-4a5e-9233-8ac64566b98c
284 441
442Mount CephFS NFS share using NFS client
443---------------------------------------
285 444
286Known restrictions 445In the guest, mount the share using the NFS client and knowing the share's
287------------------ 446export location.
288 447
289Consider the driver as a building block for supporting multi-tenant 448.. code-block:: ini
290workloads in the future. However, it can be used in private cloud 449
291deployments. 450 sudo mount -t nfs 172.24.4.3:/volumes/_nogroup/6732900b-32c1-4816-a529-4d6d3f15811e /mnt/nfs/
292 451
293- The guests have direct access to Ceph's public network. 452Known restrictions
453~~~~~~~~~~~~~~~~~~
454
455- To communicate with the Ceph backend, a CephFS driver instance
456 (represented as a backend driver section in manila.conf) requires its own
457 Ceph auth ID that is not used by other CephFS driver instances running in
458 the same controller node.
294 459
295- The snapshot support of the driver is disabled by default. The 460- The snapshot support of the driver is disabled by default. The
296 ``cephfs_enable_snapshots`` configuration option needs to be set to ``True`` 461 ``cephfs_enable_snapshots`` configuration option needs to be set to ``True``
297 to allow snapshot operations. Snapshot support will also need to be enabled 462 to allow snapshot operations. Snapshot support will also need to be enabled
298 on the backend CephFS storage. 463 on the backend CephFS storage.
299 464
300- Snapshots are read-only. A user can read a snapshot's contents from the 465- Snapshots are read-only. A user can read a snapshot's contents from the
301 ``.snap/{manila-snapshot-id}_{unknown-id}`` folder within the mounted 466 ``.snap/{manila-snapshot-id}_{unknown-id}`` folder within the mounted
302 share. 467 share.
303 468
469
470Restrictions with CephFS native share backend
471---------------------------------------------
472
304- To restrict share sizes, CephFS uses quotas that are enforced in the client 473- To restrict share sizes, CephFS uses quotas that are enforced in the client
305 side. The CephFS clients are relied on to respect quotas. 474 side. The CephFS FUSE clients are relied on to respect quotas.
306 475
307Mitaka release 476Mitaka release only
308 477
309- The secret-key of a Ceph auth ID required to mount a share is not exposed to 478- The secret-key of a Ceph auth ID required to mount a share is not exposed to
310 an user by a manila API. To workaround this, the storage admin would need to 479 an user by a manila API. To workaround this, the storage admin would need to
311 pass the key out of band of manila, or the user would need to use the Ceph ID 480 pass the key out of band of manila, or the user would need to use the Ceph ID
312 and key already created and shared with her by the cloud admin. 481 and key already created and shared with her by the cloud admin.
313 482
314 483
315Security 484Security
316-------- 485~~~~~~~~
317 486
318- Each share's data is mapped to a distinct Ceph RADOS namespace. A guest is 487- Each share's data is mapped to a distinct Ceph RADOS namespace. A guest is
319 restricted to access only that particular RADOS namespace. 488 restricted to access only that particular RADOS namespace.
320 http://docs.ceph.com/docs/master/cephfs/file-layouts/ 489 http://docs.ceph.com/docs/master/cephfs/file-layouts/
321 490
322- An additional level of resource isolation can be provided by mapping a 491- An additional level of resource isolation can be provided by mapping a
323 share's contents to a separate RADOS pool. This layout would be be preferred 492 share's contents to a separate RADOS pool. This layout would be be preferred
324 only for cloud deployments with a limited number of shares needing strong 493 only for cloud deployments with a limited number of shares needing strong
325 resource separation. You can do this by setting a share type specification, 494 resource separation. You can do this by setting a share type specification,
326 ``cephfs:data_isolated`` for the share type used by the cephfs driver. 495 ``cephfs:data_isolated`` for the share type used by the cephfs driver.
327 496
328 .. code-block:: console 497 .. code-block:: console
329 498
330 manila type-key cephfstype set cephfs:data_isolated=True 499 manila type-key cephfstype set cephfs:data_isolated=True
331 500
332- As mentioned earlier, untrusted manila guests pose security risks to the 501.. _security_cephfs_native:
333 Ceph storage cluster as they would have direct access to the cluster's 502
334 public network. 503Security with CephFS native share backend
504-----------------------------------------
505
506As the guests need direct access to Ceph's public network, CephFS native
507share backend is suitable only in private clouds where guests can be trusted.
335 508
336 509
337The :mod:`manila.share.drivers.cephfs.driver` Module 510The :mod:`manila.share.drivers.cephfs.driver` Module
diff --git a/doc/source/devref/share_back_ends_feature_support_mapping.rst b/doc/source/devref/share_back_ends_feature_support_mapping.rst
index 6486070..a6fbc1d 100644
--- a/doc/source/devref/share_back_ends_feature_support_mapping.rst
+++ b/doc/source/devref/share_back_ends_feature_support_mapping.rst
@@ -134,7 +134,7 @@ Mapping of share drivers and share access rules support
134+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+ 134+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+
135| Oracle ZFSSA | NFS,CIFS(K) | \- | \- | \- | \- | \- | \- | \- | 135| Oracle ZFSSA | NFS,CIFS(K) | \- | \- | \- | \- | \- | \- | \- |
136+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+ 136+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+
137| CephFS | \- | \- | \- | CEPHFS (M) | \- | \- | \- | CEPHFS (N) | 137| CephFS | NFS (P) | \- | \- | CEPHFS (M) | NFS (P) | \- | \- | CEPHFS (N) |
138+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+ 138+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+
139| Tegile | NFS (M) |NFS (M),CIFS (M)| \- | \- | NFS (M) |NFS (M),CIFS (M)| \- | \- | 139| Tegile | NFS (M) |NFS (M),CIFS (M)| \- | \- | NFS (M) |NFS (M),CIFS (M)| \- | \- |
140+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+ 140+----------------------------------------+--------------+----------------+------------+--------------+--------------+----------------+------------+------------+
diff --git a/manila/share/drivers/cephfs/conf/cephfs-export-template.conf b/manila/share/drivers/cephfs/conf/cephfs-export-template.conf
new file mode 100644
index 0000000..dfbcd57
--- /dev/null
+++ b/manila/share/drivers/cephfs/conf/cephfs-export-template.conf
@@ -0,0 +1,5 @@
1EXPORT {
2 FSAL {
3 Name = "CEPH";
4 }
5}
diff --git a/manila/share/drivers/cephfs/driver.py b/manila/share/drivers/cephfs/driver.py
index ccb2d076..68d8686 100644
--- a/manila/share/drivers/cephfs/driver.py
+++ b/manila/share/drivers/cephfs/driver.py
@@ -14,6 +14,7 @@
14# under the License. 14# under the License.
15 15
16 16
17import socket
17import sys 18import sys
18 19
19from oslo_config import cfg 20from oslo_config import cfg
@@ -25,9 +26,9 @@ from manila import exception
25from manila.i18n import _ 26from manila.i18n import _
26from manila.share import driver 27from manila.share import driver
27from manila.share.drivers import ganesha 28from manila.share.drivers import ganesha
29from manila.share.drivers.ganesha import utils as ganesha_utils
28from manila.share import share_types 30from manila.share import share_types
29 31
30
31try: 32try:
32 import ceph_volume_client 33 import ceph_volume_client
33 ceph_module_found = True 34 ceph_module_found = True
@@ -62,13 +63,28 @@ cephfs_opts = [
62 ), 63 ),
63 cfg.StrOpt('cephfs_protocol_helper_type', 64 cfg.StrOpt('cephfs_protocol_helper_type',
64 default="CEPHFS", 65 default="CEPHFS",
65 # TODO(rraja): Add 'NFS' once CephFS/Ganesha support is 66 choices=['CEPHFS', 'NFS'],
66 # is available in manila.
67 choices=['CEPHFS', ],
68 ignore_case=True, 67 ignore_case=True,
69 help="The type of protocol helper to use. Default is " 68 help="The type of protocol helper to use. Default is "
70 "CEPHFS." 69 "CEPHFS."
71 ), 70 ),
71 cfg.BoolOpt('cephfs_ganesha_server_is_remote',
72 default=False,
73 help="Whether the NFS-Ganesha server is remote to the driver."
74 ),
75 cfg.StrOpt('cephfs_ganesha_server_ip',
76 help="The IP address of the NFS-Ganesha server."),
77 cfg.StrOpt('cephfs_ganesha_server_username',
78 default='root',
79 help="The username to authenticate as in the remote "
80 "NFS-Ganesha server host."),
81 cfg.StrOpt('cephfs_ganesha_path_to_private_key',
82 help="The path of the driver host's private SSH key file."),
83 cfg.StrOpt('cephfs_ganesha_server_password',
84 secret=True,
85 help="The password to authenticate as the user in the remote "
86 "Ganesha server host. This is not required if "
87 "'cephfs_ganesha_path_to_private_key' is configured."),
72] 88]
73 89
74 90
@@ -82,7 +98,8 @@ def cephfs_share_path(share):
82 share['share_group_id'], share['id']) 98 share['share_group_id'], share['id'])
83 99
84 100
85class CephFSDriver(driver.ShareDriver,): 101class CephFSDriver(driver.ExecuteMixin, driver.GaneshaMixin,
102 driver.ShareDriver,):
86 """Driver for the Ceph Filesystem.""" 103 """Driver for the Ceph Filesystem."""
87 104
88 def __init__(self, *args, **kwargs): 105 def __init__(self, *args, **kwargs):
@@ -95,11 +112,15 @@ class CephFSDriver(driver.ShareDriver,):
95 self.configuration.append_config_values(cephfs_opts) 112 self.configuration.append_config_values(cephfs_opts)
96 113
97 def do_setup(self, context): 114 def do_setup(self, context):
98 protocol_helper_class = getattr(sys.modules[__name__], 115 if self.configuration.cephfs_protocol_helper_type.upper() == "CEPHFS":
99 'NativeProtocolHelper') 116 protocol_helper_class = getattr(
117 sys.modules[__name__], 'NativeProtocolHelper')
118 else:
119 protocol_helper_class = getattr(
120 sys.modules[__name__], 'NFSProtocolHelper')
100 121
101 self.protocol_helper = protocol_helper_class( 122 self.protocol_helper = protocol_helper_class(
102 None, 123 self._execute,
103 self.configuration, 124 self.configuration,
104 volume_client=self.volume_client) 125 volume_client=self.volume_client)
105 126
@@ -412,3 +433,83 @@ class NativeProtocolHelper(ganesha.NASHelperBase):
412 self._deny_access(context, share, rule) 433 self._deny_access(context, share, rule)
413 434
414 return access_keys 435 return access_keys
436
437
438class NFSProtocolHelper(ganesha.GaneshaNASHelper2):
439
440 shared_data = {}
441 supported_protocols = ('NFS',)
442
443 def __init__(self, execute, config_object, **kwargs):
444 if config_object.cephfs_ganesha_server_is_remote:
445 execute = ganesha_utils.SSHExecutor(
446 config_object.cephfs_ganesha_server_ip, 22, None,
447 config_object.cephfs_ganesha_server_username,
448 password=config_object.cephfs_ganesha_server_password,
449 privatekey=config_object.cephfs_ganesha_path_to_private_key)
450 else:
451 execute = ganesha_utils.RootExecutor(execute)
452
453 self.ganesha_host = config_object.cephfs_ganesha_server_ip
454 if not self.ganesha_host:
455 self.ganesha_host = socket.gethostname()
456 LOG.info("NFS-Ganesha server's location defaulted to driver's "
457 "hostname: %s", self.ganesha_host)
458
459 self.volume_client = kwargs.pop('volume_client')
460
461 super(NFSProtocolHelper, self).__init__(execute, config_object,
462 **kwargs)
463
464 def get_export_locations(self, share, cephfs_volume):
465 export_location = "{server_address}:{path}".format(
466 server_address=self.ganesha_host,
467 path=cephfs_volume['mount_path'])
468
469 LOG.info("Calculated export location for share %(id)s: %(loc)s",
470 {"id": share['id'], "loc": export_location})
471
472 return {
473 'path': export_location,
474 'is_admin_only': False,
475 'metadata': {},
476 }
477
478 def _default_config_hook(self):
479 """Callback to provide default export block."""
480 dconf = super(NFSProtocolHelper, self)._default_config_hook()
481 conf_dir = ganesha_utils.path_from(__file__, "conf")
482 ganesha_utils.patch(dconf, self._load_conf_dir(conf_dir))
483 return dconf
484
485 def _fsal_hook(self, base, share, access):
486 """Callback to create FSAL subblock."""
487 ceph_auth_id = ''.join(['ganesha-', share['id']])
488 auth_result = self.volume_client.authorize(
489 cephfs_share_path(share), ceph_auth_id, readonly=False,
490 tenant_id=share['project_id'])
491 # Restrict Ganesha server's access to only the CephFS subtree or path,
492 # corresponding to the manila share, that is to be exported by making
493 # Ganesha use Ceph auth IDs with path restricted capabilities to
494 # communicate with CephFS.
495 return {
496 'Name': 'Ceph',
497 'User_Id': ceph_auth_id,
498 'Secret_Access_Key': auth_result['auth_key']
499 }
500
501 def _cleanup_fsal_hook(self, base, share, access):
502 """Callback for FSAL specific cleanup after removing an export."""
503 ceph_auth_id = ''.join(['ganesha-', share['id']])
504 self.volume_client.deauthorize(cephfs_share_path(share),
505 ceph_auth_id)
506
507 def _get_export_path(self, share):
508 """Callback to provide export path."""
509 volume_path = cephfs_share_path(share)
510 return self.volume_client._get_path(volume_path)
511
512 def _get_export_pseudo_path(self, share):
513 """Callback to provide pseudo path."""
514 volume_path = cephfs_share_path(share)
515 return self.volume_client._get_path(volume_path)
diff --git a/manila/share/drivers/ganesha/__init__.py b/manila/share/drivers/ganesha/__init__.py
index 61b727c..8df495d 100644
--- a/manila/share/drivers/ganesha/__init__.py
+++ b/manila/share/drivers/ganesha/__init__.py
@@ -120,6 +120,10 @@ class GaneshaNASHelper(NASHelperBase):
120 """Subclass this to create FSAL block.""" 120 """Subclass this to create FSAL block."""
121 return {} 121 return {}
122 122
123 def _cleanup_fsal_hook(self, base_path, share, access):
124 """Callback for FSAL specific cleanup after removing an export."""
125 pass
126
123 def _allow_access(self, base_path, share, access): 127 def _allow_access(self, base_path, share, access):
124 """Allow access to the share.""" 128 """Allow access to the share."""
125 if access['access_type'] != 'ip': 129 if access['access_type'] != 'ip':
@@ -239,3 +243,4 @@ class GaneshaNASHelper2(GaneshaNASHelper):
239 else: 243 else:
240 # No clients have access to the share. Remove export. 244 # No clients have access to the share. Remove export.
241 self.ganesha.remove_export(share['name']) 245 self.ganesha.remove_export(share['name'])
246 self._cleanup_fsal_hook(None, share, None)
diff --git a/manila/share/drivers/ganesha/manager.py b/manila/share/drivers/ganesha/manager.py
index 6df1c2e..ecb1100 100644
--- a/manila/share/drivers/ganesha/manager.py
+++ b/manila/share/drivers/ganesha/manager.py
@@ -141,6 +141,11 @@ def _dump_to_conf(confdict, out=sys.stdout, indent=0):
141 out.write("{\n") 141 out.write("{\n")
142 _dump_to_conf(item, out, indent + 1) 142 _dump_to_conf(item, out, indent + 1)
143 out.write(' ' * (indent * IWIDTH) + '}\n') 143 out.write(' ' * (indent * IWIDTH) + '}\n')
144 # The 'CLIENTS' Ganesha string option is an exception in that it's
145 # string value can't be enclosed within quotes as can be done for
146 # other string options in a valid Ganesha conf file.
147 elif k.upper() == 'CLIENTS':
148 out.write(' ' * (indent * IWIDTH) + k + ' = ' + v + ';')
144 else: 149 else:
145 out.write(' ' * (indent * IWIDTH) + k + ' ') 150 out.write(' ' * (indent * IWIDTH) + k + ' ')
146 out.write('= ') 151 out.write('= ')
@@ -149,10 +154,7 @@ def _dump_to_conf(confdict, out=sys.stdout, indent=0):
149 out.write('\n') 154 out.write('\n')
150 else: 155 else:
151 dj = jsonutils.dumps(confdict) 156 dj = jsonutils.dumps(confdict)
152 if confdict == dj[1:-1]: 157 out.write(dj)
153 out.write(confdict)
154 else:
155 out.write(dj)
156 158
157 159
158def parseconf(conf): 160def parseconf(conf):
diff --git a/manila/tests/share/drivers/cephfs/test_driver.py b/manila/tests/share/drivers/cephfs/test_driver.py
index 2ef0525..326a24b 100644
--- a/manila/tests/share/drivers/cephfs/test_driver.py
+++ b/manila/tests/share/drivers/cephfs/test_driver.py
@@ -63,6 +63,7 @@ class MockVolumeClientModule(object):
63 self.create_volume = mock.Mock(return_value={ 63 self.create_volume = mock.Mock(return_value={
64 "mount_path": "/foo/bar" 64 "mount_path": "/foo/bar"
65 }) 65 })
66 self._get_path = mock.Mock(return_value='/foo/bar')
66 self.get_mon_addrs = mock.Mock(return_value=["1.2.3.4", "5.6.7.8"]) 67 self.get_mon_addrs = mock.Mock(return_value=["1.2.3.4", "5.6.7.8"])
67 self.get_authorized_ids = mock.Mock( 68 self.get_authorized_ids = mock.Mock(
68 return_value=[('eve', 'rw')]) 69 return_value=[('eve', 'rw')])
@@ -87,6 +88,7 @@ class CephFSDriverTestCase(test.TestCase):
87 88
88 def setUp(self): 89 def setUp(self):
89 super(CephFSDriverTestCase, self).setUp() 90 super(CephFSDriverTestCase, self).setUp()
91 self._execute = mock.Mock()
90 self.fake_conf = configuration.Configuration(None) 92 self.fake_conf = configuration.Configuration(None)
91 self._context = context.get_admin_context() 93 self._context = context.get_admin_context()
92 self._share = fake_share.fake_share(share_proto='CEPHFS') 94 self._share = fake_share.fake_share(share_proto='CEPHFS')
@@ -99,20 +101,32 @@ class CephFSDriverTestCase(test.TestCase):
99 self.mock_object(driver, "ceph_module_found", True) 101 self.mock_object(driver, "ceph_module_found", True)
100 self.mock_object(driver, "cephfs_share_path") 102 self.mock_object(driver, "cephfs_share_path")
101 self.mock_object(driver, 'NativeProtocolHelper') 103 self.mock_object(driver, 'NativeProtocolHelper')
104 self.mock_object(driver, 'NFSProtocolHelper')
102 105
103 self._driver = ( 106 self._driver = (
104 driver.CephFSDriver(configuration=self.fake_conf)) 107 driver.CephFSDriver(execute=self._execute,
108 configuration=self.fake_conf))
105 self._driver.protocol_helper = mock.Mock() 109 self._driver.protocol_helper = mock.Mock()
106 110
107 self.mock_object(share_types, 'get_share_type_extra_specs', 111 self.mock_object(share_types, 'get_share_type_extra_specs',
108 mock.Mock(return_value={})) 112 mock.Mock(return_value={}))
109 113
110 def test_do_setup(self): 114 @ddt.data('cephfs', 'nfs')
115 def test_do_setup(self, protocol_helper):
116 self._driver.configuration.cephfs_protocol_helper_type = (
117 protocol_helper)
118
111 self._driver.do_setup(self._context) 119 self._driver.do_setup(self._context)
112 120
113 driver.NativeProtocolHelper.assert_called_once_with( 121 if protocol_helper == 'cephfs':
114 None, self._driver.configuration, 122 driver.NativeProtocolHelper.assert_called_once_with(
115 volume_client=self._driver._volume_client) 123 self._execute, self._driver.configuration,
124 volume_client=self._driver._volume_client)
125 else:
126 driver.NFSProtocolHelper.assert_called_once_with(
127 self._execute, self._driver.configuration,
128 volume_client=self._driver._volume_client)
129
116 self._driver.protocol_helper.init_helper.assert_called_once_with() 130 self._driver.protocol_helper.init_helper.assert_called_once_with()
117 131
118 def test_create_share(self): 132 def test_create_share(self):
@@ -507,3 +521,156 @@ class NativeProtocolHelperTestCase(test.TestCase):
507 self.assertFalse(vc.get_authorized_ids.called) 521 self.assertFalse(vc.get_authorized_ids.called)
508 vc.authorize.assert_called_once_with( 522 vc.authorize.assert_called_once_with(
509 driver.cephfs_share_path(self._share), "alice") 523 driver.cephfs_share_path(self._share), "alice")
524
525
526@ddt.ddt
527class NFSProtocolHelperTestCase(test.TestCase):
528
529 def setUp(self):
530 super(NFSProtocolHelperTestCase, self).setUp()
531 self._execute = mock.Mock()
532 self._share = fake_share.fake_share(share_proto='NFS')
533 self._volume_client = MockVolumeClientModule.CephFSVolumeClient()
534 self.fake_conf = configuration.Configuration(None)
535
536 self.fake_conf.set_default('cephfs_ganesha_server_ip',
537 'fakeip')
538 self.mock_object(driver, "cephfs_share_path",
539 mock.Mock(return_value='fakevolumepath'))
540 self.mock_object(driver.ganesha_utils, 'SSHExecutor')
541 self.mock_object(driver.ganesha_utils, 'RootExecutor')
542 self.mock_object(driver.socket, 'gethostname')
543
544 self._nfs_helper = driver.NFSProtocolHelper(
545 self._execute,
546 self.fake_conf,
547 volume_client=self._volume_client)
548
549 @ddt.data(False, True)
550 def test_init_executor_type(self, ganesha_server_is_remote):
551 fake_conf = configuration.Configuration(None)
552 conf_args_list = [
553 ('cephfs_ganesha_server_is_remote', ganesha_server_is_remote),
554 ('cephfs_ganesha_server_ip', 'fakeip'),
555 ('cephfs_ganesha_server_username', 'fake_username'),
556 ('cephfs_ganesha_server_password', 'fakepwd'),
557 ('cephfs_ganesha_path_to_private_key', 'fakepathtokey')]
558 for args in conf_args_list:
559 fake_conf.set_default(*args)
560
561 driver.NFSProtocolHelper(
562 self._execute,
563 fake_conf,
564 volume_client=MockVolumeClientModule.CephFSVolumeClient()
565 )
566
567 if ganesha_server_is_remote:
568 driver.ganesha_utils.SSHExecutor.assert_has_calls(
569 [mock.call('fakeip', 22, None, 'fake_username',
570 password='fakepwd',
571 privatekey='fakepathtokey')])
572 else:
573 driver.ganesha_utils.RootExecutor.assert_has_calls(
574 [mock.call(self._execute)])
575
576 @ddt.data('fakeip', None)
577 def test_init_identify_local_host(self, ganesha_server_ip):
578 self.mock_object(driver.LOG, 'info')
579 fake_conf = configuration.Configuration(None)
580 conf_args_list = [
581 ('cephfs_ganesha_server_ip', ganesha_server_ip),
582 ('cephfs_ganesha_server_username', 'fake_username'),
583 ('cephfs_ganesha_server_password', 'fakepwd'),
584 ('cephfs_ganesha_path_to_private_key', 'fakepathtokey')]
585 for args in conf_args_list:
586 fake_conf.set_default(*args)
587
588 driver.NFSProtocolHelper(
589 self._execute,
590 fake_conf,
591 volume_client=MockVolumeClientModule.CephFSVolumeClient()
592 )
593
594 driver.ganesha_utils.RootExecutor.assert_has_calls(
595 [mock.call(self._execute)])
596 if ganesha_server_ip:
597 self.assertFalse(driver.socket.gethostname.called)
598 self.assertFalse(driver.LOG.info.called)
599 else:
600 driver.socket.gethostname.assert_called_once_with()
601 driver.LOG.info.assert_called_once()
602
603 def test_get_export_locations(self):
604 cephfs_volume = {"mount_path": "/foo/bar"}
605
606 ret = self._nfs_helper.get_export_locations(self._share,
607 cephfs_volume)
608 self.assertEqual(
609 {
610 'path': 'fakeip:/foo/bar',
611 'is_admin_only': False,
612 'metadata': {}
613 }, ret)
614
615 def test_default_config_hook(self):
616 fake_conf_dict = {'key': 'value1'}
617 self.mock_object(driver.ganesha.GaneshaNASHelper,
618 '_default_config_hook',
619 mock.Mock(return_value={}))
620 self.mock_object(driver.ganesha_utils, 'path_from',
621 mock.Mock(return_value='/fakedir/cephfs/conf'))
622 self.mock_object(self._nfs_helper, '_load_conf_dir',
623 mock.Mock(return_value=fake_conf_dict))
624
625 ret = self._nfs_helper._default_config_hook()
626
627 (driver.ganesha.GaneshaNASHelper._default_config_hook.
628 assert_called_once_with())
629 driver.ganesha_utils.path_from.assert_called_once_with(
630 driver.__file__, 'conf')
631 self._nfs_helper._load_conf_dir.assert_called_once_with(
632 '/fakedir/cephfs/conf')
633 self.assertEqual(fake_conf_dict, ret)
634
635 def test_fsal_hook(self):
636 expected_ret = {
637 'Name': 'Ceph',
638 'User_Id': 'ganesha-fakeid',
639 'Secret_Access_Key': 'fakekey'
640 }
641 self.mock_object(self._volume_client, 'authorize',
642 mock.Mock(return_value={'auth_key': 'fakekey'}))
643
644 ret = self._nfs_helper._fsal_hook(None, self._share, None)
645
646 driver.cephfs_share_path.assert_called_once_with(self._share)
647 self._volume_client.authorize.assert_called_once_with(
648 'fakevolumepath', 'ganesha-fakeid', readonly=False,
649 tenant_id='fake_project_uuid')
650 self.assertEqual(expected_ret, ret)
651
652 def test_cleanup_fsal_hook(self):
653 self.mock_object(self._volume_client, 'deauthorize')
654
655 ret = self._nfs_helper._cleanup_fsal_hook(None, self._share, None)
656
657 driver.cephfs_share_path.assert_called_once_with(self._share)
658 self._volume_client.deauthorize.assert_called_once_with(
659 'fakevolumepath', 'ganesha-fakeid')
660 self.assertIsNone(ret)
661
662 def test_get_export_path(self):
663 ret = self._nfs_helper._get_export_path(self._share)
664
665 driver.cephfs_share_path.assert_called_once_with(self._share)
666 self._volume_client._get_path.assert_called_once_with(
667 'fakevolumepath')
668 self.assertEqual('/foo/bar', ret)
669
670 def test_get_export_pseudo_path(self):
671 ret = self._nfs_helper._get_export_pseudo_path(self._share)
672
673 driver.cephfs_share_path.assert_called_once_with(self._share)
674 self._volume_client._get_path.assert_called_once_with(
675 'fakevolumepath')
676 self.assertEqual('/foo/bar', ret)
diff --git a/manila/tests/share/drivers/ganesha/test_manager.py b/manila/tests/share/drivers/ganesha/test_manager.py
index a05e6bc..4d7abb1 100644
--- a/manila/tests/share/drivers/ganesha/test_manager.py
+++ b/manila/tests/share/drivers/ganesha/test_manager.py
@@ -71,11 +71,11 @@ class GaneshaConfigTests(test.TestCase):
71 ref_ganesha_cnf = """EXPORT { 71 ref_ganesha_cnf = """EXPORT {
72 CLIENT { 72 CLIENT {
73 Clients = ip1; 73 Clients = ip1;
74 Access_Level = ro; 74 Access_Level = "ro";
75 } 75 }
76 CLIENT { 76 CLIENT {
77 Clients = ip2; 77 Clients = ip2;
78 Access_Level = rw; 78 Access_Level = "rw";
79 } 79 }
80 Export_Id = 101; 80 Export_Id = 101;
81}""" 81}"""
diff --git a/manila/tests/share/drivers/test_ganesha.py b/manila/tests/share/drivers/test_ganesha.py
index 6d8dd6a..52524a3 100644
--- a/manila/tests/share/drivers/test_ganesha.py
+++ b/manila/tests/share/drivers/test_ganesha.py
@@ -220,6 +220,11 @@ class GaneshaNASHelperTestCase(test.TestCase):
220 ret = self._helper._fsal_hook('/fakepath', self.share, self.access) 220 ret = self._helper._fsal_hook('/fakepath', self.share, self.access)
221 self.assertEqual({}, ret) 221 self.assertEqual({}, ret)
222 222
223 def test_cleanup_fsal_hook(self):
224 ret = self._helper._cleanup_fsal_hook('/fakepath', self.share,
225 self.access)
226 self.assertIsNone(ret)
227
223 def test_allow_access(self): 228 def test_allow_access(self):
224 mock_ganesha_utils_patch = mock.Mock() 229 mock_ganesha_utils_patch = mock.Mock()
225 230
@@ -403,6 +408,7 @@ class GaneshaNASHelper2TestCase(test.TestCase):
403 mock_gh = self._helper.ganesha 408 mock_gh = self._helper.ganesha
404 self.mock_object(mock_gh, '_check_export_file_exists', 409 self.mock_object(mock_gh, '_check_export_file_exists',
405 mock.Mock(return_value=True)) 410 mock.Mock(return_value=True))
411 self.mock_object(self._helper, '_cleanup_fsal_hook')
406 client = {'Access_Type': 'ro', 'Clients': '10.0.0.1'} 412 client = {'Access_Type': 'ro', 'Clients': '10.0.0.1'}
407 self.mock_object( 413 self.mock_object(
408 mock_gh, '_read_export_file', 414 mock_gh, '_read_export_file',
@@ -415,6 +421,8 @@ class GaneshaNASHelper2TestCase(test.TestCase):
415 421
416 mock_gh._check_export_file_exists.assert_called_once_with('fakename') 422 mock_gh._check_export_file_exists.assert_called_once_with('fakename')
417 mock_gh.remove_export.assert_called_once_with('fakename') 423 mock_gh.remove_export.assert_called_once_with('fakename')
424 self._helper._cleanup_fsal_hook.assert_called_once_with(
425 None, self.share, None)
418 self.assertFalse(mock_gh.add_export.called) 426 self.assertFalse(mock_gh.add_export.called)
419 self.assertFalse(mock_gh.update_export.called) 427 self.assertFalse(mock_gh.update_export.called)
420 428
@@ -423,6 +431,7 @@ class GaneshaNASHelper2TestCase(test.TestCase):
423 self.mock_object(mock_gh, '_check_export_file_exists', 431 self.mock_object(mock_gh, '_check_export_file_exists',
424 mock.Mock(return_value=False)) 432 mock.Mock(return_value=False))
425 self.mock_object(ganesha.LOG, 'warning') 433 self.mock_object(ganesha.LOG, 'warning')
434 self.mock_object(self._helper, '_cleanup_fsal_hook')
426 435
427 self._helper.update_access( 436 self._helper.update_access(
428 self._context, self.share, access_rules=[], 437 self._context, self.share, access_rules=[],
@@ -433,3 +442,4 @@ class GaneshaNASHelper2TestCase(test.TestCase):
433 self.assertFalse(mock_gh.add_export.called) 442 self.assertFalse(mock_gh.add_export.called)
434 self.assertFalse(mock_gh.update_export.called) 443 self.assertFalse(mock_gh.update_export.called)
435 self.assertFalse(mock_gh.remove_export.called) 444 self.assertFalse(mock_gh.remove_export.called)
445 self.assertFalse(self._helper._cleanup_fsal_hook.called)
diff --git a/releasenotes/notes/cephfs-add-nfs-protocol-support-44764094c9d784d8.yaml b/releasenotes/notes/cephfs-add-nfs-protocol-support-44764094c9d784d8.yaml
new file mode 100644
index 0000000..86e43e4
--- /dev/null
+++ b/releasenotes/notes/cephfs-add-nfs-protocol-support-44764094c9d784d8.yaml
@@ -0,0 +1,3 @@
1---
2features:
3 - Added NFS protocol support for shares backed by CephFS.