Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/python3 

2# 

3# Copyright (C) Citrix Systems Inc. 

4# 

5# This program is free software; you can redistribute it and/or modify 

6# it under the terms of the GNU Lesser General Public License as published 

7# by the Free Software Foundation; version 2.1 only. 

8# 

9# This program is distributed in the hope that it will be useful, 

10# but WITHOUT ANY WARRANTY; without even the implied warranty of 

11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

12# GNU Lesser General Public License for more details. 

13# 

14# You should have received a copy of the GNU Lesser General Public License 

15# along with this program; if not, write to the Free Software Foundation, Inc., 

16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 

17# 

18# This module implements a safe way to rescan a scsi host so that: 

19# - at any time there is at most 1 rescan happening on a system for a hostid 

20# - we have as few rescans as possible 

21 

22import lock 

23import util 

24import os 

25import time 

26import glob 

27from datetime import datetime 

28from xmlrpc.client import DateTime 

29 

30HOST_LOCK_NAME_FORMAT = 'host%s' 

31RESCAN_LOCK_NAME = 'rescan' 

32START_TIME_FILE_PATH_FORMAT = '/var/run/host%s_starttime_%s' 

33 

34 

35def _rescan_hostID(host): 

36 util.SMlog("Performing rescan of host ID %s" % host) 

37 path = '/sys/class/scsi_host/host%s/scan' % host 

38 if os.path.exists(path): 

39 try: 

40 scanstring = "- - -" 

41 f = open(path, 'w') 

42 f.write('%s\n' % scanstring) 

43 f.close() 

44 # allow some time for undiscovered LUNs/channels to appear 

45 time.sleep(2) 

46 except Exception as e: 

47 util.SMlog("Failed to perform full rescan of host: %s. " \ 

48 "Error: %s" % (host, str(e))) 

49 raise Exception(str(e)) 

50 

51 

52def rescan(hostid): 

53 try: 

54 try: 

55 # get the current time, call it x 

56 curr_time = datetime.utcnow() 

57 

58 # acquire common lock 

59 l = lock.Lock(RESCAN_LOCK_NAME, HOST_LOCK_NAME_FORMAT % hostid) 

60 l.acquire() 

61 

62 while(1): 

63 # check if starttime_anything exists 

64 tryRescan = False 

65 files = glob.glob(START_TIME_FILE_PATH_FORMAT % (hostid, '*')) 

66 if len(files) == 0: 

67 # if not, create starttime_x 

68 path = START_TIME_FILE_PATH_FORMAT % (hostid, str(curr_time)) 

69 path = path.replace(' ', '_') 

70 open(path, 'w').close() 

71 

72 # release common lock 

73 l.release() 

74 

75 # perform host rescan 

76 _rescan_hostID(hostid) 

77 

78 # acquire common lock 

79 l.acquire() 

80 

81 # remove starttime_x 

82 os.unlink(path) 

83 

84 # release common lock and exit 

85 l.release() 

86 break 

87 else: 

88 # if it does 

89 # read the start time 

90 start_time = files[0].split(START_TIME_FILE_PATH_FORMAT % (hostid, ''))[1] 

91 start_time = DateTime(start_time.replace('__', ' ')) 

92 

93 while(1): 

94 # stick around till start_time exists 

95 # drop common lock 

96 l.release() 

97 

98 # sleep for a sec 

99 time.sleep(1) 

100 

101 # acquire common lock 

102 l.acquire() 

103 

104 # check if start time exists 

105 if len(glob.glob(START_TIME_FILE_PATH_FORMAT % \ 

106 (hostid, '*'))) == 0: 

107 tryRescan = False 

108 if DateTime(str(curr_time)) < start_time: 

109 # we are cool, this started before the rescan 

110 # drop common lock and go home 

111 l.release() 

112 else: 

113 # try to start a rescan 

114 tryRescan = True 

115 break 

116 # else continue by default 

117 

118 if not tryRescan: 

119 break 

120 

121 except Exception as e: 

122 util.SMlog("Failed to perform rescan of host: %s. " \ 

123 "Error: %s" % (hostid, str(e))) 

124 finally: 

125 l.release()