# Copyright (C) 2014, Hitachi, Ltd. # # 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 functools import os import re import shlex import threading import time from oslo_concurrency import processutils as putils from oslo_config import cfg from oslo_utils import excutils from oslo_utils import units import six from cinder import exception from cinder.i18n import _LE, _LW from cinder.openstack.common import log as logging from cinder.openstack.common import loopingcall from cinder import utils from cinder.volume.drivers.hitachi import hbsd_basiclib as basic_lib GETSTORAGEARRAY_ONCE = 100 MAX_SNAPSHOT_COUNT = 1021 SNAP_LAST_PATH_SSB = '0xB958,0x020A' HOST_IO_SSB = '0xB958,0x0233' INVALID_LUN_SSB = '0x2E20,0x0000' INTERCEPT_LDEV_SSB = '0x2E22,0x0001' HOSTGROUP_INSTALLED = '0xB956,0x3173' LDEV_STATUS_WAITTIME = 120 LUN_DELETE_WAITTIME = basic_lib.DEFAULT_PROCESS_WAITTIME LUN_DELETE_INTERVAL = 3 EXEC_MAX_WAITTIME = 30 EXEC_RETRY_INTERVAL = 5 HORCM_WAITTIME = 1 PAIR_TYPE = ('HORC', 'MRCF', 'QS') PERMITTED_TYPE = ('CVS', 'HDP', 'HDT') RAIDCOM_LOCK_FILE = basic_lib.LOCK_DIR + 'raidcom_' HORCMGR_LOCK_FILE = basic_lib.LOCK_DIR + 'horcmgr_' RESOURCE_LOCK_FILE = basic_lib.LOCK_DIR + 'raidcom_resource_' STATUS_TABLE = { 'SMPL': basic_lib.SMPL, 'COPY': basic_lib.COPY, 'RCPY': basic_lib.COPY, 'PAIR': basic_lib.PAIR, 'PFUL': basic_lib.PAIR, 'PSUS': basic_lib.PSUS, 'PFUS': basic_lib.PSUS, 'SSUS': basic_lib.PSUS, 'PSUE': basic_lib.PSUE, } NOT_SET = '-' HORCM_RUNNING = 1 COPY_GROUP = basic_lib.NAME_PREFIX + '%s%s%03X%d' SNAP_NAME = basic_lib.NAME_PREFIX + 'snap' LDEV_NAME = basic_lib.NAME_PREFIX + 'ldev-%d-%d' MAX_MUNS = 3 EX_ENAUTH = 202 EX_ENOOBJ = 205 EX_CMDRJE = 221 EX_CMDIOE = 237 EX_INVCMD = 240 EX_INVMOD = 241 EX_ENODEV = 246 EX_ENOENT = 247 EX_OPTINV = 248 EX_ATTDBG = 250 EX_ATTHOR = 251 EX_COMERR = 255 EX_UNKOWN = -1 NO_SUCH_DEVICE = (EX_ENODEV, EX_ENOENT) COMMAND_IO_TO_RAID = (EX_CMDRJE, EX_CMDIOE, EX_INVCMD, EX_INVMOD, EX_OPTINV) HORCM_ERROR = (EX_ATTDBG, EX_ATTHOR, EX_COMERR) MAX_HOSTGROUPS = 254 MAX_HLUN = 2047 DEFAULT_PORT_BASE = 31000 LOG = logging.getLogger(__name__) volume_opts = [ cfg.StrOpt('hitachi_horcm_numbers', default='200,201', help='Instance numbers for HORCM'), cfg.StrOpt('hitachi_horcm_user', default=None, help='Username of storage system for HORCM'), cfg.StrOpt('hitachi_horcm_password', default=None, help='Password of storage system for HORCM'), cfg.BoolOpt('hitachi_horcm_add_conf', default=True, help='Add to HORCM configuration'), ] CONF = cfg.CONF CONF.register_opts(volume_opts) def horcm_synchronized(function): @functools.wraps(function) def wrapper(*args, **kargs): if len(args) == 1: inst = args[0].conf.hitachi_horcm_numbers[0] raidcom_obj_lock = args[0].raidcom_lock else: inst = args[1] raidcom_obj_lock = args[0].raidcom_pair_lock raidcom_lock_file = '%s%d' % (RAIDCOM_LOCK_FILE, inst) lock = basic_lib.get_process_lock(raidcom_lock_file) with raidcom_obj_lock, lock: return function(*args, **kargs) return wrapper def storage_synchronized(function): @functools.wraps(function) def wrapper(*args, **kargs): serial = args[0].conf.hitachi_serial_number resource_lock = args[0].resource_lock resource_lock_file = '%s%s' % (RESOURCE_LOCK_FILE, serial) lock = basic_lib.get_process_lock(resource_lock_file) with resource_lock, lock: return function(*args, **kargs) return wrapper class HBSDHORCM(basic_lib.HBSDBasicLib): def __init__(self, conf): super(HBSDHORCM, self).__init__(conf=conf) self.copy_groups = [None] * MAX_MUNS self.raidcom_lock = threading.Lock() self.raidcom_pair_lock = threading.Lock() self.horcmgr_lock = threading.Lock() self.horcmgr_flock = None self.resource_lock = threading.Lock() def check_param(self): numbers = self.conf.hitachi_horcm_numbers.split(',') if len(numbers) != 2: msg = basic_lib.output_err(601, param='hitachi_horcm_numbers') raise exception.HBSDError(message=msg) for i in numbers: if not i.isdigit(): msg = basic_lib.output_err(601, param='hitachi_horcm_numbers') raise exception.HBSDError(message=msg) self.conf.hitachi_horcm_numbers = map(int, numbers) inst = self.conf.hitachi_horcm_numbers[0] pair_inst = self.conf.hitachi_horcm_numbers[1] if inst == pair_inst: msg = basic_lib.output_err(601, param='hitachi_horcm_numbers') raise exception.HBSDError(message=msg) for param in ('hitachi_horcm_user', 'hitachi_horcm_password'): if not getattr(self.conf, param): msg = basic_lib.output_err(601, param=param) raise exception.HBSDError(message=msg) if self.conf.hitachi_thin_pool_id == self.conf.hitachi_pool_id: msg = basic_lib.output_err(601, param='hitachi_thin_pool_id') raise exception.HBSDError(message=msg) for opt in volume_opts: getattr(self.conf, opt.name) def set_copy_groups(self, host_ip): serial = self.conf.hitachi_serial_number inst = self.conf.hitachi_horcm_numbers[1] for mun in range(MAX_MUNS): copy_group = COPY_GROUP % (host_ip, serial, inst, mun) self.copy_groups[mun] = copy_group def set_pair_flock(self): inst = self.conf.hitachi_horcm_numbers[1] name = '%s%d' % (HORCMGR_LOCK_FILE, inst) self.horcmgr_flock = basic_lib.FileLock(name, self.horcmgr_lock) return self.horcmgr_flock def check_horcm(self, inst): args = 'HORCMINST=%d horcmgr -check' % inst ret, _stdout, _stderr = self.exec_command('env', args=args, printflag=False) return ret def shutdown_horcm(self, inst): ret, stdout, stderr = self.exec_command( 'horcmshutdown.sh', args=six.text_type(inst), printflag=False) return ret def start_horcm(self, inst): return self.exec_command('horcmstart.sh', args=six.text_type(inst), printflag=False) def _wait_for_horcm_shutdown(self, inst): if self.check_horcm(inst) != HORCM_RUNNING: raise loopingcall.LoopingCallDone() if self.shutdown_horcm(inst): LOG.error(_LE("Failed to shutdown horcm.")) raise loopingcall.LoopingCallDone() @horcm_synchronized def restart_horcm(self, inst=None): if inst is None: inst = self.conf.hitachi_horcm_numbers[0] loop = loopingcall.FixedIntervalLoopingCall( self._wait_for_horcm_shutdown, inst) loop.start(interval=HORCM_WAITTIME).wait() ret, stdout, stderr = self.start_horcm(inst) if ret: msg = basic_lib.output_err( 600, cmd='horcmstart.sh', ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def restart_pair_horcm(self): inst = self.conf.hitachi_horcm_numbers[1] self.restart_horcm(inst=inst) def setup_horcmgr(self, host_ip): pair_inst = self.conf.hitachi_horcm_numbers[1] self.set_copy_groups(host_ip) if self.conf.hitachi_horcm_add_conf: self.create_horcmconf() self.create_horcmconf(inst=pair_inst) self.restart_horcm() with self.horcmgr_flock: self.restart_pair_horcm() ret, stdout, stderr = self.comm_login() if ret: msg = basic_lib.output_err( 600, cmd='raidcom -login', ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def _wait_for_exec_horcm(self, cmd, args, printflag, start): if cmd == 'raidcom': serial = self.conf.hitachi_serial_number inst = self.conf.hitachi_horcm_numbers[0] raidcom_obj_lock = self.raidcom_lock args = '%s -s %s -I%d' % (args, serial, inst) else: inst = self.conf.hitachi_horcm_numbers[1] raidcom_obj_lock = self.raidcom_pair_lock args = '%s -ISI%d' % (args, inst) user = self.conf.hitachi_horcm_user passwd = self.conf.hitachi_horcm_password raidcom_lock_file = '%s%d' % (RAIDCOM_LOCK_FILE, inst) lock = basic_lib.get_process_lock(raidcom_lock_file) with raidcom_obj_lock, lock: ret, stdout, stderr = self.exec_command(cmd, args=args, printflag=printflag) if not ret or ret <= 127: raise loopingcall.LoopingCallDone((ret, stdout, stderr)) if time.time() - start >= EXEC_MAX_WAITTIME: LOG.error(_LE("horcm command timeout.")) raise loopingcall.LoopingCallDone((ret, stdout, stderr)) if (ret == EX_ENAUTH and not re.search("-login %s %s" % (user, passwd), args)): _ret, _stdout, _stderr = self.comm_login() if _ret: LOG.error(_LE("Failed to authenticate user.")) raise loopingcall.LoopingCallDone((ret, stdout, stderr)) elif ret in HORCM_ERROR: _ret = 0 with raidcom_obj_lock, lock: if self.check_horcm(inst) != HORCM_RUNNING: _ret, _stdout, _stderr = self.start_horcm(inst) if _ret and _ret != HORCM_RUNNING: LOG.error(_LE("Failed to start horcm.")) raise loopingcall.LoopingCallDone((ret, stdout, stderr)) elif ret not in COMMAND_IO_TO_RAID: LOG.error(_LE("Unexpected error occurs in horcm.")) raise loopingcall.LoopingCallDone((ret, stdout, stderr)) def exec_raidcom(self, cmd, args, printflag=True): loop = loopingcall.FixedIntervalLoopingCall( self._wait_for_exec_horcm, cmd, args, printflag, time.time()) return loop.start(interval=EXEC_RETRY_INTERVAL).wait() def comm_login(self): rmi_user = self.conf.hitachi_horcm_user rmi_pass = self.conf.hitachi_horcm_password args = '-login %s %s' % (rmi_user, rmi_pass) return self.exec_raidcom('raidcom', args, printflag=False) def comm_lock(self): ret, _stdout, stderr = self.exec_raidcom('raidcom', 'lock resource') if ret: msg = basic_lib.output_err( 603, serial=self.conf.hitachi_serial_number, inst=self.conf.hitachi_horcm_numbers[0], ret=ret, err=stderr) raise exception.HBSDError(message=msg) def comm_unlock(self): self.exec_raidcom('raidcom', 'unlock resource') def comm_reset_status(self): self.exec_raidcom('raidcom', 'reset command_status') def comm_get_status(self): return self.exec_raidcom('raidcom', 'get command_status') def get_command_error(self, stdout): lines = stdout.splitlines() line = shlex.split(lines[1]) return int(line[3]) def comm_get_ldev(self, ldev): opt = 'get ldev -ldev_id %s' % ldev ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) return stdout def add_used_hlun(self, port, gid, used_list): opt = 'get lun -port %s-%d' % (port, gid) ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() for line in lines[1:]: lun = int(shlex.split(line)[3]) if lun not in used_list: used_list.append(lun) def get_unused_ldev(self, ldev_range): start = ldev_range[0] end = ldev_range[1] while start < end: if end - start + 1 > GETSTORAGEARRAY_ONCE: cnt = GETSTORAGEARRAY_ONCE else: cnt = end - start + 1 opt = 'get ldev -ldev_id %d -cnt %d' % (start, cnt) ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() ldev_num = None for line in lines: if re.match("LDEV :", line): ldev_num = int(shlex.split(line)[2]) continue if re.match("VOL_TYPE : NOT DEFINED", line): return ldev_num start += GETSTORAGEARRAY_ONCE else: msg = basic_lib.output_err(648, resource='LDEV') raise exception.HBSDError(message=msg) def get_hgname_gid(self, port, host_grp_name): opt = 'get host_grp -port %s -key host_grp' % port ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) if line[2] == host_grp_name: return int(line[1]) return None def get_unused_gid(self, range, port): _min = range[0] _max = range[1] opt = 'get host_grp -port %s -key host_grp' % port ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() free_gid = None for line in lines[_min + 1:]: line = shlex.split(line) if int(line[1]) > _max: break if line[2] == '-': free_gid = int(line[1]) break if free_gid is None: msg = basic_lib.output_err(648, resource='GID') raise exception.HBSDError(message=msg) return free_gid def comm_set_target_wwns(self, target_ports): opt = 'get port' ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) target_wwns = {} lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) port = line[0][:5] if target_ports and port not in target_ports: continue target_wwns[port] = line[10] LOG.debug('target wwns: %s' % target_wwns) return target_wwns def comm_get_hbawwn(self, hostgroups, wwns, port, is_detected): opt = 'get host_grp -port %s' % port ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() found_wwns = 0 for line in lines[1:]: line = shlex.split(line) if not re.match(basic_lib.NAME_PREFIX, line[2]): continue gid = line[1] opt = 'get hba_wwn -port %s-%s' % (port, gid) ret, stdout, stderr = self.exec_raidcom( 'raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() for line in lines[1:]: hba_info = shlex.split(line) if hba_info[3] in wwns: hostgroups.append({'port': six.text_type(port), 'gid': int(hba_info[1]), 'initiator_wwn': hba_info[3], 'detected': is_detected}) found_wwns += 1 if len(wwns) == found_wwns: break if len(wwns) == found_wwns: break def comm_chk_login_wwn(self, wwns, port): opt = 'get port -port %s' % port ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() for line in lines[1:]: login_info = shlex.split(line) if login_info[1] in wwns: return True else: return False def comm_get_hostgroup_info(self, hgs, wwns, target_ports, login=True): security_ports = [] hostgroups = [] opt = 'get port' ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) port = line[0][:5] if target_ports and port not in target_ports: continue security = True if line[7] == 'Y' else False is_detected = None if login: is_detected = self.comm_chk_login_wwn(wwns, port) if security: self.comm_get_hbawwn(hostgroups, wwns, port, is_detected) security_ports.append(port) for hostgroup in hostgroups: hgs.append(hostgroup) return security_ports def _get_lun(self, port, gid, ldev): lun = None opt = 'get lun -port %s-%d' % (port, gid) ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) if line[5] == six.text_type(ldev): lun = int(line[3]) break return lun def _wait_for_delete_lun(self, hostgroup, ldev, start): opt = 'delete lun -port %s-%d -ldev_id %d' % (hostgroup['port'], hostgroup['gid'], ldev) ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if not ret: raise loopingcall.LoopingCallDone() if (re.search('SSB=%s' % SNAP_LAST_PATH_SSB, stderr) and not self.comm_get_snapshot(ldev) or re.search('SSB=%s' % HOST_IO_SSB, stderr)): msg = basic_lib.set_msg(310, ldev=ldev, reason=stderr) LOG.warning(msg) if time.time() - start >= LUN_DELETE_WAITTIME: msg = basic_lib.output_err( 637, method='_wait_for_delete_lun', timeout=LUN_DELETE_WAITTIME) raise exception.HBSDError(message=msg) else: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def comm_delete_lun_core(self, hostgroup, ldev): loop = loopingcall.FixedIntervalLoopingCall( self._wait_for_delete_lun, hostgroup, ldev, time.time()) loop.start(interval=LUN_DELETE_INTERVAL).wait() @storage_synchronized def comm_delete_lun(self, hostgroups, ldev): try: deleted_hostgroups = [] self.comm_lock() no_ldev_cnt = 0 for hostgroup in hostgroups: port = hostgroup['port'] gid = hostgroup['gid'] is_deleted = False for deleted in deleted_hostgroups: if port == deleted['port'] and gid == deleted['gid']: is_deleted = True if is_deleted: continue try: self.comm_delete_lun_core(hostgroup, ldev) except exception.HBSDCmdError as ex: no_ldev_cnt += 1 if ex.ret == EX_ENOOBJ: if no_ldev_cnt != len(hostgroups): continue raise exception.HBSDNotFound else: raise deleted_hostgroups.append({'port': port, 'gid': gid}) finally: self.comm_unlock() def _check_ldev_status(self, ldev, status): opt = ('get ldev -ldev_id %s -check_status %s -time %s' % (ldev, status, LDEV_STATUS_WAITTIME)) ret, _stdout, _stderr = self.exec_raidcom('raidcom', opt) return ret @storage_synchronized def comm_add_ldev(self, pool_id, ldev, capacity, is_vvol): emulation = 'OPEN-V' if is_vvol: opt = ('add ldev -pool snap -ldev_id %d ' '-capacity %dG -emulation %s' % (ldev, capacity, emulation)) else: opt = ('add ldev -pool %d -ldev_id %d ' '-capacity %dG -emulation %s' % (pool_id, ldev, capacity, emulation)) try: self.comm_lock() self.comm_reset_status() ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if ret: if re.search('SSB=%s' % INTERCEPT_LDEV_SSB, stderr): raise exception.HBSDNotFound opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) if self._check_ldev_status(ldev, "NML"): msg = basic_lib.output_err(653, ldev=ldev) raise exception.HBSDError(message=msg) finally: self.comm_unlock() @storage_synchronized def comm_add_hostgrp(self, port, gid, host_grp_name): opt = 'add host_grp -port %s-%d -host_grp_name %s' % (port, gid, host_grp_name) try: self.comm_lock() ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if ret: if re.search('SSB=%s' % HOSTGROUP_INSTALLED, stderr): raise exception.HBSDNotFound else: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError( message=msg, ret=ret, err=stderr) finally: self.comm_unlock() @storage_synchronized def comm_del_hostgrp(self, port, gid, host_grp_name): opt = 'delete host_grp -port %s-%d %s' % (port, gid, host_grp_name) try: self.comm_lock() ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) finally: self.comm_unlock() @storage_synchronized def comm_add_hbawwn(self, port, gid, wwn): opt = 'add hba_wwn -port %s-%s -hba_wwn %s' % (port, gid, wwn) try: self.comm_lock() ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) finally: self.comm_unlock() @storage_synchronized def comm_add_lun(self, unused_command, hostgroups, ldev, is_once=False): tmp_hostgroups = hostgroups[:] is_ok = False used_list = [] lun = None old_lun = None for hostgroup in hostgroups: port = hostgroup['port'] gid = hostgroup['gid'] self.add_used_hlun(port, gid, used_list) lun = self._get_lun(port, gid, ldev) # When 'lun' or 'old_lun' is 0, it should be true. # So, it cannot remove 'is not None'. if lun is not None: if old_lun is not None and old_lun != lun: msg = basic_lib.output_err(648, resource='LUN (HLUN)') raise exception.HBSDError(message=msg) is_ok = True hostgroup['lun'] = lun tmp_hostgroups.remove(hostgroup) old_lun = lun if is_once: # When 'lun' is 0, it should be true. # So, it cannot remove 'is not None'. if lun is not None: return elif len(used_list) < MAX_HLUN + 1: break else: tmp_hostgroups.remove(hostgroup) if tmp_hostgroups: used_list = [] if not used_list: lun = 0 elif lun is None: for i in range(MAX_HLUN + 1): if i not in used_list: lun = i break else: raise exception.HBSDNotFound opt = None ret = 0 stdout = None stderr = None invalid_hgs_str = None try: self.comm_lock() for hostgroup in tmp_hostgroups: port = hostgroup['port'] gid = hostgroup['gid'] if not hostgroup['detected']: if invalid_hgs_str: invalid_hgs_str = '%s, %s:%d' % (invalid_hgs_str, port, gid) else: invalid_hgs_str = '%s:%d' % (port, gid) continue opt = 'add lun -port %s-%d -ldev_id %d -lun_id %d' % ( port, gid, ldev, lun) ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if not ret: is_ok = True hostgroup['lun'] = lun if is_once: break else: msg = basic_lib.set_msg( 314, ldev=ldev, lun=lun, port=port, id=gid) LOG.warning(msg) finally: self.comm_unlock() if not is_ok: if stderr: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) else: msg = basic_lib.output_err(659, gid=invalid_hgs_str) raise exception.HBSDError(message=msg) @storage_synchronized def comm_delete_ldev(self, ldev, is_vvol): ret = -1 stdout = "" stderr = "" try: self.comm_lock() self.comm_reset_status() opt = 'delete ldev -ldev_id %d' % ldev ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if ret: if re.search('SSB=%s' % INVALID_LUN_SSB, stderr): raise exception.HBSDNotFound opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) ret, stdout, stderr = self.comm_get_status() if ret or self.get_command_error(stdout): opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) finally: self.comm_unlock() @storage_synchronized def comm_extend_ldev(self, ldev, old_size, new_size): ret = -1 stdout = "" stderr = "" extend_size = new_size - old_size try: self.comm_lock() self.comm_reset_status() opt = 'extend ldev -ldev_id %d -capacity %dG' % (ldev, extend_size) ret, stdout, stderr = self.exec_raidcom('raidcom', opt) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) ret, stdout, stderr = self.comm_get_status() if ret or self.get_command_error(stdout): opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) finally: self.comm_unlock() def comm_get_dp_pool(self, pool_id): opt = 'get dp_pool' ret, stdout, stderr = self.exec_raidcom('raidcom', opt, printflag=False) if ret: opt = 'raidcom %s' % opt msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) lines = stdout.splitlines() for line in lines[1:]: if int(shlex.split(line)[0]) == pool_id: free_gb = int(shlex.split(line)[3]) / 1024 total_gb = int(shlex.split(line)[4]) / 1024 return total_gb, free_gb msg = basic_lib.output_err(640, pool_id=pool_id) raise exception.HBSDError(message=msg) @storage_synchronized def comm_modify_ldev(self, ldev): args = 'modify ldev -ldev_id %d -status discard_zero_page' % ldev try: self.comm_lock() ret, stdout, stderr = self.exec_raidcom('raidcom', args) if ret: msg = basic_lib.set_msg(315, ldev=ldev, reason=stderr) LOG.warning(msg) finally: self.comm_unlock() def is_detected(self, port, wwn): return self.comm_chk_login_wwn([wwn], port) def discard_zero_page(self, ldev): try: self.comm_modify_ldev(ldev) except Exception as e: LOG.warning(_LW('Failed to discard zero page: %s') % six.text_type(e)) @storage_synchronized def comm_add_snapshot(self, pvol, svol): pool = self.conf.hitachi_thin_pool_id copy_size = self.conf.hitachi_copy_speed args = ('add snapshot -ldev_id %d %d -pool %d ' '-snapshot_name %s -copy_size %d' % (pvol, svol, pool, SNAP_NAME, copy_size)) try: self.comm_lock() ret, stdout, stderr = self.exec_raidcom('raidcom', args) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) finally: self.comm_unlock() @storage_synchronized def comm_delete_snapshot(self, ldev): args = 'delete snapshot -ldev_id %d' % ldev try: self.comm_lock() ret, stdout, stderr = self.exec_raidcom('raidcom', args) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) finally: self.comm_unlock() @storage_synchronized def comm_modify_snapshot(self, ldev, op): args = ('modify snapshot -ldev_id %d -snapshot_data %s' % (ldev, op)) try: self.comm_lock() ret, stdout, stderr = self.exec_raidcom('raidcom', args) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) finally: self.comm_unlock() def _wait_for_snap_status(self, pvol, svol, status, timeout, start): if (self.get_snap_pvol_status(pvol, svol) in status and self.get_snap_svol_status(svol) in status): raise loopingcall.LoopingCallDone() if time.time() - start >= timeout: msg = basic_lib.output_err( 637, method='_wait_for_snap_status', timuout=timeout) raise exception.HBSDError(message=msg) def wait_snap(self, pvol, svol, status, timeout, interval): loop = loopingcall.FixedIntervalLoopingCall( self._wait_for_snap_status, pvol, svol, status, timeout, time.time()) loop.start(interval=interval).wait() def comm_get_snapshot(self, ldev): args = 'get snapshot -ldev_id %d' % ldev ret, stdout, stderr = self.exec_raidcom('raidcom', args, printflag=False) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) return stdout def check_snap_count(self, ldev): stdout = self.comm_get_snapshot(ldev) if not stdout: return lines = stdout.splitlines() if len(lines) >= MAX_SNAPSHOT_COUNT + 1: msg = basic_lib.output_err( 615, copy_method=basic_lib.THIN, pvol=ldev) raise exception.HBSDBusy(message=msg) def get_snap_pvol_status(self, pvol, svol): stdout = self.comm_get_snapshot(pvol) if not stdout: return basic_lib.SMPL lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) if int(line[6]) == svol: return STATUS_TABLE[line[2]] else: return basic_lib.SMPL def get_snap_svol_status(self, ldev): stdout = self.comm_get_snapshot(ldev) if not stdout: return basic_lib.SMPL lines = stdout.splitlines() line = shlex.split(lines[1]) return STATUS_TABLE[line[2]] @horcm_synchronized def create_horcmconf(self, inst=None): if inst is None: inst = self.conf.hitachi_horcm_numbers[0] serial = self.conf.hitachi_serial_number filename = '/etc/horcm%d.conf' % inst port = DEFAULT_PORT_BASE + inst found = False if not os.path.exists(filename): file_str = """ HORCM_MON #ip_address service poll(10ms) timeout(10ms) 127.0.0.1 %16d 6000 3000 HORCM_CMD """ % port else: file_str = utils.read_file_as_root(filename) lines = file_str.splitlines() for line in lines: if re.match(r'\\\\.\\CMD-%s:/dev/sd' % serial, line): found = True break if not found: insert_str = r'\\\\.\\CMD-%s:/dev/sd' % serial file_str = re.sub(r'(\n\bHORCM_CMD.*|^\bHORCM_CMD.*)', r'\1\n%s\n' % insert_str, file_str) try: utils.execute('tee', filename, process_input=file_str, run_as_root=True) except putils.ProcessExecutionError as ex: msg = basic_lib.output_err( 632, file=filename, ret=ex.exit_code, err=ex.stderr) raise exception.HBSDError(message=msg) def comm_get_copy_grp(self): ret, stdout, stderr = self.exec_raidcom('raidcom', 'get copy_grp', printflag=False) if ret: opt = 'raidcom get copy_grp' msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) return stdout def comm_add_copy_grp(self, copy_group, pvol_group, svol_group, mun): args = ('add copy_grp -copy_grp_name %s %s %s -mirror_id %d' % (copy_group, pvol_group, svol_group, mun)) ret, stdout, stderr = self.exec_raidcom('raidcom', args, printflag=False) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def comm_delete_copy_grp(self, copy_group): args = 'delete copy_grp -copy_grp_name %s' % copy_group ret, stdout, stderr = self.exec_raidcom('raidcom', args, printflag=False) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def comm_get_device_grp(self, group_name): args = 'get device_grp -device_grp_name %s' % group_name ret, stdout, stderr = self.exec_raidcom('raidcom', args, printflag=False) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) return stdout def comm_add_device_grp(self, group_name, ldev_name, ldev): args = ('add device_grp -device_grp_name %s %s -ldev_id %d' % (group_name, ldev_name, ldev)) ret, stdout, stderr = self.exec_raidcom('raidcom', args, printflag=False) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def comm_delete_device_grp(self, group_name, ldev): args = ('delete device_grp -device_grp_name %s -ldev_id %d' % (group_name, ldev)) ret, stdout, stderr = self.exec_raidcom('raidcom', args, printflag=False) if ret: opt = 'raidcom %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def comm_paircreate(self, copy_group, ldev_name): args = ('-g %s -d %s -split -fq quick -c %d -vl' % (copy_group, ldev_name, self.conf.hitachi_copy_speed)) ret, stdout, stderr = self.exec_raidcom('paircreate', args) if ret: opt = 'paircreate %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def comm_pairsplit(self, copy_group, ldev_name): args = '-g %s -d %s -S' % (copy_group, ldev_name) ret, stdout, stderr = self.exec_raidcom('pairsplit', args) if ret: opt = 'pairsplit %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) def comm_pairevtwait(self, copy_group, ldev_name, check_svol): if not check_svol: option = '-nowait' else: option = '-nowaits' args = '-g %s -d %s %s' % (copy_group, ldev_name, option) ret, stdout, stderr = self.exec_raidcom('pairevtwait', args, printflag=False) if ret > 127: opt = 'pairevtwait %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) return ret def comm_pairdisplay(self, copy_group, ldev_name=None): if not ldev_name: args = '-g %s -CLI' % copy_group else: args = '-g %s -d %s -CLI' % (copy_group, ldev_name) ret, stdout, stderr = self.exec_raidcom('pairdisplay', args, printflag=False) if ret and ret not in NO_SUCH_DEVICE: opt = 'pairdisplay %s' % args msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) return ret, stdout, stderr def check_copy_grp(self, copy_group): stdout = self.comm_get_copy_grp() lines = stdout.splitlines() count = 0 for line in lines[1:]: line = shlex.split(line) if line[0] == copy_group: count += 1 if count == 2: break return count def check_device_grp(self, group_name, ldev, ldev_name=None): stdout = self.comm_get_device_grp(group_name) lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) if int(line[2]) == ldev: if not ldev_name: return True else: return line[1] == ldev_name else: return False def is_smpl(self, copy_group, ldev_name): ret, stdout, stderr = self.comm_pairdisplay(copy_group, ldev_name=ldev_name) if not stdout: return True lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) if line[9] in [NOT_SET, 'SMPL']: return True else: return False def get_copy_groups(self): copy_groups = [] stdout = self.comm_get_copy_grp() lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) if line[0] in self.copy_groups and line[0] not in copy_groups: copy_groups.append(line[0]) return copy_groups def get_matched_copy_group(self, pvol, svol, ldev_name): for copy_group in self.get_copy_groups(): pvol_group = '%sP' % copy_group if self.check_device_grp(pvol_group, pvol, ldev_name=ldev_name): return copy_group else: return None def get_paired_info(self, ldev, only_flag=False): paired_info = {'pvol': None, 'svol': []} pvol = None is_svol = False stdout = self.comm_get_snapshot(ldev) if stdout: lines = stdout.splitlines() line = shlex.split(lines[1]) status = STATUS_TABLE.get(line[2], basic_lib.UNKN) if line[1] == 'P-VOL': pvol = ldev svol = int(line[6]) else: is_svol = True pvol = int(line[6]) svol = ldev if status == basic_lib.PSUS: status = self.get_snap_pvol_status(pvol, svol) svol_info = {'lun': svol, 'status': status, 'is_vvol': True} paired_info['svol'].append(svol_info) paired_info['pvol'] = pvol if only_flag or is_svol: return paired_info for copy_group in self.get_copy_groups(): ldev_name = None pvol_status = basic_lib.UNKN svol_status = basic_lib.UNKN ret, stdout, stderr = self.comm_pairdisplay(copy_group) if not stdout: continue lines = stdout.splitlines() for line in lines[1:]: line = shlex.split(line) if line[9] not in ['P-VOL', 'S-VOL']: continue ldev0 = int(line[8]) ldev1 = int(line[12]) if ldev not in [ldev0, ldev1]: continue ldev_name = line[1] if line[9] == 'P-VOL': pvol = ldev0 svol = ldev1 pvol_status = STATUS_TABLE.get(line[10], basic_lib.UNKN) else: svol = ldev0 pvol = ldev1 svol_status = STATUS_TABLE.get(line[10], basic_lib.UNKN) if svol == ldev: is_svol = True if not ldev_name: continue pvol_group = '%sP' % copy_group pvol_ok = self.check_device_grp(pvol_group, pvol, ldev_name=ldev_name) svol_group = '%sS' % copy_group svol_ok = self.check_device_grp(svol_group, svol, ldev_name=ldev_name) if pvol_ok and svol_ok: if pvol_status == basic_lib.PSUS: status = svol_status else: status = pvol_status svol_info = {'lun': svol, 'status': status, 'is_vvol': False} paired_info['svol'].append(svol_info) if is_svol: break # When 'pvol' is 0, it should be true. # So, it cannot remove 'is not None'. if pvol is not None and paired_info['pvol'] is None: paired_info['pvol'] = pvol return paired_info @storage_synchronized def add_pair_config(self, pvol, svol, copy_group, ldev_name, mun): pvol_group = '%sP' % copy_group svol_group = '%sS' % copy_group try: self.comm_lock() self.comm_add_device_grp(pvol_group, ldev_name, pvol) self.comm_add_device_grp(svol_group, ldev_name, svol) nr_copy_groups = self.check_copy_grp(copy_group) if nr_copy_groups == 1: self.comm_delete_copy_grp(copy_group) if nr_copy_groups != 2: self.comm_add_copy_grp(copy_group, pvol_group, svol_group, mun) finally: self.comm_unlock() @storage_synchronized def delete_pair_config(self, pvol, svol, copy_group, ldev_name): pvol_group = '%sP' % copy_group svol_group = '%sS' % copy_group try: self.comm_lock() if self.check_device_grp(pvol_group, pvol, ldev_name=ldev_name): self.comm_delete_device_grp(pvol_group, pvol) if self.check_device_grp(svol_group, svol, ldev_name=ldev_name): self.comm_delete_device_grp(svol_group, svol) finally: self.comm_unlock() def _wait_for_pair_status(self, copy_group, ldev_name, status, timeout, check_svol, start): if self.comm_pairevtwait(copy_group, ldev_name, check_svol) in status: raise loopingcall.LoopingCallDone() if time.time() - start >= timeout: msg = basic_lib.output_err( 637, method='_wait_for_pair_status', timout=timeout) raise exception.HBSDError(message=msg) def wait_pair(self, copy_group, ldev_name, status, timeout, interval, check_svol=False): loop = loopingcall.FixedIntervalLoopingCall( self._wait_for_pair_status, copy_group, ldev_name, status, timeout, check_svol, time.time()) loop.start(interval=interval).wait() def comm_create_pair(self, pvol, svol, is_vvol): timeout = basic_lib.DEFAULT_PROCESS_WAITTIME interval = self.conf.hitachi_copy_check_interval if not is_vvol: restart = False create = False ldev_name = LDEV_NAME % (pvol, svol) mun = 0 for mun in range(MAX_MUNS): copy_group = self.copy_groups[mun] pvol_group = '%sP' % copy_group if not self.check_device_grp(pvol_group, pvol): break else: msg = basic_lib.output_err( 615, copy_method=basic_lib.FULL, pvol=pvol) raise exception.HBSDBusy(message=msg) try: self.add_pair_config(pvol, svol, copy_group, ldev_name, mun) self.restart_pair_horcm() restart = True self.comm_paircreate(copy_group, ldev_name) create = True self.wait_pair(copy_group, ldev_name, [basic_lib.PSUS], timeout, interval) self.wait_pair(copy_group, ldev_name, [basic_lib.PSUS, basic_lib.COPY], timeout, interval, check_svol=True) except Exception: with excutils.save_and_reraise_exception(): if create: try: self.wait_pair(copy_group, ldev_name, [basic_lib.PSUS], timeout, interval) self.wait_pair(copy_group, ldev_name, [basic_lib.PSUS], timeout, interval, check_svol=True) except Exception as ex: LOG.warning(_LW('Failed to create pair: %s') % six.text_type(ex)) try: self.comm_pairsplit(copy_group, ldev_name) self.wait_pair( copy_group, ldev_name, [basic_lib.SMPL], timeout, self.conf.hitachi_async_copy_check_interval) except Exception as ex: LOG.warning(_LW('Failed to create pair: %s') % six.text_type(ex)) if self.is_smpl(copy_group, ldev_name): try: self.delete_pair_config(pvol, svol, copy_group, ldev_name) except Exception as ex: LOG.warning(_LW('Failed to create pair: %s') % six.text_type(ex)) if restart: try: self.restart_pair_horcm() except Exception as ex: LOG.warning(_LW('Failed to restart horcm: %s') % six.text_type(ex)) else: self.check_snap_count(pvol) self.comm_add_snapshot(pvol, svol) try: self.wait_snap(pvol, svol, [basic_lib.PAIR], timeout, interval) self.comm_modify_snapshot(svol, 'create') self.wait_snap(pvol, svol, [basic_lib.PSUS], timeout, interval) except Exception: with excutils.save_and_reraise_exception(): try: self.comm_delete_snapshot(svol) self.wait_snap( pvol, svol, [basic_lib.SMPL], timeout, self.conf.hitachi_async_copy_check_interval) except Exception as ex: LOG.warning(_LW('Failed to create pair: %s') % six.text_type(ex)) def delete_pair(self, pvol, svol, is_vvol): timeout = basic_lib.DEFAULT_PROCESS_WAITTIME interval = self.conf.hitachi_async_copy_check_interval if not is_vvol: ldev_name = LDEV_NAME % (pvol, svol) copy_group = self.get_matched_copy_group(pvol, svol, ldev_name) if not copy_group: return try: self.comm_pairsplit(copy_group, ldev_name) self.wait_pair(copy_group, ldev_name, [basic_lib.SMPL], timeout, interval) finally: if self.is_smpl(copy_group, ldev_name): self.delete_pair_config(pvol, svol, copy_group, ldev_name) else: self.comm_delete_snapshot(svol) self.wait_snap(pvol, svol, [basic_lib.SMPL], timeout, interval) def comm_raidqry(self): ret, stdout, stderr = self.exec_command('raidqry', '-h') if ret: opt = 'raidqry -h' msg = basic_lib.output_err( 600, cmd=opt, ret=ret, out=stdout, err=stderr) raise exception.HBSDCmdError(message=msg, ret=ret, err=stderr) return stdout def get_comm_version(self): stdout = self.comm_raidqry() lines = stdout.splitlines() return shlex.split(lines[1])[1] def output_param_to_log(self, conf): for opt in volume_opts: if not opt.secret: value = getattr(conf, opt.name) LOG.info('\t%-35s%s' % (opt.name + ': ', six.text_type(value))) def create_lock_file(self): inst = self.conf.hitachi_horcm_numbers[0] pair_inst = self.conf.hitachi_horcm_numbers[1] serial = self.conf.hitachi_serial_number raidcom_lock_file = '%s%d' % (RAIDCOM_LOCK_FILE, inst) raidcom_pair_lock_file = '%s%d' % (RAIDCOM_LOCK_FILE, pair_inst) horcmgr_lock_file = '%s%d' % (HORCMGR_LOCK_FILE, pair_inst) resource_lock_file = '%s%s' % (RESOURCE_LOCK_FILE, serial) basic_lib.create_empty_file(raidcom_lock_file) basic_lib.create_empty_file(raidcom_pair_lock_file) basic_lib.create_empty_file(horcmgr_lock_file) basic_lib.create_empty_file(resource_lock_file) def connect_storage(self): properties = utils.brick_get_connector_properties() self.setup_horcmgr(properties['ip']) def get_max_hostgroups(self): """return the maximum value of hostgroup id.""" return MAX_HOSTGROUPS def get_hostgroup_luns(self, port, gid): list = [] self.add_used_hlun(port, gid, list) return list def get_ldev_size_in_gigabyte(self, ldev, existing_ref): param = 'serial_number' if param not in existing_ref: msg = basic_lib.output_err(700, param=param) raise exception.HBSDError(data=msg) storage = existing_ref.get(param) if storage != self.conf.hitachi_serial_number: msg = basic_lib.output_err(648, resource=param) raise exception.HBSDError(data=msg) stdout = self.comm_get_ldev(ldev) if not stdout: msg = basic_lib.output_err(648, resource='LDEV') raise exception.HBSDError(data=msg) sts_line = vol_type = "" vol_attrs = [] size = num_port = 1 lines = stdout.splitlines() for line in lines: if line.startswith("STS :"): sts_line = line elif line.startswith("VOL_TYPE :"): vol_type = shlex.split(line)[2] elif line.startswith("VOL_ATTR :"): vol_attrs = shlex.split(line)[2:] elif line.startswith("VOL_Capacity(BLK) :"): size = int(shlex.split(line)[2]) elif line.startswith("NUM_PORT :"): num_port = int(shlex.split(line)[2]) if 'NML' not in sts_line: msg = basic_lib.output_err(648, resource='LDEV') raise exception.HBSDError(data=msg) if 'OPEN-V' not in vol_type: msg = basic_lib.output_err(702, ldev=ldev) raise exception.HBSDError(data=msg) if 'HDP' not in vol_attrs: msg = basic_lib.output_err(702, ldev=ldev) raise exception.HBSDError(data=msg) for vol_attr in vol_attrs: if vol_attr == ':': continue if vol_attr in PAIR_TYPE: msg = basic_lib.output_err(705, ldev=ldev) raise exception.HBSDError(data=msg) if vol_attr not in PERMITTED_TYPE: msg = basic_lib.output_err(702, ldev=ldev) raise exception.HBSDError(data=msg) # Hitachi storage calculates volume sizes in a block unit, 512 bytes. # So, units.Gi is divided by 512. if size % (units.Gi / 512): msg = basic_lib.output_err(703, ldev=ldev) raise exception.HBSDError(data=msg) if num_port: msg = basic_lib.output_err(704, ldev=ldev) raise exception.HBSDError(data=msg) return size / (units.Gi / 512)