24
24
import VirtualDevice
25
from XMLBuilderDomain import _xml_property
25
26
from virtinst import _virtinst as _
28
def _countMACaddr(vms, searchmac):
35
for mac in ctx.xpathEval("/domain/devices/interface/mac"):
36
macaddr = mac.xpathEval("attribute::address")[0].content
37
if macaddr and _util.compareMAC(searchmac, macaddr) == 0:
44
count += _util.get_xml_path(xml, func=count_cb)
27
47
class VirtualNetworkInterface(VirtualDevice.VirtualDevice):
29
49
_virtual_device_type = VirtualDevice.VirtualDevice.VIRTUAL_DEV_NET
31
TYPE_BRIDGE = "bridge"
32
TYPE_VIRTUAL = "network"
34
network_types = [TYPE_BRIDGE, TYPE_VIRTUAL, TYPE_USER]
51
TYPE_BRIDGE = "bridge"
52
TYPE_VIRTUAL = "network"
54
TYPE_ETHERNET = "ethernet"
55
network_types = [TYPE_BRIDGE, TYPE_VIRTUAL, TYPE_USER, TYPE_ETHERNET]
36
57
def get_network_type_desc(net_type):
38
59
Return human readable description for passed network type
61
desc = net_type.capitalize()
42
63
if net_type == VirtualNetworkInterface.TYPE_BRIDGE:
43
64
desc = _("Shared physical device")
44
elif net_type == VirtualNetworkInterface.TYPE_VIRTUAL:
65
elif net_type == VirtualNetworkInterface.TYPE_VIRTUAL:
45
66
desc = _("Virtual networking")
46
67
elif net_type == VirtualNetworkInterface.TYPE_USER:
47
68
desc = _("Usermode networking")
49
raise ValueError(_("Unknown network type '%s'") % net_type)
52
71
get_network_type_desc = staticmethod(get_network_type_desc)
54
73
def __init__(self, macaddr=None, type=TYPE_BRIDGE, bridge=None,
55
network=None, model=None, conn=None):
56
VirtualDevice.VirtualDevice.__init__(self, conn)
74
network=None, model=None, conn=None,
75
parsexml=None, parsexmlnode=None, caps=None):
76
VirtualDevice.VirtualDevice.__init__(self, conn, parsexml,
58
79
self._network = None
59
81
self._macaddr = None
84
self._target_dev = None
85
self._source_dev = None
87
# Generate _random_mac
88
self._random_mac = None
89
self._default_bridge = None
63
95
self.macaddr = macaddr
68
100
if self.type == self.TYPE_VIRTUAL:
69
101
if network is None:
70
raise ValueError, _("A network name was not provided")
102
raise ValueError(_("A network name was not provided"))
104
def _generate_default_bridge(self):
105
if not self._default_bridge:
106
self._default_bridge = _util.default_bridge2(self.conn)
107
return self._default_bridge
109
def _generate_random_mac(self):
110
if self.conn and not self._random_mac:
112
for ignore in range(256):
113
self._random_mac = _util.randomMAC(self.conn.getType().lower())
114
ret = self.is_conflict_net(self.conn, self._random_mac)
115
if ret[1] is not None:
121
logging.debug("Failed to generate non-conflicting MAC")
122
return self._random_mac
124
def get_source(self):
126
Convenince function, try to return the relevant <source> value
127
per the network type.
129
if self.type == self.TYPE_VIRTUAL:
131
if self.type == self.TYPE_BRIDGE:
133
if self.type == self.TYPE_ETHERNET:
134
return self.source_dev
135
if self.type == self.TYPE_USER:
137
return self.network or self.bridge or self.source_dev
72
139
def get_type(self):
74
141
def set_type(self, val):
75
142
if val not in self.network_types:
76
raise ValueError, _("Unknown network type %s") % val
143
raise ValueError(_("Unknown network type %s") % val)
78
type = property(get_type, set_type)
145
type = _xml_property(get_type, set_type,
80
148
def get_macaddr(self):
149
if not self._macaddr:
150
return self._generate_random_mac()
81
151
return self._macaddr
82
152
def set_macaddr(self, val):
83
153
_util.validate_macaddr(val)
84
154
self._macaddr = val
85
macaddr = property(get_macaddr, set_macaddr)
155
macaddr = _xml_property(get_macaddr, set_macaddr,
156
xpath="./mac/@address")
87
158
def get_network(self):
88
159
return self._network
89
160
def set_network(self, newnet):
90
161
def _is_net_active(netobj):
91
"""Apparently the 'info' command was never hooked up for
92
libvirt virNetwork python apis."""
162
# Apparently the 'info' command was never hooked up for
163
# libvirt virNetwork python apis.
95
166
return self.conn.listNetworks().count(netobj.name())
105
176
"started.") % newnet)
107
178
self._network = newnet
108
network = property(get_network, set_network)
110
def is_conflict_net(self, conn):
111
"""is_conflict_net: determines if mac conflicts with others in system
113
returns a two element tuple:
114
first element is True if fatal collision occured
115
second element is a string description of the collision.
116
Non fatal collisions (mac addr collides with inactive guest) will
117
return (False, "description of collision")"""
118
if self.macaddr is None:
179
network = _xml_property(get_network, set_network,
180
xpath="./source/@network")
182
def get_bridge(self):
183
if not self._bridge and self.type == self.TYPE_BRIDGE:
184
return self._generate_default_bridge()
186
def set_bridge(self, val):
188
bridge = _xml_property(get_bridge, set_bridge,
189
xpath="./source/@bridge")
193
def set_model(self, val):
195
model = _xml_property(get_model, set_model,
196
xpath="./model/@type")
198
def get_target_dev(self):
199
return self._target_dev
200
def set_target_dev(self, val):
201
self._target_dev = val
202
target_dev = _xml_property(get_target_dev, set_target_dev,
203
xpath="./target/@dev")
205
def get_source_dev(self):
206
return self._source_dev
207
def set_source_dev(self, val):
208
self._source_dev = val
209
source_dev = _xml_property(get_source_dev, set_source_dev,
210
xpath="./source/@dev")
212
def is_conflict_net(self, conn, mac=None):
214
is_conflict_net: determines if mac conflicts with others in system
216
returns a two element tuple:
217
first element is True if fatal collision occured
218
second element is a string description of the collision.
220
Non fatal collisions (mac addr collides with inactive guest) will
221
return (False, "description of collision")
223
mac = mac or self.macaddr
227
# Not supported for remote connections yet
228
if self._is_remote():
119
229
return (False, None)
121
231
vms, inactive_vm = _util.fetch_all_guests(conn)
123
233
# get the Host's NIC MACaddress
124
234
hostdevs = _util.get_host_network_devices()
126
if self.countMACaddr(vms) > 0:
127
return (True, _("The MAC address you entered is already in use by another active virtual machine."))
128
for (dummy, dummy, dummy, dummy, host_macaddr) in hostdevs:
236
if _countMACaddr(vms, mac) > 0:
237
return (True, _("The MAC address you entered is already in use "
238
"by another active virtual machine."))
241
host_macaddr = dev[4]
129
242
if self.macaddr.upper() == host_macaddr.upper():
130
return (True, _("The MAC address you entered conflicts with a device on the physical host."))
131
if self.countMACaddr(inactive_vm) > 0:
132
return (False, _("The MAC address you entered is already in use by another inactive virtual machine."))
243
return (True, _("The MAC address you entered conflicts with "
244
"a device on the physical host."))
246
if _countMACaddr(inactive_vm, mac) > 0:
247
return (False, _("The MAC address you entered is already in use "
248
"by another inactive virtual machine."))
133
250
return (False, None)
135
252
def setup_dev(self, conn=None, meter=None):
140
257
DEPRECATED: Please use setup_dev instead
259
# Access self.macaddr to generate a random one
260
if not self.conn and conn:
145
if self.macaddr is None:
147
self.macaddr = _util.randomMAC(type=conn.getType().lower())
148
if self.is_conflict_net(conn)[1] is not None:
153
266
ret, msg = self.is_conflict_net(conn)
154
267
if msg is not None:
158
271
raise RuntimeError(msg)
160
if not self.bridge and self.type == "bridge":
161
self.bridge = _util.default_bridge2(self.conn)
163
def get_xml_config(self):
273
def _get_xml_config(self):
166
277
if self.type == self.TYPE_BRIDGE:
167
src_xml = " <source bridge='%s'/>\n" % self.bridge
278
src_xml = " <source bridge='%s'/>\n" % self.bridge
168
279
elif self.type == self.TYPE_VIRTUAL:
169
src_xml = " <source network='%s'/>\n" % self.network
280
src_xml = " <source network='%s'/>\n" % self.network
281
elif self.type == self.TYPE_ETHERNET and self.source_dev:
282
src_xml = " <source dev='%s'/>\n" % self.source_dev
172
model_xml = " <model type='%s'/>\n" % self.model
174
return " <interface type='%s'>\n" % self.type + \
176
" <mac address='%s'/>\n" % self.macaddr + \
180
def countMACaddr(self, vms):
187
for mac in ctx.xpathEval("/domain/devices/interface/mac"):
188
macaddr = mac.xpathEval("attribute::address")[0].content
189
if macaddr and _util.compareMAC(self.macaddr, macaddr) == 0:
196
count += _util.get_xml_path(xml, func = count_cb)
285
model_xml = " <model type='%s'/>\n" % self.model
288
target_xml = " <target dev='%s'/>\n" % self.target_dev
290
xml = " <interface type='%s'>\n" % self.type
292
xml += " <mac address='%s'/>\n" % self.macaddr
295
xml += " </interface>"
199
298
# Back compat class to avoid ABI break
200
299
class XenNetworkInterface(VirtualNetworkInterface):