34
34
from gns3server .utils .asyncio import monitor_process
35
35
from gns3server .utils .get_resource import get_resource
36
36
from gns3server .utils .hostname import is_rfc1123_hostname_valid
37
+ from gns3server .utils import macaddress_to_int , int_to_macaddress
37
38
38
39
from gns3server .compute .ubridge .ubridge_error import UbridgeError , UbridgeNamespaceError
39
40
from ..base_node import BaseNode
@@ -105,6 +106,7 @@ def __init__(
105
106
self ._environment = environment
106
107
self ._cid = None
107
108
self ._ethernet_adapters = []
109
+ self ._mac_address = ""
108
110
self ._temporary_directory = None
109
111
self ._telnet_servers = []
110
112
self ._vnc_process = None
@@ -130,6 +132,8 @@ def __init__(
130
132
else :
131
133
self .adapters = adapters
132
134
135
+ self .mac_address = "" # this will generate a MAC address
136
+
133
137
log .debug (
134
138
"{module}: {name} [{image}] initialized." .format (
135
139
module = self .manager .module_name , name = self .name , image = self ._image
@@ -145,6 +149,7 @@ def asdict(self):
145
149
"project_id" : self ._project .id ,
146
150
"image" : self ._image ,
147
151
"adapters" : self .adapters ,
152
+ "mac_address" : self .mac_address ,
148
153
"console" : self .console ,
149
154
"console_type" : self .console_type ,
150
155
"console_resolution" : self .console_resolution ,
@@ -190,6 +195,36 @@ def name(self, new_name):
190
195
def ethernet_adapters (self ):
191
196
return self ._ethernet_adapters
192
197
198
+ @property
199
+ def mac_address (self ):
200
+ """
201
+ Returns the MAC address for this Docker container.
202
+
203
+ :returns: adapter type (string)
204
+ """
205
+
206
+ return self ._mac_address
207
+
208
+ @mac_address .setter
209
+ def mac_address (self , mac_address ):
210
+ """
211
+ Sets the MAC address for this Docker container.
212
+
213
+ :param mac_address: MAC address
214
+ """
215
+
216
+ if not mac_address :
217
+ # use the node UUID to generate a random MAC address
218
+ self ._mac_address = "02:42:%s:%s:%s:00" % (self .id [2 :4 ], self .id [4 :6 ], self .id [6 :8 ])
219
+ else :
220
+ self ._mac_address = mac_address
221
+
222
+ log .info ('Docker container "{name}" [{id}]: MAC address changed to {mac_addr}' .format (
223
+ name = self ._name ,
224
+ id = self ._id ,
225
+ mac_addr = self ._mac_address )
226
+ )
227
+
193
228
@property
194
229
def start_command (self ):
195
230
return self ._start_command
@@ -1058,7 +1093,20 @@ async def _add_ubridge_connection(self, nio, adapter_number):
1058
1093
adapter_number = adapter_number , hostif = adapter .host_ifc
1059
1094
)
1060
1095
)
1061
- log .debug ("Move container %s adapter %s to namespace %s" , self .name , adapter .host_ifc , self ._namespace )
1096
+
1097
+ mac_address = int_to_macaddress (macaddress_to_int (self ._mac_address ) + adapter_number )
1098
+ custom_adapter = self ._get_custom_adapter_settings (adapter_number )
1099
+ custom_mac_address = custom_adapter .get ("mac_address" )
1100
+ if custom_mac_address :
1101
+ mac_address = custom_mac_address
1102
+
1103
+ try :
1104
+ await self ._ubridge_send ('docker set_mac_addr {ifc} {mac}' .format (ifc = adapter .host_ifc , mac = mac_address ))
1105
+ except UbridgeError :
1106
+ log .warning (f"Could not set MAC address { mac_address } on interface { adapter .host_ifc } " )
1107
+
1108
+
1109
+ log .debug (f"Move container { self .name } adapter { adapter .host_ifc } to namespace { self ._namespace } " )
1062
1110
try :
1063
1111
await self ._ubridge_send (
1064
1112
"docker move_to_ns {ifc} {ns} eth{adapter}" .format (
@@ -1067,6 +1115,8 @@ async def _add_ubridge_connection(self, nio, adapter_number):
1067
1115
)
1068
1116
except UbridgeError as e :
1069
1117
raise UbridgeNamespaceError (e )
1118
+ else :
1119
+ log .info (f"Created adapter { adapter_number } with MAC address { mac_address } in namespace { self ._namespace } " )
1070
1120
1071
1121
if nio :
1072
1122
await self ._connect_nio (adapter_number , nio )
0 commit comments