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

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

#!/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 

# 

# Clear the attach status for all VDIs in the given SR on this host.   

# Additionally, reset the paused state if this host is the master. 

 

import cleanup 

import util 

import lock 

import XenAPI 

 

def reset_sr(session, host_uuid, sr_uuid, is_sr_master): 

    from vhdutil import LOCK_TYPE_SR 

    from cleanup import LOCK_TYPE_RUNNING 

 

    cleanup.abort(sr_uuid) 

 

    gc_lock = lock.Lock(LOCK_TYPE_RUNNING, sr_uuid) 

    sr_lock = lock.Lock(LOCK_TYPE_SR, sr_uuid) 

    gc_lock.acquire() 

    sr_lock.acquire() 

 

    sr_ref = session.xenapi.SR.get_by_uuid(sr_uuid) 

 

    host_ref = session.xenapi.host.get_by_uuid(host_uuid) 

    host_key = "host_%s" % host_ref 

 

    util.SMlog("RESET for SR %s (master: %s)" % (sr_uuid, is_sr_master)) 

 

    vdi_recs = session.xenapi.VDI.get_all_records_where( \ 

            "field \"SR\" = \"%s\"" % sr_ref) 

 

    for vdi_ref, vdi_rec in vdi_recs.iteritems(): 

        vdi_uuid = vdi_rec["uuid"] 

        sm_config = vdi_rec["sm_config"] 

        if sm_config.get(host_key): 

            util.SMlog("Clearing attached status for VDI %s" % vdi_uuid) 

            session.xenapi.VDI.remove_from_sm_config(vdi_ref, host_key) 

        if is_sr_master and sm_config.get("paused"): 

            util.SMlog("Clearing paused status for VDI %s" % vdi_uuid) 

            session.xenapi.VDI.remove_from_sm_config(vdi_ref, "paused") 

 

    sr_lock.release() 

    gc_lock.release() 

 

def reset_vdi(session, vdi_uuid, force, term_output=True, writable=True): 

    vdi_ref = session.xenapi.VDI.get_by_uuid(vdi_uuid) 

    vdi_rec = session.xenapi.VDI.get_record(vdi_ref) 

    sm_config = vdi_rec["sm_config"] 

    host_ref = None 

    clean = True 

    for key, val in sm_config.iteritems(): 

        if key.startswith("host_"): 

            host_ref = key[len("host_"):] 

            host_uuid = None 

            host_invalid = False 

            host_str = host_ref 

            try: 

                host_rec = session.xenapi.host.get_record(host_ref) 

                host_uuid = host_rec["uuid"] 

                host_str = "%s (%s)" % (host_uuid, host_rec["name_label"]) 

            except XenAPI.Failure, e: 

                msg = "Invalid host: %s (%s)" % (host_ref, e) 

                util.SMlog(msg) 

                if term_output: 

                    print msg 

                host_invalid=True 

 

            if host_invalid: 

                session.xenapi.VDI.remove_from_sm_config(vdi_ref, key) 

                msg = "Invalid host: Force-cleared %s for %s on host %s" % \ 

                        (val, vdi_uuid, host_str) 

                util.SMlog(msg) 

                if term_output: 

                    print msg 

                continue 

 

            if force: 

                session.xenapi.VDI.remove_from_sm_config(vdi_ref, key) 

                msg = "Force-cleared %s for %s on host %s" % \ 

                        (val, vdi_uuid, host_str) 

                util.SMlog(msg) 

                if term_output: 

                    print msg 

                continue 

 

            ret = session.xenapi.host.call_plugin( 

                    host_ref, "on-slave", "is_open", 

                    {"vdiUuid": vdi_uuid, "srRef": vdi_rec["SR"]}) 

            if ret != "False": 

                util.SMlog("VDI %s is still open on host %s, not resetting" % \ 

                        (vdi_uuid, host_str)) 

                if term_output: 

                    print "ERROR: VDI %s is still open on host %s" % \ 

                            (vdi_uuid, host_str) 

                if writable: 

                    return False 

                else: 

                    clean = False 

            else: 

                session.xenapi.VDI.remove_from_sm_config(vdi_ref, key) 

                msg = "Cleared %s for %s on host %s" % \ 

                        (val, vdi_uuid, host_str) 

                util.SMlog(msg) 

                if term_output: 

                    print msg 

 

    if not host_ref: 

        msg = "VDI %s is not marked as attached anywhere, nothing to do" \ 

            % vdi_uuid 

        util.SMlog(msg) 

        if term_output: 

            print msg 

    return clean 

 

def usage(): 

    print "Usage:" 

    print "all <HOST UUID> <SR UUID> [--master]" 

    print "single <VDI UUID> [--force]" 

    print 

    print "*WARNING!* calling with 'all' on an attached SR, or using " + \ 

            "--force may cause DATA CORRUPTION if the VDI is still " + \ 

            "attached somewhere. Always manually double-check that " + \ 

            "the VDI is not in use before running this script." 

    sys.exit(1) 

 

142if __name__ == '__main__': 

    import sys 

    import atexit 

 

    if len(sys.argv) not in [3, 4, 5]: 

        usage() 

 

    session = XenAPI.xapi_local() 

    session.xenapi.login_with_password('root', '', '', 'SM') 

    atexit.register(session.xenapi.session.logout) 

 

    mode = sys.argv[1] 

    if mode == "all": 

        if len(sys.argv) not in [4, 5]: 

            usage() 

        host_uuid = sys.argv[2] 

        sr_uuid = sys.argv[3] 

        is_master = False 

        if len(sys.argv) == 5: 

            if sys.argv[4] == "--master": 

                is_master = True 

            else: 

                usage() 

        reset_sr(session, host_uuid, sr_uuid, is_master) 

    elif mode == "single": 

        vdi_uuid = sys.argv[2] 

        force = False 

        if len(sys.argv) == 4 and sys.argv[3] == "--force": 

            force = True 

        reset_vdi(session, vdi_uuid, force) 

    elif len(sys.argv) in [3, 4]: 

        # backwards compatibility: the arguments for the "all" case used to be  

        # just host_uuid, sr_uuid, [is_master] (i.e., no "all" string, since it  

        # was the only mode available). To avoid having to change XAPI, accept  

        # the old format here as well. 

        host_uuid = sys.argv[1] 

        sr_uuid = sys.argv[2] 

        is_master = False 

        if len(sys.argv) == 4: 

            if sys.argv[3] == "--master": 

                is_master = True 

            else: 

                usage() 

        reset_sr(session, host_uuid, sr_uuid, is_master) 

    else: 

        usage()