2
2
import contextlib
3
3
import json
4
4
import subprocess
5
+ import time
5
6
6
7
import attr
7
8
10
11
from ..step import step
11
12
from ..util .helper import processwrapper
12
13
from ..util .managedfile import ManagedFile
14
+ from ..util .timeout import Timeout
13
15
from ..resource .common import NetworkResource
14
16
15
17
@@ -25,6 +27,14 @@ def __attrs_post_init__(self):
25
27
self ._record_handle = None
26
28
self ._replay_handle = None
27
29
30
+ def on_activate (self ):
31
+ self ._set_interface ("up" )
32
+ self ._wait_state ("up" )
33
+
34
+ def on_deactivate (self ):
35
+ self ._set_interface ("down" )
36
+ self ._wait_state ("down" )
37
+
28
38
def _wrap_command (self , args ):
29
39
wrapper = ["sudo" , "labgrid-raw-interface" ]
30
40
@@ -35,6 +45,126 @@ def _wrap_command(self, args):
35
45
# keep wrapper and args as-is
36
46
return wrapper + args
37
47
48
+ @step (args = ["state" ])
49
+ def _set_interface (self , state ):
50
+ """Set interface to given state."""
51
+ cmd = ["ip" , self .iface .ifname , state ]
52
+ cmd = self ._wrap_command (cmd )
53
+ subprocess .check_call (cmd )
54
+
55
+ @Driver .check_active
56
+ def set_interface_up (self ):
57
+ """Set bound interface up."""
58
+ self ._set_interface ("up" )
59
+
60
+ @Driver .check_active
61
+ def set_interface_down (self ):
62
+ """Set bound interface down."""
63
+ self ._set_interface ("down" )
64
+
65
+ def _get_state (self ):
66
+ """Returns the bound interface's operstate."""
67
+ if_state = self .iface .extra .get ("state" )
68
+ if if_state :
69
+ return if_state
70
+
71
+ cmd = self .iface .command_prefix + ["cat" , f"/sys/class/net/{ self .iface .ifname } /operstate" ]
72
+ output = processwrapper .check_output (cmd ).decode ("ascii" )
73
+ if_state = output .strip ()
74
+ return if_state
75
+
76
+ @Driver .check_active
77
+ def get_state (self ):
78
+ """Returns the bound interface's operstate."""
79
+ return self ._get_state ()
80
+
81
+ @step (title = "wait_state" , args = ["expected_state" , "timeout" ])
82
+ def _wait_state (self , expected_state , timeout = 60 ):
83
+ """Wait until the expected state is reached or the timeout expires."""
84
+ timeout = Timeout (float (timeout ))
85
+
86
+ while True :
87
+ if self ._get_state () == expected_state :
88
+ return
89
+ if timeout .expired :
90
+ raise TimeoutError (
91
+ f"exported interface { self .iface .ifname } did not go { expected_state } within { timeout .timeout } seconds"
92
+ )
93
+ time .sleep (1 )
94
+
95
+ @Driver .check_active
96
+ def wait_state (self , expected_state , timeout = 60 ):
97
+ """Wait until the expected state is reached or the timeout expires."""
98
+ self ._wait_state (expected_state , timeout = timeout )
99
+
100
+ @Driver .check_active
101
+ def get_ethtool_settings (self ):
102
+ """
103
+ Returns settings via ethtool of the bound network interface resource.
104
+ """
105
+ cmd = self .iface .command_prefix + ["ethtool" , "--json" , self .iface .ifname ]
106
+ output = subprocess .check_output (cmd , encoding = "utf-8" )
107
+ return json .loads (output )[0 ]
108
+
109
+ @Driver .check_active
110
+ @step (args = ["settings" ])
111
+ def ethtool_configure (self , ** settings ):
112
+ """
113
+ Change settings on interface.
114
+
115
+ Supported settings are described in ethtool(8) --change (use "_" instead of "-").
116
+ """
117
+ cmd = ["ethtool" , "change" , self .iface .ifname ]
118
+ cmd += [item .replace ("_" , "-" ) for pair in settings .items () for item in pair ]
119
+ cmd = self ._wrap_command (cmd )
120
+ subprocess .check_call (cmd )
121
+
122
+ @Driver .check_active
123
+ def get_ethtool_eee_settings (self ):
124
+ """
125
+ Returns Energy-Efficient Ethernet settings via ethtool of the bound network interface
126
+ resource.
127
+ """
128
+ cmd = self .iface .command_prefix + ["ethtool" , "--show-eee" , "--json" , self .iface .ifname ]
129
+ output = subprocess .check_output (cmd , encoding = "utf-8" )
130
+ return json .loads (output )[0 ]
131
+
132
+ @Driver .check_active
133
+ @step (args = ["settings" ])
134
+ def ethtool_configure_eee (self , ** settings ):
135
+ """
136
+ Change Energy-Efficient Ethernet settings via ethtool of the bound network interface
137
+ resource.
138
+
139
+ Supported settings are described in ethtool(8) --set-eee (use "_" instead of "-").
140
+ """
141
+ cmd = ["ethtool" , "set-eee" , self .iface .ifname ]
142
+ cmd += [item .replace ("_" , "-" ) for pair in settings .items () for item in pair ]
143
+ cmd = self ._wrap_command (cmd )
144
+ subprocess .check_call (cmd )
145
+
146
+ @Driver .check_active
147
+ def get_ethtool_pause_settings (self ):
148
+ """
149
+ Returns pause parameters via ethtool of the bound network interface resource.
150
+ """
151
+ cmd = self .iface .command_prefix + ["ethtool" , "--json" , "--show-pause" , self .iface .ifname ]
152
+ output = subprocess .check_output (cmd , encoding = "utf-8" )
153
+ return json .loads (output )[0 ]
154
+
155
+ @Driver .check_active
156
+ @step (args = ["settings" ])
157
+ def ethtool_configure_pause (self , ** settings ):
158
+ """
159
+ Change pause parameters via ethtool of the bound network interface resource.
160
+
161
+ Supported settings are described in ethtool(8) --pause
162
+ """
163
+ cmd = ["ethtool" , "pause" , self .iface .ifname ]
164
+ cmd += [item for pair in settings .items () for item in pair ]
165
+ cmd = self ._wrap_command (cmd )
166
+ subprocess .check_call (cmd )
167
+
38
168
def _stop (self , proc , * , timeout = None ):
39
169
assert proc is not None
40
170
0 commit comments