643 lines
26 KiB
Python
643 lines
26 KiB
Python
# Copyright (c) 2019 Infortrend Technology, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import json
|
|
import re
|
|
|
|
from oslo_concurrency import processutils
|
|
from oslo_log import log
|
|
from oslo_utils import units
|
|
|
|
from manila.common import constants
|
|
from manila import exception
|
|
from manila.i18n import _
|
|
from manila.share import utils as share_utils
|
|
from manila import utils as manila_utils
|
|
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
def _bi_to_gi(bi_size):
|
|
return bi_size / units.Gi
|
|
|
|
|
|
class InfortrendNAS(object):
|
|
|
|
_SSH_PORT = 22
|
|
|
|
def __init__(self, nas_ip, username, password, ssh_key,
|
|
timeout, pool_dict, channel_dict):
|
|
self.nas_ip = nas_ip
|
|
self.port = self._SSH_PORT
|
|
self.username = username
|
|
self.password = password
|
|
self.ssh_key = ssh_key
|
|
self.ssh_timeout = timeout
|
|
self.pool_dict = pool_dict
|
|
self.channel_dict = channel_dict
|
|
self.command = ""
|
|
self.ssh = None
|
|
self.sshpool = None
|
|
self.location = 'a@0'
|
|
|
|
def _execute(self, command_line):
|
|
command_line.extend(['-z', self.location])
|
|
commands = ' '.join(command_line)
|
|
manila_utils.check_ssh_injection(commands)
|
|
LOG.debug('Executing: %(command)s', {'command': commands})
|
|
|
|
cli_out = self._ssh_execute(commands)
|
|
|
|
return self._parser(cli_out)
|
|
|
|
def _ssh_execute(self, commands):
|
|
try:
|
|
out, err = processutils.ssh_execute(
|
|
self.ssh, commands,
|
|
timeout=self.ssh_timeout, check_exit_code=True)
|
|
except processutils.ProcessExecutionError as pe:
|
|
rc = pe.exit_code
|
|
out = pe.stdout
|
|
out = out.replace('\n', '\\n')
|
|
msg = _('Error on execute ssh command. '
|
|
'Exit code: %(rc)d, msg: %(out)s') % {
|
|
'rc': rc, 'out': out}
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
return out
|
|
|
|
def _parser(self, content=None):
|
|
LOG.debug('parsing data:\n%s', content)
|
|
content = content.replace("\r", "")
|
|
content = content.strip()
|
|
json_string = content.replace("'", "\"")
|
|
cli_data = json_string.splitlines()[2]
|
|
if cli_data:
|
|
try:
|
|
data_dict = json.loads(cli_data)
|
|
except Exception:
|
|
msg = _('Failed to parse data: '
|
|
'%(cli_data)s to dictionary.') % {
|
|
'cli_data': cli_data}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
rc = int(data_dict['cliCode'][0]['Return'], 16)
|
|
if rc == 0:
|
|
result = data_dict['data']
|
|
else:
|
|
result = data_dict['cliCode'][0]['CLI']
|
|
else:
|
|
msg = _('No data is returned from NAS.')
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
if rc != 0:
|
|
msg = _('NASCLI error, returned: %(result)s.') % {
|
|
'result': result}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendCLIException(
|
|
err=msg, rc=rc, out=result)
|
|
|
|
return rc, result
|
|
|
|
def do_setup(self):
|
|
self._init_connect()
|
|
self._ensure_service_on('nfs')
|
|
self._ensure_service_on('cifs')
|
|
|
|
def _init_connect(self):
|
|
if not (self.sshpool and self.ssh):
|
|
self.sshpool = manila_utils.SSHPool(ip=self.nas_ip,
|
|
port=self.port,
|
|
conn_timeout=None,
|
|
login=self.username,
|
|
password=self.password,
|
|
privatekey=self.ssh_key)
|
|
self.ssh = self.sshpool.create()
|
|
|
|
if not self.ssh.get_transport().is_active():
|
|
self.sshpool = manila_utils.SSHPool(ip=self.nas_ip,
|
|
port=self.port,
|
|
conn_timeout=None,
|
|
login=self.username,
|
|
password=self.password,
|
|
privatekey=self.ssh_key)
|
|
self.ssh = self.sshpool.create()
|
|
|
|
LOG.debug('NAScmd [%s@%s] start!', self.username, self.nas_ip)
|
|
|
|
def check_for_setup_error(self):
|
|
self._check_pools_setup()
|
|
self._check_channels_status()
|
|
|
|
def _ensure_service_on(self, proto, slot='A'):
|
|
command_line = ['service', 'status', proto]
|
|
rc, service_status = self._execute(command_line)
|
|
if not service_status[0][slot][proto.upper()]['enabled']:
|
|
command_line = ['service', 'restart', proto]
|
|
self._execute(command_line)
|
|
|
|
def _check_channels_status(self):
|
|
channel_list = list(self.channel_dict.keys())
|
|
command_line = ['ifconfig', 'inet', 'show']
|
|
rc, channels_status = self._execute(command_line)
|
|
for channel in channels_status:
|
|
if 'CH' in channel['datalink']:
|
|
ch = channel['datalink'].strip('CH')
|
|
if ch in self.channel_dict.keys():
|
|
self.channel_dict[ch] = channel['IP']
|
|
channel_list.remove(ch)
|
|
if channel['status'] == 'DOWN':
|
|
LOG.warning('Channel [%(ch)s] status '
|
|
'is down, please check.', {
|
|
'ch': ch})
|
|
if len(channel_list) != 0:
|
|
msg = _('Channel setting %(channel_list)s is invalid!') % {
|
|
'channel_list': channel_list}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(message=msg)
|
|
|
|
def _check_pools_setup(self):
|
|
pool_list = list(self.pool_dict.keys())
|
|
command_line = ['folder', 'status']
|
|
rc, pool_data = self._execute(command_line)
|
|
for pool in pool_data:
|
|
pool_name = self._extract_pool_name(pool)
|
|
if pool_name in self.pool_dict.keys():
|
|
pool_list.remove(pool_name)
|
|
self.pool_dict[pool_name]['id'] = pool['volumeId']
|
|
self.pool_dict[pool_name]['path'] = pool['directory'] + '/'
|
|
if len(pool_list) == 0:
|
|
break
|
|
|
|
if len(pool_list) != 0:
|
|
msg = _('Please create %(pool_list)s pool/s in advance!') % {
|
|
'pool_list': pool_list}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(message=msg)
|
|
|
|
def _extract_pool_name(self, pool_info):
|
|
return pool_info['directory'].split('/')[1]
|
|
|
|
def _extract_lv_name(self, pool_info):
|
|
return pool_info['path'].split('/')[2]
|
|
|
|
def update_pools_stats(self):
|
|
pools = []
|
|
command_line = ['folder', 'status']
|
|
rc, pools_data = self._execute(command_line)
|
|
|
|
for pool_info in pools_data:
|
|
pool_name = self._extract_pool_name(pool_info)
|
|
|
|
if pool_name in self.pool_dict.keys():
|
|
total_space = float(pool_info['size'])
|
|
pool_quota_used = self._get_pool_quota_used(pool_name)
|
|
available_space = total_space - pool_quota_used
|
|
|
|
total_capacity_gb = round(_bi_to_gi(total_space), 2)
|
|
free_capacity_gb = round(_bi_to_gi(available_space), 2)
|
|
|
|
pool = {
|
|
'pool_name': pool_name,
|
|
'total_capacity_gb': total_capacity_gb,
|
|
'free_capacity_gb': free_capacity_gb,
|
|
'reserved_percentage': 0,
|
|
'qos': False,
|
|
'dedupe': False,
|
|
'compression': False,
|
|
'snapshot_support': False,
|
|
'thin_provisioning': False,
|
|
'thick_provisioning': True,
|
|
'replication_type': None,
|
|
}
|
|
pools.append(pool)
|
|
|
|
return pools
|
|
|
|
def _get_pool_quota_used(self, pool_name):
|
|
pool_quota_used = 0.0
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
folder_name = self._extract_lv_name(pool_data)
|
|
|
|
command_line = ['fquota', 'status', pool_data['id'],
|
|
folder_name, '-t', 'folder']
|
|
rc, quota_status = self._execute(command_line)
|
|
|
|
for share_quota in quota_status:
|
|
pool_quota_used += int(share_quota['quota'])
|
|
|
|
return pool_quota_used
|
|
|
|
def _get_share_pool_data(self, pool_name):
|
|
if not pool_name:
|
|
msg = _("Pool is not available in the share host.")
|
|
raise exception.InvalidHost(reason=msg)
|
|
|
|
if pool_name in self.pool_dict.keys():
|
|
return self.pool_dict[pool_name]
|
|
else:
|
|
msg = _('Pool [%(pool_name)s] not set in conf.') % {
|
|
'pool_name': pool_name}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
def create_share(self, share, share_server=None):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
folder_name = self._extract_lv_name(pool_data)
|
|
share_proto = share['share_proto'].lower()
|
|
share_name = share['id'].replace('-', '')
|
|
share_path = pool_data['path'] + share_name
|
|
|
|
command_line = ['folder', 'options', pool_data['id'],
|
|
folder_name, '-c', share_name]
|
|
self._execute(command_line)
|
|
|
|
self._set_share_size(
|
|
pool_data['id'], pool_name, share_name, share['size'])
|
|
self._ensure_protocol_on(share_path, share_proto, share_name)
|
|
|
|
LOG.info('Create Share [%(share)s] completed.', {
|
|
'share': share['id']})
|
|
|
|
return self._export_location(
|
|
share_name, share_proto, pool_data['path'])
|
|
|
|
def _export_location(self, share_name, share_proto, pool_path=None):
|
|
location = []
|
|
location_data = {
|
|
'pool_path': pool_path,
|
|
'share_name': share_name,
|
|
}
|
|
self._check_channels_status()
|
|
for ch in sorted(self.channel_dict.keys()):
|
|
ip = self.channel_dict[ch]
|
|
if share_proto == 'nfs':
|
|
location.append(
|
|
ip + ':%(pool_path)s%(share_name)s' % location_data)
|
|
elif share_proto == 'cifs':
|
|
location.append(
|
|
'\\\\' + ip + '\\%(share_name)s' % location_data)
|
|
else:
|
|
msg = _('Unsupported protocol: [%s].') % share_proto
|
|
raise exception.InvalidInput(msg)
|
|
|
|
return location
|
|
|
|
def _set_share_size(self, pool_id, pool_name, share_name, share_size):
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
folder_name = self._extract_lv_name(pool_data)
|
|
command_line = ['fquota', 'create', pool_id, folder_name,
|
|
share_name, str(share_size) + 'G', '-t', 'folder']
|
|
self._execute(command_line)
|
|
|
|
LOG.debug('Set Share [%(share_name)s] '
|
|
'Size [%(share_size)s G] completed.', {
|
|
'share_name': share_name,
|
|
'share_size': share_size})
|
|
return
|
|
|
|
def _get_share_size(self, pool_id, pool_name, share_name):
|
|
share_size = None
|
|
command_line = ['fquota', 'status', pool_id,
|
|
share_name, '-t', 'folder']
|
|
rc, quota_status = self._execute(command_line)
|
|
|
|
for share_quota in quota_status:
|
|
if share_quota['name'] == share_name:
|
|
share_size = round(_bi_to_gi(float(share_quota['quota'])), 2)
|
|
break
|
|
|
|
return share_size
|
|
|
|
def delete_share(self, share, share_server=None):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
folder_name = self._extract_lv_name(pool_data)
|
|
share_name = share['id'].replace('-', '')
|
|
|
|
if self._check_share_exist(pool_name, share_name):
|
|
command_line = ['folder', 'options', pool_data['id'],
|
|
folder_name, '-d', share_name]
|
|
self._execute(command_line)
|
|
else:
|
|
LOG.warning('Share [%(share_name)s] is already deleted.', {
|
|
'share_name': share_name})
|
|
|
|
LOG.info('Delete Share [%(share)s] completed.', {
|
|
'share': share['id']})
|
|
|
|
def _check_share_exist(self, pool_name, share_name):
|
|
path = self.pool_dict[pool_name]['path']
|
|
command_line = ['pagelist', 'folder', path]
|
|
rc, subfolders = self._execute(command_line)
|
|
return any(subfolder['name'] == share_name for subfolder in subfolders)
|
|
|
|
def update_access(self, share, access_rules, add_rules,
|
|
delete_rules, share_server=None):
|
|
self._evict_unauthorized_clients(share, access_rules, share_server)
|
|
access_dict = {}
|
|
for access in access_rules:
|
|
try:
|
|
self._allow_access(share, access, share_server)
|
|
except (exception.InfortrendNASException) as e:
|
|
msg = _('Failed to allow access to client %(access)s, '
|
|
'reason %(e)s.') % {
|
|
'access': access['access_to'], 'e': e}
|
|
LOG.error(msg)
|
|
access_dict[access['id']] = 'error'
|
|
|
|
return access_dict
|
|
|
|
def _evict_unauthorized_clients(self, share, access_rules,
|
|
share_server=None):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
share_proto = share['share_proto'].lower()
|
|
share_name = share['id'].replace('-', '')
|
|
share_path = pool_data['path'] + share_name
|
|
|
|
access_list = []
|
|
for access in access_rules:
|
|
access_list.append(access['access_to'])
|
|
|
|
if share_proto == 'nfs':
|
|
host_ip_list = []
|
|
command_line = ['share', 'status', '-f', share_path]
|
|
rc, nfs_status = self._execute(command_line)
|
|
host_list = nfs_status[0]['nfs_detail']['hostList']
|
|
for host in host_list:
|
|
if host['host'] != '*':
|
|
host_ip_list.append(host['host'])
|
|
for ip in host_ip_list:
|
|
if ip not in access_list:
|
|
command_line = ['share', 'options', share_path,
|
|
'nfs', '-c', ip]
|
|
try:
|
|
self._execute(command_line)
|
|
except exception.InfortrendNASException:
|
|
msg = _("Failed to remove share access rule %s") % (ip)
|
|
LOG.exception(msg)
|
|
pass
|
|
|
|
elif share_proto == 'cifs':
|
|
host_user_list = []
|
|
command_line = ['acl', 'get', share_path]
|
|
rc, cifs_status = self._execute(command_line)
|
|
for cifs_rule in cifs_status:
|
|
if cifs_rule['name']:
|
|
host_user_list.append(cifs_rule['name'])
|
|
for user in host_user_list:
|
|
if user not in access_list:
|
|
command_line = ['acl', 'delete', share_path, '-u', user]
|
|
try:
|
|
self._execute(command_line)
|
|
except exception.InfortrendNASException:
|
|
msg = _("Failed to remove share access rule %s") % (
|
|
user)
|
|
LOG.exception(msg)
|
|
pass
|
|
|
|
def _allow_access(self, share, access, share_server=None):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
share_name = share['id'].replace('-', '')
|
|
share_path = pool_data['path'] + share_name
|
|
share_proto = share['share_proto'].lower()
|
|
access_type = access['access_type']
|
|
access_level = access['access_level'] or constants.ACCESS_LEVEL_RW
|
|
access_to = access['access_to']
|
|
ACCESS_LEVEL_MAP = {access_level: access_level}
|
|
msg = self._check_access_legal(share_proto, access_type)
|
|
if msg:
|
|
raise exception.InvalidShareAccess(reason=msg)
|
|
|
|
if share_proto == 'nfs':
|
|
command_line = ['share', 'options', share_path, 'nfs',
|
|
'-h', access_to, '-p', access_level]
|
|
self._execute(command_line)
|
|
|
|
elif share_proto == 'cifs':
|
|
if not self._check_user_exist(access_to):
|
|
msg = _('Please create user [%(user)s] in advance.') % {
|
|
'user': access_to}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
if access_level == constants.ACCESS_LEVEL_RW:
|
|
cifs_access = 'f'
|
|
elif access_level == constants.ACCESS_LEVEL_RO:
|
|
cifs_access = 'r'
|
|
try:
|
|
access_level = ACCESS_LEVEL_MAP[access_level]
|
|
except KeyError:
|
|
msg = _('Unsupported access_level: [%s].') % access_level
|
|
raise exception.InvalidInput(msg)
|
|
|
|
command_line = ['acl', 'set', share_path,
|
|
'-u', access_to, '-a', cifs_access]
|
|
self._execute(command_line)
|
|
|
|
LOG.info('Share [%(share)s] access to [%(access_to)s] '
|
|
'level [%(level)s] protocol [%(share_proto)s] completed.', {
|
|
'share': share['id'],
|
|
'access_to': access_to,
|
|
'level': access_level,
|
|
'share_proto': share_proto})
|
|
|
|
def _ensure_protocol_on(self, share_path, share_proto, cifs_name):
|
|
if not self._check_proto_enabled(share_path, share_proto):
|
|
command_line = ['share', share_path, share_proto, 'on']
|
|
if share_proto == 'cifs':
|
|
command_line.extend(['-n', cifs_name])
|
|
self._execute(command_line)
|
|
|
|
def _check_proto_enabled(self, share_path, share_proto):
|
|
command_line = ['share', 'status', '-f', share_path]
|
|
rc, share_status = self._execute(command_line)
|
|
if share_status:
|
|
check_enabled = share_status[0][share_proto]
|
|
if check_enabled:
|
|
return True
|
|
return False
|
|
|
|
def _check_user_exist(self, user_name):
|
|
command_line = ['useradmin', 'user', 'list']
|
|
rc, user_list = self._execute(command_line)
|
|
for user in user_list:
|
|
if user['Name'] == user_name:
|
|
return True
|
|
return False
|
|
|
|
def _check_access_legal(self, share_proto, access_type):
|
|
msg = None
|
|
if share_proto == 'cifs' and access_type != 'user':
|
|
msg = _('Infortrend CIFS share only supports USER access type.')
|
|
elif share_proto == 'nfs' and access_type != 'ip':
|
|
msg = _('Infortrend NFS share only supports IP access type.')
|
|
elif share_proto not in ('nfs', 'cifs'):
|
|
msg = _('Unsupported share protocol [%s].') % share_proto
|
|
return msg
|
|
|
|
def get_pool(self, share):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
if not pool_name:
|
|
share_name = share['id'].replace('-', '')
|
|
for pool in self.pool_dict.keys():
|
|
if self._check_share_exist(pool, share_name):
|
|
pool_name = pool
|
|
break
|
|
return pool_name
|
|
|
|
def ensure_share(self, share, share_server=None):
|
|
share_proto = share['share_proto'].lower()
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
share_name = share['id'].replace('-', '')
|
|
return self._export_location(
|
|
share_name, share_proto, pool_data['path'])
|
|
|
|
def extend_share(self, share, new_size, share_server=None):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
share_name = share['id'].replace('-', '')
|
|
self._set_share_size(pool_data['id'], pool_name, share_name, new_size)
|
|
|
|
LOG.info('Successfully Extend Share [%(share)s] '
|
|
'to size [%(new_size)s G].', {
|
|
'share': share['id'],
|
|
'new_size': new_size})
|
|
|
|
def shrink_share(self, share, new_size, share_server=None):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
share_name = share['id'].replace('-', '')
|
|
folder_name = self._extract_lv_name(pool_data)
|
|
|
|
command_line = ['fquota', 'status', pool_data['id'],
|
|
folder_name, '-t', 'folder']
|
|
rc, quota_status = self._execute(command_line)
|
|
|
|
for share_quota in quota_status:
|
|
if share_quota['name'] == share_name:
|
|
used_space = round(_bi_to_gi(float(share_quota['used'])), 2)
|
|
|
|
if new_size < used_space:
|
|
raise exception.ShareShrinkingPossibleDataLoss(
|
|
share_id=share['id'])
|
|
|
|
self._set_share_size(pool_data['id'], pool_name, share_name, new_size)
|
|
|
|
LOG.info('Successfully Shrink Share [%(share)s] '
|
|
'to size [%(new_size)s G].', {
|
|
'share': share['id'],
|
|
'new_size': new_size})
|
|
|
|
def manage_existing(self, share, driver_options):
|
|
share_proto = share['share_proto'].lower()
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
pool_data = self._get_share_pool_data(pool_name)
|
|
volume_name = self._extract_lv_name(pool_data)
|
|
input_location = share['export_locations'][0]['path']
|
|
share_name = share['id'].replace('-', '')
|
|
|
|
ch_ip, folder_name = self._parse_location(input_location, share_proto)
|
|
|
|
if not self._check_channel_ip(ch_ip):
|
|
msg = _('Export location ip: [%(ch_ip)s] '
|
|
'is incorrect, please use data port ip.') % {
|
|
'ch_ip': ch_ip}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
if not self._check_share_exist(pool_name, folder_name):
|
|
msg = _('Can not find folder [%(folder_name)s] '
|
|
'in pool [%(pool_name)s].') % {
|
|
'folder_name': folder_name,
|
|
'pool_name': pool_name}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
share_path = pool_data['path'] + folder_name
|
|
self._ensure_protocol_on(share_path, share_proto, share_name)
|
|
share_size = self._get_share_size(
|
|
pool_data['id'], pool_name, folder_name)
|
|
|
|
if not share_size:
|
|
msg = _('Folder [%(folder_name)s] has no size limitation, '
|
|
'please set it first for Openstack management.') % {
|
|
'folder_name': folder_name}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
# rename folder name
|
|
command_line = ['folder', 'options', pool_data['id'], volume_name,
|
|
'-k', folder_name, share_name]
|
|
self._execute(command_line)
|
|
|
|
location = self._export_location(
|
|
share_name, share_proto, pool_data['path'])
|
|
|
|
LOG.info('Successfully Manage Infortrend Share [%(folder_name)s], '
|
|
'Size: [%(size)s G], Protocol: [%(share_proto)s], '
|
|
'new name: [%(share_name)s].', {
|
|
'folder_name': folder_name,
|
|
'size': share_size,
|
|
'share_proto': share_proto,
|
|
'share_name': share_name})
|
|
|
|
return {'size': share_size, 'export_locations': location}
|
|
|
|
def _parse_location(self, input_location, share_proto):
|
|
ip = None
|
|
folder_name = None
|
|
pattern_ip = r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
|
|
if share_proto == 'nfs':
|
|
pattern_folder = r'[^\/]+$'
|
|
ip = "".join(re.findall(pattern_ip, input_location))
|
|
folder_name = "".join(re.findall(pattern_folder, input_location))
|
|
|
|
elif share_proto == 'cifs':
|
|
pattern_folder = r'[^\\]+$'
|
|
ip = "".join(re.findall(pattern_ip, input_location))
|
|
folder_name = "".join(re.findall(pattern_folder, input_location))
|
|
|
|
if not (ip and folder_name):
|
|
msg = _('Export location error, please check '
|
|
'ip: [%(ip)s], folder_name: [%(folder_name)s].') % {
|
|
'ip': ip,
|
|
'folder_name': folder_name}
|
|
LOG.error(msg)
|
|
raise exception.InfortrendNASException(err=msg)
|
|
|
|
return ip, folder_name
|
|
|
|
def _check_channel_ip(self, channel_ip):
|
|
return any(ip == channel_ip for ip in self.channel_dict.values())
|
|
|
|
def unmanage(self, share):
|
|
pool_name = share_utils.extract_host(share['host'], level='pool')
|
|
share_name = share['id'].replace('-', '')
|
|
|
|
if not self._check_share_exist(pool_name, share_name):
|
|
LOG.warning('Share [%(share_name)s] does not exist.', {
|
|
'share_name': share_name})
|
|
return
|
|
|
|
LOG.info('Successfully Unmanaged Share [%(share)s].', {
|
|
'share': share['id']})
|