@@ -20,15 +20,20 @@ def __init__(self, addr, port):
20
20
21
21
@property
22
22
def is_reachable (self ):
23
- if not self ._addr ._host .exists ('nc' ):
23
+ """Return if port is reachable"""
24
+ if not self ._addr ._host .exists ("nc" ):
25
+ if self ._addr .namespace :
26
+ # in this case cannot use namespace
27
+ raise NotImplementedError (
28
+ "nc command not available, namespace cannot be used" )
24
29
# Fallback to bash if netcat is not available
25
30
return self ._addr .run_expect (
26
31
[0 , 1 , 124 ],
27
32
"timeout 1 bash -c 'cat < /dev/null > /dev/tcp/%s/%s'" ,
28
33
self ._addr .name , self ._port ).rc == 0
29
34
30
- return self ._addr .run (
31
- "nc -w 1 -z %s %s" , self ._addr .name , self ._port ).rc == 0
35
+ return self ._addr .run ("{}nc -w 1 -z {} {}" . format ( self . _addr . _prefix ,
36
+ self ._addr .name , self ._port ) ).rc == 0
32
37
33
38
34
39
class Addr (Module ):
@@ -47,17 +52,54 @@ class Addr(Module):
47
52
True
48
53
>>> google.port(666).is_reachable
49
54
False
50
- """
51
55
52
- def __init__ (self , name ):
56
+ Can also be use within a network namespace_.
57
+
58
+ >>> localhost = host.addr("localhost", "ns1")
59
+ >>> localhost.is_resolvable
60
+ True
61
+
62
+ Network namespaces can only be used if ip_ command is available
63
+ because in this case, the module use ip-netns_ as command prefix.
64
+ In the other case, it will raise NotImplementedError.
65
+
66
+ .. _namespace: https://man7.org/linux/man-pages/man7/namespaces.7.html
67
+ .. _ip: https://man7.org/linux/man-pages/man8/ip.8.html
68
+ .. _ip-netns: https://man7.org/linux/man-pages/man8/ip-netns.8.html
69
+ """
70
+ def __init__ (self , name , namespace = None ):
53
71
self ._name = name
72
+ self ._namespace = namespace
73
+ if self .namespace and not self ._host .exists ("ip" ):
74
+ raise NotImplementedError (
75
+ "ip command not available, namespace cannot be used" )
54
76
super ().__init__ ()
55
77
56
78
@property
57
79
def name (self ):
58
80
"""Return host name"""
59
81
return self ._name
60
82
83
+ @property
84
+ def namespace (self ):
85
+ """Return network namespace"""
86
+ return self ._namespace
87
+
88
+ @property
89
+ def _prefix (self ):
90
+ """Return the prefix to use for commands"""
91
+ prefix = ""
92
+ if self .namespace :
93
+ prefix = "ip netns exec %s " % self .namespace
94
+ return prefix
95
+
96
+ @property
97
+ def namespace_exists (self ):
98
+ """Test if the network namespace exists"""
99
+ # could use ip netns list instead
100
+ return self .namespace and self .run_test ("test -e /var/run/netns/%s" ,
101
+ self .namespace ).rc == 0
102
+
61
103
@property
62
104
def is_resolvable (self ):
63
105
"""Return if address is resolvable"""
@@ -66,8 +108,8 @@ def is_resolvable(self):
66
108
@property
67
109
def is_reachable (self ):
68
110
"""Return if address is reachable"""
69
- return self .run_expect ([0 , 1 , 2 ],
70
- "ping -W 1 -c 1 %s" , self .name ).rc == 0
111
+ return self .run_expect ([0 , 1 , 2 ], "{}ping -W 1 -c 1 {}" . format (
112
+ self . _prefix , self .name ) ).rc == 0
71
113
72
114
@property
73
115
def ip_addresses (self ):
@@ -92,6 +134,7 @@ def __repr__(self):
92
134
return "<addr %s>" % (self .name ,)
93
135
94
136
def _resolve (self , method ):
95
- result = self .run_expect ([0 , 2 ], "getent %s %s" , method , self .name )
137
+ result = self .run_expect ([0 , 1 , 2 ], "{}getent {} {}" .format (
138
+ self ._prefix , method , self .name ))
96
139
lines = result .stdout .splitlines ()
97
140
return list (set (line .split ()[0 ] for line in lines ))
0 commit comments