summaryrefslogtreecommitdiffstats
path: root/dmraid.py
blob: f887e4040b019dfbdf95431d11f7ee0cb8e50aae (plain)
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
#!/usr/bin/python
#
# dmraid.py - dmraid probing control
#
# Peter Jones <pjones@redhat.com>
#
# Copyright 2005 Red Hat, Inc.
#
# This software may be freely redistributed under the terms of the GNU
# library public license.
#
# You should have received a copy of the GNU Library Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
"""DMRaid probing control."""
# XXX dmraid and md raid should be abstracted from the same thing. -pj
# XXX dmraid and lvm should use a common control mechanism (such as block.dm)
#     for device-mapper. -pj

import sys
import block
import parted

import logging
#log = logging.getLogger("anaconda")
log = logging
import isys

# these arches can have their /boot on DMRAID and not have their
# boot loader blow up
# XXX This needs to be functional so it can test if drives sit on particular
# controlers. -pj
dmraidBootArches = [ "i386", "x86_64" ]

def getRaidSetDisks(rs, descend=False):
    """Builds a list of disks used by a dmraid set

    rs is a block.dmraid.raidset instance
    Returns a list of parted.PedDevice instances.
    """

    if not isinstance(rs, block.dmraid.raidset):
        raise TypeError, "getRaidSetInfo needs raidset, got %s" % (rs.__type__,)

    devs = []
    for c in rs.children:
        if isinstance(c, block.dmraid.raiddev):
            dev = parted.PedDevice.get(c.device.path)
            devs.append(dev)
        elif descend and isinstance(c, block.dmraid.raidset): 
            devs += getRaidSetDisks(c)
    return devs

# This is a placeholder, because "spares" isn't implemented in
# block.dmraid.raidset yet; once dmraid has support for SNIA DDF or
# fake raid 5, I'll add it. -pj
def getRaidSetSpareDisks(rs, descend=False):
    """Builds a list of disks used as spares by a dmraid set

    rs is a block.dmraid.raidset instance
    Returns a list of parted.PedDevice instances.
    """

    if not isinstance(rs, block.dmraid.raidset):
        raise TypeError, "getRaidSetInfo needs raidset, got %s" % (rs.__type__,)

    devs = []
    if hasattr(rs, 'spares'):
        for c in rs.spares:
            if isinstance(c, block.dmraid.raiddev):
                dev = parted.PedDevice.get(c.device.path)
                devs.append(dev)
            elif descend and isinstance(c, block.dmraid.raidset): 
                devs += getRaidSetSpareDisks(c, descend)
    # children might have spares, too.
    for c in rs.children:
        if descend and isinstance(c, block.dmraid.raidset):
            devs += getRaidSetSpareDisks(c, descend)
    return devs

def getRaidSetInfo(rs):
    """Builds information about a dmraid set
    
    rs is a block.dmraid.raidset instance
    Returns a list of tuples for this raidset and its
      dependencies, in sorted order, of the form
      (raidSet, parentRaidSet, devices, level, nrDisks, totalDisks)
    """

    if not isinstance(rs, block.dmraid.raidset):
        raise TypeError, "getRaidSetInfo needs raidset, got %s" % (rs.__type__,)

    sets = []
    for c in rs.children:
        if isinstance(c, block.dmraid.raidset):
            infos = getRaidSetInfo(c)
            for info in infos:
                if info[1] is None:
                    info[1] = rs
            sets += infos

    try:
        parent = None

        devs = getRaidSetDisks(rs)
        sparedevs = getRaidSetSpareDisks(rs)

        totalDisks = len(devs) + len(sparedevs)
        nrDisks = len(devs)
        devices = devs + sparedevs

        # XXX missing some types here -pj
        dmtype2level = { 'stripe': 0, 'mirror': 1, }
        level = dmtype2level[rs.dmtype]

        sets.append((rs, parent, devices, level, nrDisks, totalDisks))
    except:
        # something went haywire
        log.error("Exception occurred reading info for %s: %s" % \
            (repr(rs), (sys.exc_type, ))) # XXX PJFIX sys.exc_info)))
        raise

    return sets

def scanForRaid(drives):
    """Scans for dmraid devices on drives.

    drives is a list of device names.
    Returns a list of (raidSet, parentRaidSet, devices, level, totalDisks)
      tuples.
    """

    Sets = {}
    Devices = {}

    probeDrives = []
    for d in drives:
        dp = "/tmp/" + d
        isys.makeDevInode(d, dp)
        probeDrives.append(dp)
    
    dmsets = block.get_raidsets(probeDrives)
    for dmset in dmsets:
        infos = getRaidSetInfo(dmset)

        for info in infos:
            (rs, parent, devices, level, nrDisks, totalDisks) = info


def startAllRaid(driveList):
    """Do a raid start on raid devices and return a list like scanForRaid."""
    rc = []