Coverage for manila/share/drivers/windows/windows_smb_driver.py: 97%
80 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2015 Cloudbase Solutions SRL
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16import os
18from oslo_log import log
19from oslo_utils import units
21from manila.share import driver as base_driver
22from manila.share.drivers import generic
23from manila.share.drivers.windows import service_instance
24from manila.share.drivers.windows import windows_smb_helper
25from manila.share.drivers.windows import windows_utils
26from manila.share.drivers.windows import winrm_helper
29LOG = log.getLogger(__name__)
32class WindowsSMBDriver(generic.GenericShareDriver):
33 # NOTE(lpetrut): The first partition will be reserved by the OS.
34 _DEFAULT_SHARE_PARTITION = 2
36 def __init__(self, *args, **kwargs):
37 super(WindowsSMBDriver, self).__init__(*args, **kwargs)
38 LOG.warning('Windows SMB share driver has been deprecated and is '
39 'expected to be removed in a future release.')
41 self._remote_execute = winrm_helper.WinRMHelper(
42 configuration=self.configuration).execute
43 self._windows_utils = windows_utils.WindowsUtils(
44 remote_execute=self._remote_execute)
45 self._smb_helper = windows_smb_helper.WindowsSMBHelper(
46 remote_execute=self._remote_execute,
47 configuration=self.configuration)
49 def _update_share_stats(self, data=None):
50 base_driver.ShareDriver._update_share_stats(
51 self, data=dict(storage_protocol="CIFS"))
53 def _setup_service_instance_manager(self):
54 self.service_instance_manager = (
55 service_instance.WindowsServiceInstanceManager(
56 driver_config=self.configuration))
58 def _setup_helpers(self):
59 self._helpers = {key: self._smb_helper for key in ("SMB", "CIFS")}
61 def _teardown_server(self, server_details, security_services=None):
62 security_service = (
63 self.service_instance_manager.get_valid_security_service(
64 security_services))
65 if server_details.get('joined_domain') and security_service: 65 ↛ 77line 65 didn't jump to line 77 because the condition on line 65 was always true
66 try:
67 self._windows_utils.unjoin_domain(server_details,
68 security_service['user'],
69 security_service['password'])
70 except Exception as exc:
71 LOG.warning("Failed to remove service instance "
72 "%(instance_id)s from domain %(domain)s. "
73 "Exception: %(exc)s.",
74 dict(instance_id=server_details['instance_id'],
75 domain=security_service['domain'],
76 exc=exc))
77 super(WindowsSMBDriver, self)._teardown_server(server_details,
78 security_services)
80 def _format_device(self, server_details, volume):
81 disk_number = self._get_disk_number(server_details, volume)
82 self._windows_utils.initialize_disk(server_details, disk_number)
83 self._windows_utils.create_partition(server_details, disk_number)
84 self._windows_utils.format_partition(
85 server_details, disk_number,
86 self._DEFAULT_SHARE_PARTITION)
88 def _mount_device(self, share, server_details, volume):
89 mount_path = self._get_mount_path(share)
90 if not self._is_device_mounted(mount_path, server_details, volume): 90 ↛ exitline 90 didn't return from function '_mount_device' because the condition on line 90 was always true
91 disk_number = self._get_disk_number(server_details, volume)
92 self._windows_utils.ensure_directory_exists(server_details,
93 mount_path)
94 self._ensure_disk_online_and_writable(server_details, disk_number)
95 self._windows_utils.add_access_path(server_details,
96 mount_path,
97 disk_number,
98 self._DEFAULT_SHARE_PARTITION)
100 def _unmount_device(self, share, server_details):
101 mount_path = self._get_mount_path(share)
102 disk_number = self._windows_utils.get_disk_number_by_mount_path(
103 server_details, mount_path)
105 self._windows_utils.remove(server_details, mount_path,
106 is_junction=True)
107 if disk_number: 107 ↛ exitline 107 didn't return from function '_unmount_device' because the condition on line 107 was always true
108 self._windows_utils.set_disk_online_status(
109 server_details, disk_number, online=False)
111 def _resize_filesystem(self, server_details, volume, new_size=None):
112 disk_number = self._get_disk_number(server_details, volume)
113 self._ensure_disk_online_and_writable(server_details, disk_number)
115 if not new_size:
116 new_size_bytes = self._windows_utils.get_partition_maximum_size(
117 server_details, disk_number, self._DEFAULT_SHARE_PARTITION)
118 else:
119 new_size_bytes = new_size * units.Gi
121 self._windows_utils.resize_partition(server_details,
122 new_size_bytes,
123 disk_number,
124 self._DEFAULT_SHARE_PARTITION)
126 def _ensure_disk_online_and_writable(self, server_details, disk_number):
127 self._windows_utils.update_disk(server_details, disk_number)
128 self._windows_utils.set_disk_readonly_status(
129 server_details, disk_number, readonly=False)
130 self._windows_utils.set_disk_online_status(
131 server_details, disk_number, online=True)
133 def _get_mounted_share_size(self, mount_path, server_details):
134 total_bytes = self._windows_utils.get_disk_space_by_path(
135 server_details, mount_path)[0]
136 return float(total_bytes) / units.Gi
138 def _get_consumed_space(self, mount_path, server_details):
139 total_bytes, free_bytes = self._windows_utils.get_disk_space_by_path(
140 server_details, mount_path)
141 return float(total_bytes - free_bytes) / units.Gi
143 def _get_mount_path(self, share):
144 mount_path = os.path.join(self.configuration.share_mount_path,
145 share['name'])
146 return self._windows_utils.normalize_path(mount_path)
148 def _get_disk_number(self, server_details, volume):
149 disk_number = self._windows_utils.get_disk_number_by_serial_number(
150 server_details, volume['id'])
151 if disk_number is None:
152 LOG.debug("Could not identify the mounted disk by serial number "
153 "using the volume id %(volume_id)s. Attempting to "
154 "retrieve it by the volume mount point %(mountpoint)s.",
155 dict(volume_id=volume['id'],
156 mountpoint=volume['mountpoint']))
157 # Assumes the mount_point will be something like /dev/hdX
158 mount_point = volume['mountpoint']
159 disk_number = ord(mount_point[-1]) - ord('a')
160 return disk_number
162 def _is_device_mounted(self, mount_path, server_details, volume=None):
163 disk_number = self._windows_utils.get_disk_number_by_mount_path(
164 server_details, mount_path)
165 return disk_number is not None