~ubuntu-branches/ubuntu/raring/virtinst/raring-proposed

« back to all changes in this revision

Viewing changes to virtinst/VirtualHostDevice.py

  • Committer: Bazaar Package Importer
  • Author(s): Guido Günther
  • Date: 2009-03-22 20:13:27 UTC
  • mto: (1.4.1 sid)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: james.westby@ubuntu.com-20090322201327-5ch3kqxe772e23zx
Tags: upstream-0.400.3
Import upstream version 0.400.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright 2009  Red Hat, Inc.
 
3
# Cole Robinson <crobinso@redhat.com>
 
4
#
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free  Software Foundation; either version 2 of the License, or
 
8
# (at your option)  any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
18
# MA 02110-1301 USA.
 
19
 
 
20
import VirtualDevice
 
21
import NodeDeviceParser
 
22
import logging
 
23
from virtinst import _virtinst as _
 
24
 
 
25
class VirtualHostDevice(VirtualDevice.VirtualDevice):
 
26
 
 
27
    def device_from_node(conn, name=None, nodedev=None):
 
28
        """
 
29
        Convert the passed libvirt node device name to a VirtualHostDevice
 
30
        instance, with proper error reporting.
 
31
 
 
32
        @param conn: libvirt.virConnect instance to perform the lookup on
 
33
        @param name: libvirt node device name to lookup
 
34
 
 
35
        @rtype: L{virtinst.VirtualHostDevice} instance
 
36
        """
 
37
 
 
38
        if not name and not nodedev:
 
39
            raise ValueError(_("'name' or 'nodedev' required."))
 
40
 
 
41
        if nodedev:
 
42
            nodeinst = nodedev
 
43
        else:
 
44
            nodeinst = NodeDeviceParser.lookupNodeName(conn, name)
 
45
 
 
46
        if isinstance(nodeinst, NodeDeviceParser.PCIDevice):
 
47
            return VirtualHostDevicePCI(conn, nodedev=nodeinst)
 
48
        elif isinstance(nodeinst, NodeDeviceParser.USBDevice):
 
49
            return VirtualHostDeviceUSB(conn, nodedev=nodeinst)
 
50
        elif isinstance(nodeinst, NodeDeviceParser.NetDevice):
 
51
            parentname = nodeinst.parent
 
52
            try:
 
53
                return VirtualHostDevice.device_from_node(conn,
 
54
                                                          name=parentname)
 
55
            except:
 
56
                logging.exception("Fetching net parent device failed.")
 
57
 
 
58
        raise ValueError(_("Node device type '%s' cannot be attached to "
 
59
                           " guest.") % nodeinst.device_type)
 
60
 
 
61
    device_from_node = staticmethod(device_from_node)
 
62
 
 
63
    def __init__(self, conn, nodedev):
 
64
        """
 
65
        @param conn: Connection the device/guest will be installed on
 
66
        @type conn: libvirt.virConnect
 
67
        @param nodedev: Optional NodeDevice instance for device being
 
68
                         attached to the guest
 
69
        @type nodedev: L{virtinst.NodeDeviceParser.NodeDevice}
 
70
        """
 
71
        VirtualDevice.VirtualDevice.__init__(self, conn)
 
72
 
 
73
        self.mode = None
 
74
        self.type = None
 
75
 
 
76
        self.managed = True
 
77
 
 
78
        self._nodedev = nodedev
 
79
 
 
80
    def _get_source_xml(self):
 
81
        raise NotImplementedError("Must be implemented in subclass")
 
82
 
 
83
    def setup(self, conn = None):
 
84
        """
 
85
        Perform DeviceDetach and DeviceReset calls if necessary
 
86
 
 
87
        @param conn: libvirt virConnect instance to use (defaults to devices
 
88
                     connection)
 
89
        """
 
90
        raise NotImplementedError
 
91
 
 
92
    def get_xml_config(self):
 
93
        xml =  ("    <hostdev mode='%s' type='%s' managed='%s'>\n" % \
 
94
                (self.mode, self.type, self.managed and "yes" or "no"))
 
95
        xml += "      <source>\n"
 
96
        xml += self._get_source_xml()
 
97
        xml += "      </source>\n"
 
98
        xml += "    </hostdev>\n"
 
99
        return xml
 
100
 
 
101
 
 
102
class VirtualHostDeviceUSB(VirtualHostDevice):
 
103
 
 
104
    def __init__(self, conn, nodedev=None):
 
105
        VirtualHostDevice.__init__(self, conn, nodedev)
 
106
 
 
107
        self.mode = "subsystem"
 
108
        self.type = "usb"
 
109
 
 
110
        self.vendor = None
 
111
        self.product = None
 
112
 
 
113
        self.bus = None
 
114
        self.device = None
 
115
 
 
116
        self._set_from_nodedev(self._nodedev)
 
117
 
 
118
 
 
119
    def _set_from_nodedev(self, nodedev):
 
120
        if not nodedev:
 
121
            return
 
122
 
 
123
        if not isinstance(nodedev, NodeDeviceParser.USBDevice):
 
124
            raise ValueError(_("'nodedev' must be a USBDevice instance."))
 
125
 
 
126
        self.vendor = nodedev.vendor_id
 
127
        self.product = nodedev.product_id
 
128
        self.bus = nodedev.bus
 
129
        self.device = nodedev.device
 
130
 
 
131
    def _get_source_xml(self):
 
132
        xml = ""
 
133
        if self.vendor and self.product:
 
134
            xml += "        <vendor id='%s'/>\n" % self.vendor
 
135
            xml += "        <product id='%s'/>\n" % self.product
 
136
        elif self.bus and self.device:
 
137
            xml += "        <address bus='%s' device='%s'/>\n" % (self.bus,
 
138
                                                                  self.device)
 
139
        else:
 
140
            raise RuntimeError(_("'vendor' and 'product', or 'bus' and "
 
141
                                 " 'device' are required."))
 
142
        return xml
 
143
 
 
144
 
 
145
    def setup(self, conn = None):
 
146
        if not conn:
 
147
            conn = self.conn
 
148
 
 
149
        # No libvirt api support for USB Detach/Reset yet
 
150
        return
 
151
 
 
152
class VirtualHostDevicePCI(VirtualHostDevice):
 
153
 
 
154
    def __init__(self, conn, nodedev=None):
 
155
        VirtualHostDevice.__init__(self, conn, nodedev)
 
156
 
 
157
        self.mode = "subsystem"
 
158
        self.type = "pci"
 
159
 
 
160
        self.domain = "0x0"
 
161
        self.bus = None
 
162
        self.slot = None
 
163
        self.function = None
 
164
 
 
165
        self._set_from_nodedev(self._nodedev)
 
166
 
 
167
 
 
168
    def _set_from_nodedev(self, nodedev):
 
169
        if not nodedev:
 
170
            return
 
171
 
 
172
        if not isinstance(nodedev, NodeDeviceParser.PCIDevice):
 
173
            raise ValueError(_("'nodedev' must be a PCIDevice instance."))
 
174
 
 
175
        self.domain = nodedev.domain
 
176
        self.bus = nodedev.bus
 
177
        self.slot = nodedev.slot
 
178
        self.function = nodedev.function
 
179
 
 
180
    def _get_source_xml(self):
 
181
        if not (self.domain and self.bus and self.slot and self.function):
 
182
            raise RuntimeError(_("'domain', 'bus', 'slot', and 'function' "
 
183
                                 "must be specified."))
 
184
 
 
185
        xml = "        <address domain='%s' bus='%s' slot='%s' function='%s'/>\n"
 
186
        return xml % (self.domain, self.bus, self.slot, self.function)
 
187
 
 
188
    def setup(self, conn = None):
 
189
        """
 
190
        Perform DeviceDetach and DeviceReset calls if necessary
 
191
 
 
192
        @param conn: libvirt virConnect instance to use (defaults to devices
 
193
                     connection)
 
194
        """
 
195
        if not conn:
 
196
            conn = self.conn
 
197
 
 
198
        if not NodeDeviceParser.is_pci_detach_capable(conn):
 
199
            return
 
200
 
 
201
        try:
 
202
            # Do this as a sanity check, so that we don't fail at domain
 
203
            # start time
 
204
            self._nodedev.deviceDetach()
 
205
            self._nodedev.deviceReset()
 
206
        except Exception, e:
 
207
            raise RuntimeError(_("Could not detach PCI device: %s" % str(e)))
 
208
 
 
209