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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

#!/usr/bin/python 

# 

# Copyright (C) Citrix Systems Inc. 

# 

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

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

# by the Free Software Foundation; version 2.1 only. 

# 

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

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

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  

# GNU Lesser General Public License for more details. 

# 

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

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

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

 

"""Copy of mpath_dmp.py in SM with unneeded code removed""" 

 

import os 

import errno 

from . import util 

from . import f_exceptions 

 

DEVMAPPERPATH = "/dev/mapper" 

DEVBYIDPATH = "/dev/disk/by-id" 

MP_INUSEDIR = "/dev/disk/mpInuse" 

 

def activate_MPdev(sid, dst): 

    try: 

        os.mkdir(MP_INUSEDIR) 

    except OSError as exc: 

        if exc.errno == errno.EEXIST: 

            pass 

        else: 

            raise 

    path = os.path.join(MP_INUSEDIR, sid) 

    cmd = ['ln', '-sf', dst, path] 

    util.pread2(cmd) 

 

def deactivate_MPdev(sid): 

    path = os.path.join(MP_INUSEDIR, sid) 

    if os.path.exists(path): 

        os.unlink(path) 

 

def reset(sid): 

    util.SMlog("Resetting LUN %s" % sid) 

    _resetDMP(sid) 

 

def _resetDMP(sid): 

# If mpath has been turned on since the sr/vdi was attached, we 

# might be trying to unmap it before the daemon has been started 

# This is unnecessary (and will fail) so just return. 

    deactivate_MPdev(sid) 

 

# If the multipath daemon is running, but we were initially plugged 

# with multipathing set to no, there may be no map for us in the multipath 

# tables. In that case, list_paths will return [], but remove_map might 

# throw an exception. Catch it and ignore it. 

    util.retry(lambda: util.pread2(['/usr/sbin/multipath', '-f', sid]), 

               maxretry = 3, period = 4) 

    util.retry(lambda: util.pread2(['/usr/sbin/multipath', '-W']), maxretry = 3, 

               period = 4) 

 

    path = "/dev/mapper/%s" % sid 

 

    if not util.wait_for_nopath(path, 10): 

        util.SMlog("MPATH: WARNING - path did not disappear [%s]" % path) 

    else: 

        util.SMlog("MPATH: path disappeared [%s]" % path) 

 

def refresh(sid): 

    # Refresh the multipath status 

    util.SMlog("Refreshing LUN %s" % sid) 

    if len(sid): 

        path = DEVBYIDPATH + "/scsi-" + sid 

        if not os.path.exists(path): 

            raise f_exceptions.XenError("mpath_dmp", "{} not found". 

                                        format(path)) 

        _refresh_DMP(sid) 

    else: 

        raise f_exceptions.XenError('mpath_dmp', 'MPath not written yet') 

 

 

def _is_valid_multipath_device(sid): 

    by_id_path = "/dev/disk/by-id/scsi-"+sid 

    real_path = util.get_real_path(by_id_path) 

    (ret, stdout, stderr) = util.doexec(['/usr/sbin/multipath', '-a', sid]) 

    if ret < 0: 

        util.SMlog("Failed to add {}: wwid could be explicitly blacklisted\n" 

                   " Continue with multipath disabled for this SR".format(sid)) 

        return False 

    (ret, stdout, stderr) = util.doexec(['/usr/sbin/multipath', '-c', 

                                         real_path]) 

    if ret == 1: 

        # This is very fragile but it is not a good sign to fail without 

        # any output. At least until multipath 0.4.9, for example, multipath -c 

        # fails without any log if it is able to retrieve the wwid of the 

        # device. 

        # In this case it is better to fail immediately. 

        if not stdout+stderr: 

            # Attempt to cleanup wwids file before raising 

            try: 

                (ret, stdout, stderr) = util.doexec(['/usr/sbin/multipath', 

                                                     '-w', sid]) 

            except OSError: 

                util.SMlog("Error removing {} from wwids file".format(sid)) 

            raise f_exceptions.XenError('MultipathGenericFailure', 

                                        '"multipath -c" failed without any' 

                                        ' output on {}'.format(real_path)) 

        util.SMlog("When dealing with {} returned with:\n" 

                   " {}{} Continue with multipath disabled for this SR" 

                   .format(sid, stdout, stderr)) 

        return False 

    return True 

 

 

def _refresh_DMP(sid): 

    if not _is_valid_multipath_device(sid): 

        return 

    util.retry(lambda: util.pread2(['/usr/sbin/multipath', '-r', sid]), maxretry = 3, 

                           period = 4) 

    path = os.path.join(DEVMAPPERPATH, sid) 

    util.wait_for_path(path, 10) 

    if not os.path.exists(path): 

        raise f_exceptions.XenError('DMP', 'failed to activate mapper path') 

    lvm_path = "/dev/disk/by-scsid/"+sid+"/mapper" 

    util.wait_for_path(lvm_path, 10) 

    activate_MPdev(sid, path)