Tests: isolation check moved to the pytest_sessionstart().
This change eliminates the need for some classes to run Unit one more time before running tests.
This commit is contained in:
@@ -17,6 +17,7 @@ import pytest
|
|||||||
from unit.check.go import check_go
|
from unit.check.go import check_go
|
||||||
from unit.check.node import check_node
|
from unit.check.node import check_node
|
||||||
from unit.check.tls import check_openssl
|
from unit.check.tls import check_openssl
|
||||||
|
from unit.check.isolation import check_isolation
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
from unit.utils import public_dir
|
from unit.utils import public_dir
|
||||||
from unit.utils import waitforfiles
|
from unit.utils import waitforfiles
|
||||||
@@ -123,6 +124,7 @@ def pytest_sessionstart(session):
|
|||||||
option.available = {'modules': {}, 'features': {}}
|
option.available = {'modules': {}, 'features': {}}
|
||||||
|
|
||||||
unit = unit_run()
|
unit = unit_run()
|
||||||
|
option.temp_dir = unit['temp_dir']
|
||||||
|
|
||||||
# read unit.log
|
# read unit.log
|
||||||
|
|
||||||
@@ -161,6 +163,8 @@ def pytest_sessionstart(session):
|
|||||||
k: v for k, v in option.available['modules'].items() if v is not None
|
k: v for k, v in option.available['modules'].items() if v is not None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_isolation()
|
||||||
|
|
||||||
unit_stop()
|
unit_stop()
|
||||||
|
|
||||||
_check_alerts()
|
_check_alerts()
|
||||||
|
|||||||
@@ -5,31 +5,13 @@ import shutil
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from conftest import unit_run
|
|
||||||
from conftest import unit_stop
|
|
||||||
from unit.applications.lang.go import TestApplicationGo
|
from unit.applications.lang.go import TestApplicationGo
|
||||||
from unit.feature.isolation import TestFeatureIsolation
|
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
from unit.utils import getns
|
||||||
|
|
||||||
class TestGoIsolation(TestApplicationGo):
|
class TestGoIsolation(TestApplicationGo):
|
||||||
prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']}
|
prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']}
|
||||||
|
|
||||||
isolation = TestFeatureIsolation()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setup_class(cls, complete_check=True):
|
|
||||||
check = super().setup_class(complete_check=False)
|
|
||||||
|
|
||||||
unit = unit_run()
|
|
||||||
option.temp_dir = unit['temp_dir']
|
|
||||||
|
|
||||||
TestFeatureIsolation().check(option.available, unit['temp_dir'])
|
|
||||||
|
|
||||||
assert unit_stop() is None
|
|
||||||
shutil.rmtree(unit['temp_dir'])
|
|
||||||
|
|
||||||
return check if not complete_check else check()
|
|
||||||
|
|
||||||
def unpriv_creds(self):
|
def unpriv_creds(self):
|
||||||
nobody_uid = pwd.getpwnam('nobody').pw_uid
|
nobody_uid = pwd.getpwnam('nobody').pw_uid
|
||||||
|
|
||||||
@@ -219,8 +201,8 @@ class TestGoIsolation(TestApplicationGo):
|
|||||||
== option.available['features']['isolation'][ns]
|
== option.available['features']['isolation'][ns]
|
||||||
), ('%s match' % ns)
|
), ('%s match' % ns)
|
||||||
|
|
||||||
assert obj['NS']['MNT'] != self.isolation.getns('mnt'), 'mnt set'
|
assert obj['NS']['MNT'] != getns('mnt'), 'mnt set'
|
||||||
assert obj['NS']['USER'] != self.isolation.getns('user'), 'user set'
|
assert obj['NS']['USER'] != getns('user'), 'user set'
|
||||||
|
|
||||||
def test_isolation_pid(self, is_su):
|
def test_isolation_pid(self, is_su):
|
||||||
if not self.isolation_key('pid'):
|
if not self.isolation_key('pid'):
|
||||||
|
|||||||
@@ -2,30 +2,13 @@ import shutil
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from conftest import unit_run
|
|
||||||
from conftest import unit_stop
|
|
||||||
from unit.applications.lang.php import TestApplicationPHP
|
from unit.applications.lang.php import TestApplicationPHP
|
||||||
from unit.feature.isolation import TestFeatureIsolation
|
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|
||||||
class TestPHPIsolation(TestApplicationPHP):
|
class TestPHPIsolation(TestApplicationPHP):
|
||||||
prerequisites = {'modules': {'php': 'any'}, 'features': ['isolation']}
|
prerequisites = {'modules': {'php': 'any'}, 'features': ['isolation']}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setup_class(cls, complete_check=True):
|
|
||||||
check = super().setup_class(complete_check=False)
|
|
||||||
|
|
||||||
unit = unit_run()
|
|
||||||
option.temp_dir = unit['temp_dir']
|
|
||||||
|
|
||||||
TestFeatureIsolation().check(option.available, unit['temp_dir'])
|
|
||||||
|
|
||||||
assert unit_stop() is None
|
|
||||||
shutil.rmtree(unit['temp_dir'])
|
|
||||||
|
|
||||||
return check if not complete_check else check()
|
|
||||||
|
|
||||||
def test_php_isolation_rootfs(self, is_su, temp_dir):
|
def test_php_isolation_rootfs(self, is_su, temp_dir):
|
||||||
isolation_features = option.available['features']['isolation'].keys()
|
isolation_features = option.available['features']['isolation'].keys()
|
||||||
|
|
||||||
|
|||||||
@@ -2,30 +2,13 @@ import shutil
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from conftest import unit_run
|
|
||||||
from conftest import unit_stop
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.feature.isolation import TestFeatureIsolation
|
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|
||||||
class TestPythonIsolation(TestApplicationPython):
|
class TestPythonIsolation(TestApplicationPython):
|
||||||
prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']}
|
prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setup_class(cls, complete_check=True):
|
|
||||||
check = super().setup_class(complete_check=False)
|
|
||||||
|
|
||||||
unit = unit_run()
|
|
||||||
option.temp_dir = unit['temp_dir']
|
|
||||||
|
|
||||||
TestFeatureIsolation().check(option.available, unit['temp_dir'])
|
|
||||||
|
|
||||||
assert unit_stop() is None
|
|
||||||
shutil.rmtree(unit['temp_dir'])
|
|
||||||
|
|
||||||
return check if not complete_check else check()
|
|
||||||
|
|
||||||
def test_python_isolation_rootfs(self, is_su, temp_dir):
|
def test_python_isolation_rootfs(self, is_su, temp_dir):
|
||||||
isolation_features = option.available['features']['isolation'].keys()
|
isolation_features = option.available['features']['isolation'].keys()
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from unit.applications.lang.python import TestApplicationPython
|
from unit.applications.lang.python import TestApplicationPython
|
||||||
from unit.feature.isolation import TestFeatureIsolation
|
|
||||||
|
|
||||||
|
|
||||||
class TestPythonIsolation(TestApplicationPython):
|
class TestPythonIsolation(TestApplicationPython):
|
||||||
|
|||||||
@@ -3,30 +3,13 @@ import shutil
|
|||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from conftest import unit_run
|
|
||||||
from conftest import unit_stop
|
|
||||||
from unit.applications.lang.ruby import TestApplicationRuby
|
from unit.applications.lang.ruby import TestApplicationRuby
|
||||||
from unit.feature.isolation import TestFeatureIsolation
|
|
||||||
from unit.option import option
|
from unit.option import option
|
||||||
|
|
||||||
|
|
||||||
class TestRubyIsolation(TestApplicationRuby):
|
class TestRubyIsolation(TestApplicationRuby):
|
||||||
prerequisites = {'modules': {'ruby': 'any'}, 'features': ['isolation']}
|
prerequisites = {'modules': {'ruby': 'any'}, 'features': ['isolation']}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setup_class(cls, complete_check=True):
|
|
||||||
check = super().setup_class(complete_check=False)
|
|
||||||
|
|
||||||
unit = unit_run()
|
|
||||||
option.temp_dir = unit['temp_dir']
|
|
||||||
|
|
||||||
TestFeatureIsolation().check(option.available, unit['temp_dir'])
|
|
||||||
|
|
||||||
assert unit_stop() is None
|
|
||||||
shutil.rmtree(unit['temp_dir'])
|
|
||||||
|
|
||||||
return check if not complete_check else check()
|
|
||||||
|
|
||||||
def test_ruby_isolation_rootfs(self, is_su):
|
def test_ruby_isolation_rootfs(self, is_su):
|
||||||
isolation_features = option.available['features']['isolation'].keys()
|
isolation_features = option.available['features']['isolation'].keys()
|
||||||
|
|
||||||
|
|||||||
158
test/unit/check/isolation.py
Normal file
158
test/unit/check/isolation.py
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from unit.applications.lang.go import TestApplicationGo
|
||||||
|
from unit.applications.lang.java import TestApplicationJava
|
||||||
|
from unit.applications.lang.node import TestApplicationNode
|
||||||
|
from unit.applications.proto import TestApplicationProto
|
||||||
|
from unit.http import TestHTTP
|
||||||
|
from unit.option import option
|
||||||
|
from unit.utils import getns
|
||||||
|
|
||||||
|
allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net']
|
||||||
|
http = TestHTTP()
|
||||||
|
|
||||||
|
def check_isolation():
|
||||||
|
test_conf = {"namespaces": {"credential": True}}
|
||||||
|
available = option.available
|
||||||
|
|
||||||
|
conf = ''
|
||||||
|
if 'go' in available['modules']:
|
||||||
|
TestApplicationGo().prepare_env('empty', 'app')
|
||||||
|
|
||||||
|
conf = {
|
||||||
|
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
||||||
|
"applications": {
|
||||||
|
"empty": {
|
||||||
|
"type": "external",
|
||||||
|
"processes": {"spare": 0},
|
||||||
|
"working_directory": option.test_dir + "/go/empty",
|
||||||
|
"executable": option.temp_dir + "/go/app",
|
||||||
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
elif 'python' in available['modules']:
|
||||||
|
conf = {
|
||||||
|
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
||||||
|
"applications": {
|
||||||
|
"empty": {
|
||||||
|
"type": "python",
|
||||||
|
"processes": {"spare": 0},
|
||||||
|
"path": option.test_dir + "/python/empty",
|
||||||
|
"working_directory": option.test_dir + "/python/empty",
|
||||||
|
"module": "wsgi",
|
||||||
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
elif 'php' in available['modules']:
|
||||||
|
conf = {
|
||||||
|
"listeners": {"*:7080": {"pass": "applications/phpinfo"}},
|
||||||
|
"applications": {
|
||||||
|
"phpinfo": {
|
||||||
|
"type": "php",
|
||||||
|
"processes": {"spare": 0},
|
||||||
|
"root": option.test_dir + "/php/phpinfo",
|
||||||
|
"working_directory": option.test_dir + "/php/phpinfo",
|
||||||
|
"index": "index.php",
|
||||||
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
elif 'ruby' in available['modules']:
|
||||||
|
conf = {
|
||||||
|
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
||||||
|
"applications": {
|
||||||
|
"empty": {
|
||||||
|
"type": "ruby",
|
||||||
|
"processes": {"spare": 0},
|
||||||
|
"working_directory": option.test_dir + "/ruby/empty",
|
||||||
|
"script": option.test_dir + "/ruby/empty/config.ru",
|
||||||
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
elif 'java' in available['modules']:
|
||||||
|
TestApplicationJava().prepare_env('empty')
|
||||||
|
|
||||||
|
conf = {
|
||||||
|
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
||||||
|
"applications": {
|
||||||
|
"empty": {
|
||||||
|
"unit_jars": option.current_dir + "/build",
|
||||||
|
"type": "java",
|
||||||
|
"processes": {"spare": 0},
|
||||||
|
"working_directory": option.test_dir + "/java/empty/",
|
||||||
|
"webapp": option.temp_dir + "/java",
|
||||||
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
elif 'node' in available['modules']:
|
||||||
|
TestApplicationNode().prepare_env('basic')
|
||||||
|
|
||||||
|
conf = {
|
||||||
|
"listeners": {"*:7080": {"pass": "applications/basic"}},
|
||||||
|
"applications": {
|
||||||
|
"basic": {
|
||||||
|
"type": "external",
|
||||||
|
"processes": {"spare": 0},
|
||||||
|
"working_directory": option.temp_dir + "/node",
|
||||||
|
"executable": "app.js",
|
||||||
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
elif 'perl' in available['modules']:
|
||||||
|
conf = {
|
||||||
|
"listeners": {"*:7080": {"pass": "applications/body_empty"}},
|
||||||
|
"applications": {
|
||||||
|
"body_empty": {
|
||||||
|
"type": "perl",
|
||||||
|
"processes": {"spare": 0},
|
||||||
|
"working_directory": option.test_dir
|
||||||
|
+ "/perl/body_empty",
|
||||||
|
"script": option.test_dir + "/perl/body_empty/psgi.pl",
|
||||||
|
"isolation": {"namespaces": {"credential": True}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
resp = http.put(
|
||||||
|
url='/config',
|
||||||
|
sock_type='unix',
|
||||||
|
addr=option.temp_dir + '/control.unit.sock',
|
||||||
|
body=json.dumps(conf),
|
||||||
|
)
|
||||||
|
|
||||||
|
if 'success' not in resp:
|
||||||
|
return
|
||||||
|
|
||||||
|
userns = getns('user')
|
||||||
|
if not userns:
|
||||||
|
return
|
||||||
|
|
||||||
|
available['features']['isolation'] = {'user': userns}
|
||||||
|
|
||||||
|
unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone'
|
||||||
|
if os.path.exists(unp_clone_path):
|
||||||
|
with open(unp_clone_path, 'r') as f:
|
||||||
|
if str(f.read()).rstrip() == '1':
|
||||||
|
available['features']['isolation'][
|
||||||
|
'unprivileged_userns_clone'
|
||||||
|
] = True
|
||||||
|
|
||||||
|
for ns in allns:
|
||||||
|
ns_value = getns(ns)
|
||||||
|
if ns_value:
|
||||||
|
available['features']['isolation'][ns] = ns_value
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
from unit.applications.lang.go import TestApplicationGo
|
|
||||||
from unit.applications.lang.java import TestApplicationJava
|
|
||||||
from unit.applications.lang.node import TestApplicationNode
|
|
||||||
from unit.applications.proto import TestApplicationProto
|
|
||||||
from unit.option import option
|
|
||||||
|
|
||||||
|
|
||||||
class TestFeatureIsolation(TestApplicationProto):
|
|
||||||
allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net']
|
|
||||||
|
|
||||||
def check(self, available, temp_dir):
|
|
||||||
test_conf = {"namespaces": {"credential": True}}
|
|
||||||
|
|
||||||
conf = ''
|
|
||||||
if 'go' in available['modules']:
|
|
||||||
TestApplicationGo().prepare_env('empty', 'app')
|
|
||||||
|
|
||||||
conf = {
|
|
||||||
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
|
||||||
"applications": {
|
|
||||||
"empty": {
|
|
||||||
"type": "external",
|
|
||||||
"processes": {"spare": 0},
|
|
||||||
"working_directory": option.test_dir + "/go/empty",
|
|
||||||
"executable": option.temp_dir + "/go/app",
|
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'python' in available['modules']:
|
|
||||||
conf = {
|
|
||||||
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
|
||||||
"applications": {
|
|
||||||
"empty": {
|
|
||||||
"type": "python",
|
|
||||||
"processes": {"spare": 0},
|
|
||||||
"path": option.test_dir + "/python/empty",
|
|
||||||
"working_directory": option.test_dir + "/python/empty",
|
|
||||||
"module": "wsgi",
|
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'php' in available['modules']:
|
|
||||||
conf = {
|
|
||||||
"listeners": {"*:7080": {"pass": "applications/phpinfo"}},
|
|
||||||
"applications": {
|
|
||||||
"phpinfo": {
|
|
||||||
"type": "php",
|
|
||||||
"processes": {"spare": 0},
|
|
||||||
"root": option.test_dir + "/php/phpinfo",
|
|
||||||
"working_directory": option.test_dir + "/php/phpinfo",
|
|
||||||
"index": "index.php",
|
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'ruby' in available['modules']:
|
|
||||||
conf = {
|
|
||||||
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
|
||||||
"applications": {
|
|
||||||
"empty": {
|
|
||||||
"type": "ruby",
|
|
||||||
"processes": {"spare": 0},
|
|
||||||
"working_directory": option.test_dir + "/ruby/empty",
|
|
||||||
"script": option.test_dir + "/ruby/empty/config.ru",
|
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'java' in available['modules']:
|
|
||||||
TestApplicationJava().prepare_env('empty')
|
|
||||||
|
|
||||||
conf = {
|
|
||||||
"listeners": {"*:7080": {"pass": "applications/empty"}},
|
|
||||||
"applications": {
|
|
||||||
"empty": {
|
|
||||||
"unit_jars": option.current_dir + "/build",
|
|
||||||
"type": "java",
|
|
||||||
"processes": {"spare": 0},
|
|
||||||
"working_directory": option.test_dir + "/java/empty/",
|
|
||||||
"webapp": option.temp_dir + "/java",
|
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'node' in available['modules']:
|
|
||||||
TestApplicationNode().prepare_env('basic')
|
|
||||||
|
|
||||||
conf = {
|
|
||||||
"listeners": {"*:7080": {"pass": "applications/basic"}},
|
|
||||||
"applications": {
|
|
||||||
"basic": {
|
|
||||||
"type": "external",
|
|
||||||
"processes": {"spare": 0},
|
|
||||||
"working_directory": option.temp_dir + "/node",
|
|
||||||
"executable": "app.js",
|
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
elif 'perl' in available['modules']:
|
|
||||||
conf = {
|
|
||||||
"listeners": {"*:7080": {"pass": "applications/body_empty"}},
|
|
||||||
"applications": {
|
|
||||||
"body_empty": {
|
|
||||||
"type": "perl",
|
|
||||||
"processes": {"spare": 0},
|
|
||||||
"working_directory": option.test_dir
|
|
||||||
+ "/perl/body_empty",
|
|
||||||
"script": option.test_dir + "/perl/body_empty/psgi.pl",
|
|
||||||
"isolation": {"namespaces": {"credential": True}},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
else:
|
|
||||||
return
|
|
||||||
|
|
||||||
if 'success' not in self.conf(conf):
|
|
||||||
return
|
|
||||||
|
|
||||||
userns = self.getns('user')
|
|
||||||
if not userns:
|
|
||||||
return
|
|
||||||
|
|
||||||
available['features']['isolation'] = {'user': userns}
|
|
||||||
|
|
||||||
unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone'
|
|
||||||
if os.path.exists(unp_clone_path):
|
|
||||||
with open(unp_clone_path, 'r') as f:
|
|
||||||
if str(f.read()).rstrip() == '1':
|
|
||||||
available['features']['isolation'][
|
|
||||||
'unprivileged_userns_clone'
|
|
||||||
] = True
|
|
||||||
|
|
||||||
for ns in self.allns:
|
|
||||||
ns_value = self.getns(ns)
|
|
||||||
if ns_value:
|
|
||||||
available['features']['isolation'][ns] = ns_value
|
|
||||||
|
|
||||||
def getns(self, nstype):
|
|
||||||
# read namespace id from symlink file:
|
|
||||||
# it points to: '<nstype>:[<ns id>]'
|
|
||||||
# # eg.: 'pid:[4026531836]'
|
|
||||||
nspath = '/proc/self/ns/' + nstype
|
|
||||||
data = None
|
|
||||||
|
|
||||||
if os.path.exists(nspath):
|
|
||||||
data = int(os.readlink(nspath)[len(nstype) + 2 : -1])
|
|
||||||
|
|
||||||
return data
|
|
||||||
@@ -4,8 +4,7 @@ from unit.option import option
|
|||||||
|
|
||||||
class TestUnit():
|
class TestUnit():
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_class(cls, complete_check=True):
|
def setup_class(cls):
|
||||||
def check():
|
|
||||||
missed = []
|
missed = []
|
||||||
|
|
||||||
# check modules
|
# check modules
|
||||||
@@ -35,8 +34,3 @@ class TestUnit():
|
|||||||
|
|
||||||
if missed:
|
if missed:
|
||||||
pytest.skip(', '.join(missed) + ' feature(s) not supported')
|
pytest.skip(', '.join(missed) + ' feature(s) not supported')
|
||||||
|
|
||||||
if complete_check:
|
|
||||||
check()
|
|
||||||
else:
|
|
||||||
return check
|
|
||||||
|
|||||||
@@ -48,3 +48,15 @@ def waitforsocket(port):
|
|||||||
|
|
||||||
pytest.fail('Can\'t connect to the 127.0.0.1:' + port)
|
pytest.fail('Can\'t connect to the 127.0.0.1:' + port)
|
||||||
|
|
||||||
|
|
||||||
|
def getns(nstype):
|
||||||
|
# read namespace id from symlink file:
|
||||||
|
# it points to: '<nstype>:[<ns id>]'
|
||||||
|
# # eg.: 'pid:[4026531836]'
|
||||||
|
nspath = '/proc/self/ns/' + nstype
|
||||||
|
data = None
|
||||||
|
|
||||||
|
if os.path.exists(nspath):
|
||||||
|
data = int(os.readlink(nspath)[len(nstype) + 2 : -1])
|
||||||
|
|
||||||
|
return data
|
||||||
|
|||||||
Reference in New Issue
Block a user