Coverage for sm/core/util.py : 39%

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"""Fake util module"""
4import os
5import subprocess
6import time
7import re
8import glob
9import syslog
10import signal
11import socket
13from . import f_exceptions
15SCSI_ID_BIN = '/usr/lib/udev/scsi_id'
16ISCSI_REFDIR = '/var/run/sr-ref'
18NO_LOGGING_STAMPFILE = '/etc/xensource/no_sm_log'
19LOGGING = not os.path.exists(NO_LOGGING_STAMPFILE)
20_SM_SYSLOG_FACILITY = syslog.LOG_LOCAL2
21LOG_EMERG = syslog.LOG_EMERG
22LOG_ALERT = syslog.LOG_ALERT
23LOG_CRIT = syslog.LOG_CRIT
24LOG_ERR = syslog.LOG_ERR
25LOG_WARNING = syslog.LOG_WARNING
26LOG_NOTICE = syslog.LOG_NOTICE
27LOG_INFO = syslog.LOG_INFO
28LOG_DEBUG = syslog.LOG_DEBUG
31def doexec(args, inputtext=None):
32 """Execute a subprocess, then return its return code, stdout and stderr"""
34 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
35 stdout=subprocess.PIPE,
36 stderr=subprocess.PIPE,
37 close_fds=True)
38 inputtext = inputtext.encode('utf-8') if inputtext else inputtext
39 (stdout, stderr) = proc.communicate(inputtext)
40 stdout = stdout.decode('utf-8')
41 stderr = stderr.decode('utf-8')
42 ret = proc.returncode
43 return (ret, stdout, stderr)
45def get_real_path(path):
46 "Follow symlinks to the actual file"
47 absPath = path
48 directory = ''
49 while os.path.islink(absPath):
50 directory = os.path.dirname(absPath)
51 absPath = os.readlink(absPath)
52 absPath = os.path.join(directory, absPath)
53 return absPath
56def wait_for_path(path, timeout):
57 for _ in range(timeout):
58 if len(glob.glob(path)):
59 return True
60 time.sleep(1)
61 return False
63def wait_for_nopath(path,timeout):
64 for i in range(0,timeout):
65 if not os.path.exists(path):
66 return True
67 time.sleep(1)
68 return False
71def scsi_id_sanitise(str_):
72 """scsi_id_sanitise"""
73 text = re.sub("^\s+", "", str_) # pylint: disable=W1401
74 return re.sub("\s+", "_", text) # pylint: disable=W1401
77def is_string(value):
78 """trivial"""
79 return isinstance(value, str)
82def pread(cmdlist, scramble=None, expect_rc=0):
83 """ported from SM util"""
84 cmdlist_for_exec = []
85 cmdlist_for_log = []
86 for item in cmdlist:
87 if is_string(item):
88 cmdlist_for_exec.append(item)
89 if scramble:
90 if item.find(scramble) != -1:
91 cmdlist_for_log.append("<filtered out>")
92 else:
93 cmdlist_for_log.append(item)
94 else:
95 cmdlist_for_log.append(item)
96 else:
97 cmdlist_for_exec.append(item[0])
98 cmdlist_for_log.append(item[1])
100 (ret, stdout, stderr) = doexec(cmdlist_for_exec)
101 if ret != expect_rc:
102 if stderr == '':
103 stderr = stdout
104 raise f_exceptions.XenError("Command", stderr.strip())
105 return stdout
108def pread2(cmdlist):
109 """Ditto"""
110 return pread(cmdlist)
113def get_scsi_id(path):
114 """Get the SCSI id of a block device
116 Input:
117 path -- (str) path to block device; can be symlink
119 Return:
120 scsi_id -- (str) the device's SCSI id
122 Raise:
123 f_exceptions.XenError
124 """
126 if not path.startswith('/dev/'):
127 path = '/dev/' + path.lstrip('/')
129 stdout = pread2([SCSI_ID_BIN, '-g', '--device', path])
131 return scsi_id_sanitise(stdout[:-1])
134def match_uuid(s):
135 regex = re.compile("^[0-9a-f]{8}-(([0-9a-f]{4})-){3}[0-9a-f]{12}")
136 return regex.search(s, 0)
139class TimeoutException(Exception):
140 pass
143def timeout_call(timeoutseconds, function, *arguments):
144 def handler(signum, frame):
145 raise TimeoutException()
146 signal.signal(signal.SIGALRM, handler)
147 signal.alarm(timeoutseconds)
148 try:
149 function(*arguments)
150 finally:
151 # Cancel the alarm signal so that it isn't fired later on
152 signal.alarm(0)
155def _incr_iscsiSR_refcount(targetIQN, uuid):
156 if not os.path.exists(ISCSI_REFDIR):
157 os.mkdir(ISCSI_REFDIR)
158 filename = os.path.join(ISCSI_REFDIR, targetIQN)
159 try:
160 f = open(filename, 'a+')
161 except:
162 raise f_exceptions.XenError('LVMRefCount',
163 message='file %s' % filename)
165 f.seek(0)
166 found = False
167 refcount = 0
168 for line in filter(match_uuid, f.readlines()):
169 refcount += 1
170 if line.find(uuid) != -1:
171 found = True
172 if not found:
173 f.write("%s\n" % uuid)
174 refcount += 1
175 f.close()
176 return refcount
179def _decr_iscsiSR_refcount(targetIQN, uuid):
180 filename = os.path.join(ISCSI_REFDIR, targetIQN)
181 if not os.path.exists(filename):
182 return 0
183 try:
184 f = open(filename, 'a+')
185 except:
186 raise f_exceptions.XenError('LVMRefCount',
187 message='file %s' % filename)
188 f.seek(0)
189 output = []
190 refcount = 0
191 for line in filter(match_uuid, f.readlines()):
192 if line.find(uuid) == -1:
193 output.append(line[:-1])
194 refcount += 1
195 if not refcount:
196 os.unlink(filename)
197 return refcount
199 # Re-open file and truncate
200 f.close()
201 f = open(filename, 'w')
202 for i in range(0,refcount):
203 f.write("%s\n" % output[i])
204 f.close()
205 return refcount
207def _logToSyslog(ident, facility, priority, message):
208 syslog.openlog(ident, 0, facility)
209 syslog.syslog(priority, "[%d] %s" % (os.getpid(), message))
210 syslog.closelog()
213def SMlog(message, ident="SM", priority=LOG_INFO):
214 if LOGGING: 214 ↛ exitline 214 didn't return from function 'SMlog', because the condition on line 214 was never false
215 for message_line in str(message).split('\n'):
216 _logToSyslog(ident, _SM_SYSLOG_FACILITY, priority, message_line)
219def retry(f, maxretry=20, period=3):
220 retries = 0
221 while True:
222 try:
223 return f()
224 except Exception as e:
225 SMlog("Got exception: %s. Retry number: %s" % (str(e),retries))
227 retries += 1
228 if retries >= maxretry:
229 break
231 time.sleep(period)
233 return f()
235def testHost(hostname, port):
236 """
237 Modified from _testHost in sm.util
238 """
239 SMlog("testHost: Testing host/port: %s,%d" % (hostname,port))
240 try:
241 sockinfo = socket.getaddrinfo(hostname, int(port))[0]
242 except:
243 SMlog('Exception occured getting IP for %s' % hostname)
244 return False
246 timeout = 10
248 sock = socket.socket(sockinfo[0], socket.SOCK_STREAM)
249 # Only allow the connect to block for up to timeout seconds
250 sock.settimeout(timeout)
251 try:
252 sock.connect(sockinfo[4])
253 # Fix for MS storage server bug
254 sock.send(b'\n')
255 sock.close()
256 return True
257 except socket.error as reason:
258 SMlog("testHost: Connect failed after %d seconds (%s) - %s" \
259 % (timeout, hostname, reason))
260 return False