test_core.py 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. # -*- coding: utf-8 -*-
  2. '''
  3. :codeauthor: Erik Johnson <erik@saltstack.com>
  4. '''
  5. # Import Python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import logging
  8. import os
  9. import socket
  10. import textwrap
  11. # Import Salt Testing Libs
  12. try:
  13. import pytest
  14. except ImportError as import_error:
  15. pytest = None
  16. from tests.support.mixins import LoaderModuleMockMixin
  17. from tests.support.unit import TestCase, skipIf
  18. from tests.support.mock import (
  19. MagicMock,
  20. patch,
  21. mock_open,
  22. NO_MOCK,
  23. NO_MOCK_REASON
  24. )
  25. # Import Salt Libs
  26. import salt.utils.dns
  27. import salt.utils.files
  28. import salt.utils.network
  29. import salt.utils.platform
  30. import salt.utils.path
  31. import salt.grains.core as core
  32. # Import 3rd-party libs
  33. from salt.ext import six
  34. from salt._compat import ipaddress
  35. log = logging.getLogger(__name__)
  36. # Globals
  37. IPv4Address = ipaddress.IPv4Address
  38. IPv6Address = ipaddress.IPv6Address
  39. IP4_LOCAL = '127.0.0.1'
  40. IP4_ADD1 = '10.0.0.1'
  41. IP4_ADD2 = '10.0.0.2'
  42. IP6_LOCAL = '::1'
  43. IP6_ADD1 = '2001:4860:4860::8844'
  44. IP6_ADD2 = '2001:4860:4860::8888'
  45. IP6_ADD_SCOPE = 'fe80::6238:e0ff:fe06:3f6b%enp2s0'
  46. OS_RELEASE_DIR = os.path.join(os.path.dirname(__file__), "os-releases")
  47. SOLARIS_DIR = os.path.join(os.path.dirname(__file__), 'solaris')
  48. @skipIf(NO_MOCK, NO_MOCK_REASON)
  49. @skipIf(not pytest, False)
  50. class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
  51. '''
  52. Test cases for core grains
  53. '''
  54. def setup_loader_modules(self):
  55. return {core: {}}
  56. @patch("os.path.isfile")
  57. def test_parse_etc_os_release(self, path_isfile_mock):
  58. path_isfile_mock.side_effect = lambda x: x == "/usr/lib/os-release"
  59. with salt.utils.files.fopen(os.path.join(OS_RELEASE_DIR, "ubuntu-17.10")) as os_release_file:
  60. os_release_content = os_release_file.read()
  61. with patch("salt.utils.files.fopen", mock_open(read_data=os_release_content)):
  62. os_release = core._parse_os_release(
  63. '/etc/os-release',
  64. '/usr/lib/os-release')
  65. self.assertEqual(os_release, {
  66. "NAME": "Ubuntu",
  67. "VERSION": "17.10 (Artful Aardvark)",
  68. "ID": "ubuntu",
  69. "ID_LIKE": "debian",
  70. "PRETTY_NAME": "Ubuntu 17.10",
  71. "VERSION_ID": "17.10",
  72. "HOME_URL": "https://www.ubuntu.com/",
  73. "SUPPORT_URL": "https://help.ubuntu.com/",
  74. "BUG_REPORT_URL": "https://bugs.launchpad.net/ubuntu/",
  75. "PRIVACY_POLICY_URL": "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy",
  76. "VERSION_CODENAME": "artful",
  77. "UBUNTU_CODENAME": "artful",
  78. })
  79. def test_parse_cpe_name_wfn(self):
  80. '''
  81. Parse correct CPE_NAME data WFN formatted
  82. :return:
  83. '''
  84. for cpe, cpe_ret in [('cpe:/o:opensuse:leap:15.0',
  85. {'phase': None, 'version': '15.0', 'product': 'leap',
  86. 'vendor': 'opensuse', 'part': 'operating system'}),
  87. ('cpe:/o:vendor:product:42:beta',
  88. {'phase': 'beta', 'version': '42', 'product': 'product',
  89. 'vendor': 'vendor', 'part': 'operating system'})]:
  90. ret = core._parse_cpe_name(cpe)
  91. for key in cpe_ret:
  92. assert key in ret
  93. assert cpe_ret[key] == ret[key]
  94. def test_parse_cpe_name_v23(self):
  95. '''
  96. Parse correct CPE_NAME data v2.3 formatted
  97. :return:
  98. '''
  99. for cpe, cpe_ret in [('cpe:2.3:o:microsoft:windows_xp:5.1.601:beta:*:*:*:*:*:*',
  100. {'phase': 'beta', 'version': '5.1.601', 'product': 'windows_xp',
  101. 'vendor': 'microsoft', 'part': 'operating system'}),
  102. ('cpe:2.3:h:corellian:millenium_falcon:1.0:*:*:*:*:*:*:*',
  103. {'phase': None, 'version': '1.0', 'product': 'millenium_falcon',
  104. 'vendor': 'corellian', 'part': 'hardware'}),
  105. ('cpe:2.3:*:dark_empire:light_saber:3.0:beta:*:*:*:*:*:*',
  106. {'phase': 'beta', 'version': '3.0', 'product': 'light_saber',
  107. 'vendor': 'dark_empire', 'part': None})]:
  108. ret = core._parse_cpe_name(cpe)
  109. for key in cpe_ret:
  110. assert key in ret
  111. assert cpe_ret[key] == ret[key]
  112. def test_parse_cpe_name_broken(self):
  113. '''
  114. Parse broken CPE_NAME data
  115. :return:
  116. '''
  117. for cpe in ['cpe:broken', 'cpe:broken:in:all:ways:*:*:*:*',
  118. 'cpe:x:still:broken:123', 'who:/knows:what:is:here']:
  119. assert core._parse_cpe_name(cpe) == {}
  120. def test_missing_os_release(self):
  121. with patch('salt.utils.files.fopen', mock_open(read_data={})):
  122. os_release = core._parse_os_release('/etc/os-release', '/usr/lib/os-release')
  123. self.assertEqual(os_release, {})
  124. @skipIf(not salt.utils.platform.is_windows(), 'System is not Windows')
  125. def test__windows_platform_data(self):
  126. grains = core._windows_platform_data()
  127. keys = ['biosversion',
  128. 'osrelease',
  129. 'kernelrelease',
  130. 'motherboard',
  131. 'serialnumber',
  132. 'timezone',
  133. 'manufacturer',
  134. 'kernelversion',
  135. 'osservicepack',
  136. 'virtual',
  137. 'productname',
  138. 'osfullname',
  139. 'osmanufacturer',
  140. 'osversion',
  141. 'windowsdomain']
  142. for key in keys:
  143. self.assertIn(key, grains)
  144. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  145. def test_gnu_slash_linux_in_os_name(self):
  146. '''
  147. Test to return a list of all enabled services
  148. '''
  149. _path_exists_map = {
  150. '/proc/1/cmdline': False
  151. }
  152. _path_isfile_map = {}
  153. _cmd_run_map = {
  154. 'dpkg --print-architecture': 'amd64',
  155. }
  156. path_exists_mock = MagicMock(side_effect=lambda x: _path_exists_map[x])
  157. path_isfile_mock = MagicMock(
  158. side_effect=lambda x: _path_isfile_map.get(x, False)
  159. )
  160. cmd_run_mock = MagicMock(
  161. side_effect=lambda x: _cmd_run_map[x]
  162. )
  163. empty_mock = MagicMock(return_value={})
  164. orig_import = __import__
  165. if six.PY2:
  166. built_in = '__builtin__'
  167. else:
  168. built_in = 'builtins'
  169. def _import_mock(name, *args):
  170. if name == 'lsb_release':
  171. raise ImportError('No module named lsb_release')
  172. return orig_import(name, *args)
  173. # - Skip the first if statement
  174. # - Skip the selinux/systemd stuff (not pertinent)
  175. # - Skip the init grain compilation (not pertinent)
  176. # - Ensure that lsb_release fails to import
  177. # - Skip all the /etc/*-release stuff (not pertinent)
  178. # - Mock linux_distribution to give us the OS name that we want
  179. # - Make a bunch of functions return empty dicts, we don't care about
  180. # these grains for the purposes of this test.
  181. # - Mock the osarch
  182. distro_mock = MagicMock(return_value=('Debian GNU/Linux', '8.3', ''))
  183. with patch.object(salt.utils.platform, 'is_proxy',
  184. MagicMock(return_value=False)), \
  185. patch.object(core, '_linux_bin_exists',
  186. MagicMock(return_value=False)), \
  187. patch.object(os.path, 'exists', path_exists_mock), \
  188. patch('{0}.__import__'.format(built_in), side_effect=_import_mock), \
  189. patch.object(os.path, 'isfile', path_isfile_mock), \
  190. patch.object(core, '_parse_lsb_release', empty_mock), \
  191. patch.object(core, '_parse_os_release', empty_mock), \
  192. patch.object(core, '_parse_lsb_release', empty_mock), \
  193. patch.object(core, 'linux_distribution', distro_mock), \
  194. patch.object(core, '_linux_cpudata', empty_mock), \
  195. patch.object(core, '_linux_gpu_data', empty_mock), \
  196. patch.object(core, '_memdata', empty_mock), \
  197. patch.object(core, '_hw_data', empty_mock), \
  198. patch.object(core, '_virtual', empty_mock), \
  199. patch.object(core, '_ps', empty_mock), \
  200. patch.dict(core.__salt__, {'cmd.run': cmd_run_mock}):
  201. os_grains = core.os_data()
  202. self.assertEqual(os_grains.get('os_family'), 'Debian')
  203. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  204. def test_suse_os_from_cpe_data(self):
  205. '''
  206. Test if 'os' grain is parsed from CPE_NAME of /etc/os-release
  207. '''
  208. _path_exists_map = {
  209. '/proc/1/cmdline': False
  210. }
  211. _os_release_map = {
  212. 'NAME': 'SLES',
  213. 'VERSION': '12-SP1',
  214. 'VERSION_ID': '12.1',
  215. 'PRETTY_NAME': 'SUSE Linux Enterprise Server 12 SP1',
  216. 'ID': 'sles',
  217. 'ANSI_COLOR': '0;32',
  218. 'CPE_NAME': 'cpe:/o:suse:sles:12:sp1'
  219. }
  220. path_exists_mock = MagicMock(side_effect=lambda x: _path_exists_map[x])
  221. empty_mock = MagicMock(return_value={})
  222. osarch_mock = MagicMock(return_value="amd64")
  223. os_release_mock = MagicMock(return_value=_os_release_map)
  224. orig_import = __import__
  225. if six.PY2:
  226. built_in = '__builtin__'
  227. else:
  228. built_in = 'builtins'
  229. def _import_mock(name, *args):
  230. if name == 'lsb_release':
  231. raise ImportError('No module named lsb_release')
  232. return orig_import(name, *args)
  233. distro_mock = MagicMock(
  234. return_value=('SUSE Linux Enterprise Server ', '12', 'x86_64')
  235. )
  236. # - Skip the first if statement
  237. # - Skip the selinux/systemd stuff (not pertinent)
  238. # - Skip the init grain compilation (not pertinent)
  239. # - Ensure that lsb_release fails to import
  240. # - Skip all the /etc/*-release stuff (not pertinent)
  241. # - Mock linux_distribution to give us the OS name that we want
  242. # - Mock the osarch
  243. with patch.object(salt.utils.platform, 'is_proxy',
  244. MagicMock(return_value=False)), \
  245. patch.object(core, '_linux_bin_exists',
  246. MagicMock(return_value=False)), \
  247. patch.object(os.path, 'exists', path_exists_mock), \
  248. patch('{0}.__import__'.format(built_in),
  249. side_effect=_import_mock), \
  250. patch.object(os.path, 'isfile', MagicMock(return_value=False)), \
  251. patch.object(core, '_parse_os_release', os_release_mock), \
  252. patch.object(core, '_parse_lsb_release', empty_mock), \
  253. patch.object(core, 'linux_distribution', distro_mock), \
  254. patch.object(core, '_linux_gpu_data', empty_mock), \
  255. patch.object(core, '_hw_data', empty_mock), \
  256. patch.object(core, '_linux_cpudata', empty_mock), \
  257. patch.object(core, '_virtual', empty_mock), \
  258. patch.dict(core.__salt__, {'cmd.run': osarch_mock}):
  259. os_grains = core.os_data()
  260. self.assertEqual(os_grains.get('os_family'), 'Suse')
  261. self.assertEqual(os_grains.get('os'), 'SUSE')
  262. def _run_os_grains_tests(self, os_release_filename, os_release_map, expectation):
  263. path_isfile_mock = MagicMock(side_effect=lambda x: x in os_release_map.get('files', []))
  264. empty_mock = MagicMock(return_value={})
  265. osarch_mock = MagicMock(return_value="amd64")
  266. if os_release_filename:
  267. os_release_data = core._parse_os_release(
  268. os.path.join(OS_RELEASE_DIR, os_release_filename)
  269. )
  270. else:
  271. os_release_data = os_release_map.get('os_release_file', {})
  272. os_release_mock = MagicMock(return_value=os_release_data)
  273. orig_import = __import__
  274. if six.PY2:
  275. built_in = '__builtin__'
  276. else:
  277. built_in = 'builtins'
  278. def _import_mock(name, *args):
  279. if name == 'lsb_release':
  280. raise ImportError('No module named lsb_release')
  281. return orig_import(name, *args)
  282. suse_release_file = os_release_map.get('suse_release_file')
  283. file_contents = {'/proc/1/cmdline': ''}
  284. if suse_release_file:
  285. file_contents['/etc/SuSE-release'] = suse_release_file
  286. # - Skip the first if statement
  287. # - Skip the selinux/systemd stuff (not pertinent)
  288. # - Skip the init grain compilation (not pertinent)
  289. # - Ensure that lsb_release fails to import
  290. # - Skip all the /etc/*-release stuff (not pertinent)
  291. # - Mock linux_distribution to give us the OS name that we want
  292. # - Mock the osarch
  293. distro_mock = MagicMock(return_value=os_release_map['linux_distribution'])
  294. with patch.object(salt.utils.platform, 'is_proxy', MagicMock(return_value=False)), \
  295. patch.object(core, '_linux_bin_exists', MagicMock(return_value=False)), \
  296. patch.object(os.path, 'exists', path_isfile_mock), \
  297. patch('{0}.__import__'.format(built_in), side_effect=_import_mock), \
  298. patch.object(os.path, 'isfile', path_isfile_mock), \
  299. patch.object(core, '_parse_os_release', os_release_mock), \
  300. patch.object(core, '_parse_lsb_release', empty_mock), \
  301. patch('salt.utils.files.fopen', mock_open(read_data=file_contents)), \
  302. patch.object(core, 'linux_distribution', distro_mock), \
  303. patch.object(core, '_linux_gpu_data', empty_mock), \
  304. patch.object(core, '_linux_cpudata', empty_mock), \
  305. patch.object(core, '_virtual', empty_mock), \
  306. patch.dict(core.__salt__, {'cmd.run': osarch_mock}):
  307. os_grains = core.os_data()
  308. grains = {k: v for k, v in os_grains.items()
  309. if k in set(["os", "os_family", "osfullname", "oscodename", "osfinger",
  310. "osrelease", "osrelease_info", "osmajorrelease"])}
  311. self.assertEqual(grains, expectation)
  312. def _run_suse_os_grains_tests(self, os_release_map, expectation):
  313. os_release_map['linux_distribution'] = ('SUSE test', 'version', 'arch')
  314. expectation['os'] = 'SUSE'
  315. expectation['os_family'] = 'Suse'
  316. self._run_os_grains_tests(None, os_release_map, expectation)
  317. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  318. def test_suse_os_grains_sles11sp3(self):
  319. '''
  320. Test if OS grains are parsed correctly in SLES 11 SP3
  321. '''
  322. _os_release_map = {
  323. 'suse_release_file': textwrap.dedent('''
  324. SUSE Linux Enterprise Server 11 (x86_64)
  325. VERSION = 11
  326. PATCHLEVEL = 3
  327. '''),
  328. 'files': ["/etc/SuSE-release"],
  329. }
  330. expectation = {
  331. 'oscodename': 'SUSE Linux Enterprise Server 11 SP3',
  332. 'osfullname': "SLES",
  333. 'osrelease': '11.3',
  334. 'osrelease_info': (11, 3),
  335. 'osmajorrelease': 11,
  336. 'osfinger': 'SLES-11',
  337. }
  338. self._run_suse_os_grains_tests(_os_release_map, expectation)
  339. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  340. def test_suse_os_grains_sles11sp4(self):
  341. '''
  342. Test if OS grains are parsed correctly in SLES 11 SP4
  343. '''
  344. _os_release_map = {
  345. 'os_release_file': {
  346. 'NAME': 'SLES',
  347. 'VERSION': '11.4',
  348. 'VERSION_ID': '11.4',
  349. 'PRETTY_NAME': 'SUSE Linux Enterprise Server 11 SP4',
  350. 'ID': 'sles',
  351. 'ANSI_COLOR': '0;32',
  352. 'CPE_NAME': 'cpe:/o:suse:sles:11:4'
  353. },
  354. }
  355. expectation = {
  356. 'oscodename': 'SUSE Linux Enterprise Server 11 SP4',
  357. 'osfullname': "SLES",
  358. 'osrelease': '11.4',
  359. 'osrelease_info': (11, 4),
  360. 'osmajorrelease': 11,
  361. 'osfinger': 'SLES-11',
  362. }
  363. self._run_suse_os_grains_tests(_os_release_map, expectation)
  364. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  365. def test_suse_os_grains_sles12(self):
  366. '''
  367. Test if OS grains are parsed correctly in SLES 12
  368. '''
  369. _os_release_map = {
  370. 'os_release_file': {
  371. 'NAME': 'SLES',
  372. 'VERSION': '12',
  373. 'VERSION_ID': '12',
  374. 'PRETTY_NAME': 'SUSE Linux Enterprise Server 12',
  375. 'ID': 'sles',
  376. 'ANSI_COLOR': '0;32',
  377. 'CPE_NAME': 'cpe:/o:suse:sles:12'
  378. },
  379. }
  380. expectation = {
  381. 'oscodename': 'SUSE Linux Enterprise Server 12',
  382. 'osfullname': "SLES",
  383. 'osrelease': '12',
  384. 'osrelease_info': (12,),
  385. 'osmajorrelease': 12,
  386. 'osfinger': 'SLES-12',
  387. }
  388. self._run_suse_os_grains_tests(_os_release_map, expectation)
  389. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  390. def test_suse_os_grains_sles12sp1(self):
  391. '''
  392. Test if OS grains are parsed correctly in SLES 12 SP1
  393. '''
  394. _os_release_map = {
  395. 'os_release_file': {
  396. 'NAME': 'SLES',
  397. 'VERSION': '12-SP1',
  398. 'VERSION_ID': '12.1',
  399. 'PRETTY_NAME': 'SUSE Linux Enterprise Server 12 SP1',
  400. 'ID': 'sles',
  401. 'ANSI_COLOR': '0;32',
  402. 'CPE_NAME': 'cpe:/o:suse:sles:12:sp1'
  403. },
  404. }
  405. expectation = {
  406. 'oscodename': 'SUSE Linux Enterprise Server 12 SP1',
  407. 'osfullname': "SLES",
  408. 'osrelease': '12.1',
  409. 'osrelease_info': (12, 1),
  410. 'osmajorrelease': 12,
  411. 'osfinger': 'SLES-12',
  412. }
  413. self._run_suse_os_grains_tests(_os_release_map, expectation)
  414. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  415. def test_suse_os_grains_opensuse_leap_42_1(self):
  416. '''
  417. Test if OS grains are parsed correctly in openSUSE Leap 42.1
  418. '''
  419. _os_release_map = {
  420. 'os_release_file': {
  421. 'NAME': 'openSUSE Leap',
  422. 'VERSION': '42.1',
  423. 'VERSION_ID': '42.1',
  424. 'PRETTY_NAME': 'openSUSE Leap 42.1 (x86_64)',
  425. 'ID': 'opensuse',
  426. 'ANSI_COLOR': '0;32',
  427. 'CPE_NAME': 'cpe:/o:opensuse:opensuse:42.1'
  428. },
  429. }
  430. expectation = {
  431. 'oscodename': 'openSUSE Leap 42.1 (x86_64)',
  432. 'osfullname': "Leap",
  433. 'osrelease': '42.1',
  434. 'osrelease_info': (42, 1),
  435. 'osmajorrelease': 42,
  436. 'osfinger': 'Leap-42',
  437. }
  438. self._run_suse_os_grains_tests(_os_release_map, expectation)
  439. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  440. def test_suse_os_grains_tumbleweed(self):
  441. '''
  442. Test if OS grains are parsed correctly in openSUSE Tumbleweed
  443. '''
  444. _os_release_map = {
  445. 'os_release_file': {
  446. 'NAME': 'openSUSE',
  447. 'VERSION': 'Tumbleweed',
  448. 'VERSION_ID': '20160504',
  449. 'PRETTY_NAME': 'openSUSE Tumbleweed (20160504) (x86_64)',
  450. 'ID': 'opensuse',
  451. 'ANSI_COLOR': '0;32',
  452. 'CPE_NAME': 'cpe:/o:opensuse:opensuse:20160504'
  453. },
  454. }
  455. expectation = {
  456. 'oscodename': 'openSUSE Tumbleweed (20160504) (x86_64)',
  457. 'osfullname': "Tumbleweed",
  458. 'osrelease': '20160504',
  459. 'osrelease_info': (20160504,),
  460. 'osmajorrelease': 20160504,
  461. 'osfinger': 'Tumbleweed-20160504',
  462. }
  463. self._run_suse_os_grains_tests(_os_release_map, expectation)
  464. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  465. def test_debian_7_os_grains(self):
  466. '''
  467. Test if OS grains are parsed correctly in Debian 7 "wheezy"
  468. '''
  469. _os_release_map = {
  470. 'linux_distribution': ('debian', '7.11', ''),
  471. }
  472. expectation = {
  473. 'os': 'Debian',
  474. 'os_family': 'Debian',
  475. 'oscodename': 'wheezy',
  476. 'osfullname': 'Debian GNU/Linux',
  477. 'osrelease': '7',
  478. 'osrelease_info': (7,),
  479. 'osmajorrelease': 7,
  480. 'osfinger': 'Debian-7',
  481. }
  482. self._run_os_grains_tests("debian-7", _os_release_map, expectation)
  483. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  484. def test_debian_8_os_grains(self):
  485. '''
  486. Test if OS grains are parsed correctly in Debian 8 "jessie"
  487. '''
  488. _os_release_map = {
  489. 'linux_distribution': ('debian', '8.10', ''),
  490. }
  491. expectation = {
  492. 'os': 'Debian',
  493. 'os_family': 'Debian',
  494. 'oscodename': 'jessie',
  495. 'osfullname': 'Debian GNU/Linux',
  496. 'osrelease': '8',
  497. 'osrelease_info': (8,),
  498. 'osmajorrelease': 8,
  499. 'osfinger': 'Debian-8',
  500. }
  501. self._run_os_grains_tests("debian-8", _os_release_map, expectation)
  502. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  503. def test_debian_9_os_grains(self):
  504. '''
  505. Test if OS grains are parsed correctly in Debian 9 "stretch"
  506. '''
  507. _os_release_map = {
  508. 'linux_distribution': ('debian', '9.3', ''),
  509. }
  510. expectation = {
  511. 'os': 'Debian',
  512. 'os_family': 'Debian',
  513. 'oscodename': 'stretch',
  514. 'osfullname': 'Debian GNU/Linux',
  515. 'osrelease': '9',
  516. 'osrelease_info': (9,),
  517. 'osmajorrelease': 9,
  518. 'osfinger': 'Debian-9',
  519. }
  520. self._run_os_grains_tests("debian-9", _os_release_map, expectation)
  521. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  522. def test_ubuntu_xenial_os_grains(self):
  523. '''
  524. Test if OS grains are parsed correctly in Ubuntu 16.04 "Xenial Xerus"
  525. '''
  526. _os_release_map = {
  527. 'linux_distribution': ('Ubuntu', '16.04', 'xenial'),
  528. }
  529. expectation = {
  530. 'os': 'Ubuntu',
  531. 'os_family': 'Debian',
  532. 'oscodename': 'xenial',
  533. 'osfullname': 'Ubuntu',
  534. 'osrelease': '16.04',
  535. 'osrelease_info': (16, 4),
  536. 'osmajorrelease': 16,
  537. 'osfinger': 'Ubuntu-16.04',
  538. }
  539. self._run_os_grains_tests("ubuntu-16.04", _os_release_map, expectation)
  540. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  541. def test_ubuntu_artful_os_grains(self):
  542. '''
  543. Test if OS grains are parsed correctly in Ubuntu 17.10 "Artful Aardvark"
  544. '''
  545. _os_release_map = {
  546. 'linux_distribution': ('Ubuntu', '17.10', 'artful'),
  547. }
  548. expectation = {
  549. 'os': 'Ubuntu',
  550. 'os_family': 'Debian',
  551. 'oscodename': 'artful',
  552. 'osfullname': 'Ubuntu',
  553. 'osrelease': '17.10',
  554. 'osrelease_info': (17, 10),
  555. 'osmajorrelease': 17,
  556. 'osfinger': 'Ubuntu-17.10',
  557. }
  558. self._run_os_grains_tests("ubuntu-17.10", _os_release_map, expectation)
  559. @skipIf(not salt.utils.platform.is_windows(), 'System is not Windows')
  560. def test_windows_platform_data(self):
  561. '''
  562. Test the _windows_platform_data function
  563. '''
  564. grains = ['biosversion', 'kernelrelease', 'kernelversion',
  565. 'manufacturer', 'motherboard', 'osfullname', 'osmanufacturer',
  566. 'osrelease', 'osservicepack', 'osversion', 'productname',
  567. 'serialnumber', 'timezone', 'virtual', 'windowsdomain',
  568. 'windowsdomaintype']
  569. returned_grains = core._windows_platform_data()
  570. for grain in grains:
  571. self.assertIn(grain, returned_grains)
  572. valid_types = ['Unknown', 'Unjoined', 'Workgroup', 'Domain']
  573. self.assertIn(returned_grains['windowsdomaintype'], valid_types)
  574. valid_releases = ['Vista', '7', '8', '8.1', '10', '2008Server',
  575. '2008ServerR2', '2012Server', '2012ServerR2',
  576. '2016Server', '2019Server']
  577. self.assertIn(returned_grains['osrelease'], valid_releases)
  578. def test__windows_os_release_grain(self):
  579. versions = {
  580. 'Windows 10 Home': '10',
  581. 'Windows 10 Pro': '10',
  582. 'Windows 10 Pro for Workstations': '10',
  583. 'Windows 10 Pro Education': '10',
  584. 'Windows 10 Enterprise': '10',
  585. 'Windows 10 Enterprise LTSB': '10',
  586. 'Windows 10 Education': '10',
  587. 'Windows 10 IoT Core': '10',
  588. 'Windows 10 IoT Enterprise': '10',
  589. 'Windows 10 S': '10',
  590. 'Windows 8.1': '8.1',
  591. 'Windows 8.1 Pro': '8.1',
  592. 'Windows 8.1 Enterprise': '8.1',
  593. 'Windows 8.1 OEM': '8.1',
  594. 'Windows 8.1 with Bing': '8.1',
  595. 'Windows 8': '8',
  596. 'Windows 8 Pro': '8',
  597. 'Windows 8 Enterprise': '8',
  598. 'Windows 8 OEM': '8',
  599. 'Windows 7 Starter': '7',
  600. 'Windows 7 Home Basic': '7',
  601. 'Windows 7 Home Premium': '7',
  602. 'Windows 7 Professional': '7',
  603. 'Windows 7 Enterprise': '7',
  604. 'Windows 7 Ultimate': '7',
  605. 'Windows Thin PC': 'Thin',
  606. 'Windows Vista Starter': 'Vista',
  607. 'Windows Vista Home Basic': 'Vista',
  608. 'Windows Vista Home Premium': 'Vista',
  609. 'Windows Vista Business': 'Vista',
  610. 'Windows Vista Enterprise': 'Vista',
  611. 'Windows Vista Ultimate': 'Vista',
  612. 'Windows Server 2019 Essentials': '2019Server',
  613. 'Windows Server 2019 Standard': '2019Server',
  614. 'Windows Server 2019 Datacenter': '2019Server',
  615. 'Windows Server 2016 Essentials': '2016Server',
  616. 'Windows Server 2016 Standard': '2016Server',
  617. 'Windows Server 2016 Datacenter': '2016Server',
  618. 'Windows Server 2012 R2 Foundation': '2012ServerR2',
  619. 'Windows Server 2012 R2 Essentials': '2012ServerR2',
  620. 'Windows Server 2012 R2 Standard': '2012ServerR2',
  621. 'Windows Server 2012 R2 Datacenter': '2012ServerR2',
  622. 'Windows Server 2012 Foundation': '2012Server',
  623. 'Windows Server 2012 Essentials': '2012Server',
  624. 'Windows Server 2012 Standard': '2012Server',
  625. 'Windows Server 2012 Datacenter': '2012Server',
  626. 'Windows MultiPoint Server 2012': '2012Server',
  627. 'Windows Small Business Server 2011': '2011Server',
  628. 'Windows MultiPoint Server 2011': '2011Server',
  629. 'Windows Home Server 2011': '2011Server',
  630. 'Windows MultiPoint Server 2010': '2010Server',
  631. 'Windows Server 2008 R2 Foundation': '2008ServerR2',
  632. 'Windows Server 2008 R2 Standard': '2008ServerR2',
  633. 'Windows Server 2008 R2 Enterprise': '2008ServerR2',
  634. 'Windows Server 2008 R2 Datacenter': '2008ServerR2',
  635. 'Windows Server 2008 R2 for Itanium-based Systems': '2008ServerR2',
  636. 'Windows Web Server 2008 R2': '2008ServerR2',
  637. 'Windows Storage Server 2008 R2': '2008ServerR2',
  638. 'Windows HPC Server 2008 R2': '2008ServerR2',
  639. 'Windows Server 2008 Standard': '2008Server',
  640. 'Windows Server 2008 Enterprise': '2008Server',
  641. 'Windows Server 2008 Datacenter': '2008Server',
  642. 'Windows Server 2008 for Itanium-based Systems': '2008Server',
  643. 'Windows Server Foundation 2008': '2008Server',
  644. 'Windows Essential Business Server 2008': '2008Server',
  645. 'Windows HPC Server 2008': '2008Server',
  646. 'Windows Small Business Server 2008': '2008Server',
  647. 'Windows Storage Server 2008': '2008Server',
  648. 'Windows Web Server 2008': '2008Server'
  649. }
  650. for caption in versions:
  651. version = core._windows_os_release_grain(caption, 1)
  652. self.assertEqual(
  653. version,
  654. versions[caption],
  655. 'version: {0}\n'
  656. 'found: {1}\n'
  657. 'caption: {2}'.format(version, versions[caption], caption)
  658. )
  659. embedded_versions = {
  660. 'Windows Embedded 8.1 Industry Pro': '8.1',
  661. 'Windows Embedded 8 Industry Pro': '8',
  662. 'Windows POSReady 7': '7',
  663. 'Windows Embedded Standard 7': '7',
  664. 'Windows Embedded POSReady 2009': '2009',
  665. 'Windows Embedded Standard 2009': '2009',
  666. 'Windows XP Embedded': 'XP',
  667. }
  668. for caption in embedded_versions:
  669. version = core._windows_os_release_grain(caption, 1)
  670. self.assertEqual(
  671. version,
  672. embedded_versions[caption],
  673. '{0} != {1}\n'
  674. 'version: {0}\n'
  675. 'found: {1}\n'
  676. 'caption: {2}'.format(version, embedded_versions[caption], caption)
  677. )
  678. # Special Cases
  679. # Windows Embedded Standard is Windows 7
  680. caption = 'Windows Embedded Standard'
  681. with patch('platform.release', MagicMock(return_value='7')):
  682. version = core._windows_os_release_grain(caption, 1)
  683. self.assertEqual(version, '7')
  684. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  685. def test_linux_memdata(self):
  686. '''
  687. Test memdata on Linux systems
  688. '''
  689. _proc_meminfo = textwrap.dedent('''\
  690. MemTotal: 16277028 kB
  691. SwapTotal: 4789244 kB''')
  692. with patch('salt.utils.files.fopen', mock_open(read_data=_proc_meminfo)):
  693. memdata = core._linux_memdata()
  694. self.assertEqual(memdata.get('mem_total'), 15895)
  695. self.assertEqual(memdata.get('swap_total'), 4676)
  696. @skipIf(salt.utils.platform.is_windows(), 'System is Windows')
  697. def test_bsd_memdata(self):
  698. '''
  699. Test to memdata on *BSD systems
  700. '''
  701. _path_exists_map = {}
  702. _path_isfile_map = {}
  703. _cmd_run_map = {
  704. 'freebsd-version -u': '10.3-RELEASE',
  705. '/sbin/sysctl -n hw.physmem': '2121781248',
  706. '/sbin/sysctl -n vm.swap_total': '419430400'
  707. }
  708. path_exists_mock = MagicMock(side_effect=lambda x: _path_exists_map[x])
  709. path_isfile_mock = MagicMock(
  710. side_effect=lambda x: _path_isfile_map.get(x, False)
  711. )
  712. cmd_run_mock = MagicMock(
  713. side_effect=lambda x: _cmd_run_map[x]
  714. )
  715. empty_mock = MagicMock(return_value={})
  716. mock_freebsd_uname = ('FreeBSD',
  717. 'freebsd10.3-hostname-8148',
  718. '10.3-RELEASE',
  719. 'FreeBSD 10.3-RELEASE #0 r297264: Fri Mar 25 02:10:02 UTC 2016 root@releng1.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC',
  720. 'amd64',
  721. 'amd64')
  722. with patch('platform.uname',
  723. MagicMock(return_value=mock_freebsd_uname)):
  724. with patch.object(salt.utils.platform, 'is_linux',
  725. MagicMock(return_value=False)):
  726. with patch.object(salt.utils.platform, 'is_freebsd',
  727. MagicMock(return_value=True)):
  728. # Skip the first if statement
  729. with patch.object(salt.utils.platform, 'is_proxy',
  730. MagicMock(return_value=False)):
  731. # Skip the init grain compilation (not pertinent)
  732. with patch.object(os.path, 'exists', path_exists_mock):
  733. with patch('salt.utils.path.which') as mock:
  734. mock.return_value = '/sbin/sysctl'
  735. # Make a bunch of functions return empty dicts,
  736. # we don't care about these grains for the
  737. # purposes of this test.
  738. with patch.object(
  739. core,
  740. '_bsd_cpudata',
  741. empty_mock):
  742. with patch.object(
  743. core,
  744. '_hw_data',
  745. empty_mock):
  746. with patch.object(
  747. core,
  748. '_virtual',
  749. empty_mock):
  750. with patch.object(
  751. core,
  752. '_ps',
  753. empty_mock):
  754. # Mock the osarch
  755. with patch.dict(
  756. core.__salt__,
  757. {'cmd.run': cmd_run_mock}):
  758. os_grains = core.os_data()
  759. self.assertEqual(os_grains.get('mem_total'), 2023)
  760. self.assertEqual(os_grains.get('swap_total'), 400)
  761. @skipIf(salt.utils.platform.is_windows(), 'System is Windows')
  762. def test_docker_virtual(self):
  763. '''
  764. Test if OS grains are parsed correctly in Ubuntu Xenial Xerus
  765. '''
  766. with patch.object(os.path, 'isdir', MagicMock(return_value=False)):
  767. with patch.object(os.path,
  768. 'isfile',
  769. MagicMock(side_effect=lambda x: True if x == '/proc/1/cgroup' else False)):
  770. for cgroup_substr in (':/system.slice/docker', ':/docker/',
  771. ':/docker-ce/'):
  772. cgroup_data = \
  773. '10:memory{0}a_long_sha256sum'.format(cgroup_substr)
  774. log.debug(
  775. 'Testing Docker cgroup substring \'%s\'', cgroup_substr)
  776. with patch('salt.utils.files.fopen', mock_open(read_data=cgroup_data)):
  777. with patch.dict(core.__salt__, {'cmd.run_all': MagicMock()}):
  778. self.assertEqual(
  779. core._virtual({'kernel': 'Linux'}).get('virtual_subtype'),
  780. 'Docker'
  781. )
  782. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  783. def test_xen_virtual(self):
  784. '''
  785. Test if OS grains are parsed correctly in Ubuntu Xenial Xerus
  786. '''
  787. with patch.object(os.path, 'isfile', MagicMock(return_value=False)):
  788. with patch.dict(core.__salt__, {'cmd.run': MagicMock(return_value='')}), \
  789. patch.object(os.path,
  790. 'isfile',
  791. MagicMock(side_effect=lambda x: True if x == '/sys/bus/xen/drivers/xenconsole' else False)):
  792. log.debug('Testing Xen')
  793. self.assertEqual(
  794. core._virtual({'kernel': 'Linux'}).get('virtual_subtype'),
  795. 'Xen PV DomU'
  796. )
  797. def _check_ipaddress(self, value, ip_v):
  798. '''
  799. check if ip address in a list is valid
  800. '''
  801. for val in value:
  802. assert isinstance(val, six.string_types)
  803. ip_method = 'is_ipv{0}'.format(ip_v)
  804. self.assertTrue(getattr(salt.utils.network, ip_method)(val))
  805. def _check_empty(self, key, value, empty):
  806. '''
  807. if empty is False and value does not exist assert error
  808. if empty is True and value exists assert error
  809. '''
  810. if not empty and not value:
  811. raise Exception("{0} is empty, expecting a value".format(key))
  812. elif empty and value:
  813. raise Exception("{0} is suppose to be empty. value: {1} \
  814. exists".format(key, value))
  815. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  816. def test_fqdn_return(self):
  817. '''
  818. test ip4 and ip6 return values
  819. '''
  820. net_ip4_mock = [IP4_LOCAL, IP4_ADD1, IP4_ADD2]
  821. net_ip6_mock = [IP6_LOCAL, IP6_ADD1, IP6_ADD2]
  822. self._run_fqdn_tests(net_ip4_mock, net_ip6_mock,
  823. ip4_empty=False, ip6_empty=False)
  824. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  825. def test_fqdn6_empty(self):
  826. '''
  827. test when ip6 is empty
  828. '''
  829. net_ip4_mock = [IP4_LOCAL, IP4_ADD1, IP4_ADD2]
  830. net_ip6_mock = []
  831. self._run_fqdn_tests(net_ip4_mock, net_ip6_mock,
  832. ip4_empty=False)
  833. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  834. def test_fqdn4_empty(self):
  835. '''
  836. test when ip4 is empty
  837. '''
  838. net_ip4_mock = []
  839. net_ip6_mock = [IP6_LOCAL, IP6_ADD1, IP6_ADD2]
  840. self._run_fqdn_tests(net_ip4_mock, net_ip6_mock,
  841. ip6_empty=False)
  842. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  843. def test_fqdn_all_empty(self):
  844. '''
  845. test when both ip4 and ip6 are empty
  846. '''
  847. net_ip4_mock = []
  848. net_ip6_mock = []
  849. self._run_fqdn_tests(net_ip4_mock, net_ip6_mock)
  850. def _run_fqdn_tests(self, net_ip4_mock, net_ip6_mock,
  851. ip6_empty=True, ip4_empty=True):
  852. def _check_type(key, value, ip4_empty, ip6_empty):
  853. '''
  854. check type and other checks
  855. '''
  856. assert isinstance(value, list)
  857. if '4' in key:
  858. self._check_empty(key, value, ip4_empty)
  859. self._check_ipaddress(value, ip_v='4')
  860. elif '6' in key:
  861. self._check_empty(key, value, ip6_empty)
  862. self._check_ipaddress(value, ip_v='6')
  863. ip4_mock = [(2, 1, 6, '', (IP4_ADD1, 0)),
  864. (2, 3, 0, '', (IP4_ADD2, 0))]
  865. ip6_mock = [(10, 1, 6, '', (IP6_ADD1, 0, 0, 0)),
  866. (10, 3, 0, '', (IP6_ADD2, 0, 0, 0))]
  867. with patch.dict(core.__opts__, {'ipv6': False}):
  868. with patch.object(salt.utils.network, 'ip_addrs',
  869. MagicMock(return_value=net_ip4_mock)):
  870. with patch.object(salt.utils.network, 'ip_addrs6',
  871. MagicMock(return_value=net_ip6_mock)):
  872. with patch.object(core.socket, 'getaddrinfo', side_effect=[ip4_mock, ip6_mock]):
  873. get_fqdn = core.ip_fqdn()
  874. ret_keys = ['fqdn_ip4', 'fqdn_ip6', 'ipv4', 'ipv6']
  875. for key in ret_keys:
  876. value = get_fqdn[key]
  877. _check_type(key, value, ip4_empty, ip6_empty)
  878. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  879. @patch.object(salt.utils.platform, 'is_windows', MagicMock(return_value=False))
  880. @patch('salt.grains.core.__opts__', {'ipv6': False})
  881. def test_dns_return(self):
  882. '''
  883. test the return for a dns grain. test for issue:
  884. https://github.com/saltstack/salt/issues/41230
  885. '''
  886. resolv_mock = {'domain': '', 'sortlist': [], 'nameservers':
  887. [ipaddress.IPv4Address(IP4_ADD1),
  888. ipaddress.IPv6Address(IP6_ADD1),
  889. IP6_ADD_SCOPE], 'ip4_nameservers':
  890. [ipaddress.IPv4Address(IP4_ADD1)],
  891. 'search': ['test.saltstack.com'], 'ip6_nameservers':
  892. [ipaddress.IPv6Address(IP6_ADD1),
  893. IP6_ADD_SCOPE], 'options': []}
  894. ret = {'dns': {'domain': '', 'sortlist': [], 'nameservers':
  895. [IP4_ADD1, IP6_ADD1,
  896. IP6_ADD_SCOPE], 'ip4_nameservers':
  897. [IP4_ADD1], 'search': ['test.saltstack.com'],
  898. 'ip6_nameservers': [IP6_ADD1, IP6_ADD_SCOPE],
  899. 'options': []}}
  900. with patch.object(salt.utils.dns, 'parse_resolv', MagicMock(return_value=resolv_mock)):
  901. assert core.dns() == ret
  902. @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
  903. @patch.object(salt.utils, 'is_windows', MagicMock(return_value=False))
  904. @patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4', '5.6.7.8']))
  905. @patch('salt.utils.network.ip_addrs6',
  906. MagicMock(return_value=['fe80::a8b2:93ff:fe00:0', 'fe80::a8b2:93ff:dead:beef']))
  907. @patch('salt.utils.network.socket.getfqdn', MagicMock(side_effect=lambda v: v)) # Just pass-through
  908. def test_fqdns_return(self):
  909. '''
  910. test the return for a dns grain. test for issue:
  911. https://github.com/saltstack/salt/issues/41230
  912. '''
  913. reverse_resolv_mock = [('foo.bar.baz', [], ['1.2.3.4']),
  914. ('rinzler.evil-corp.com', [], ['5.6.7.8']),
  915. ('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']),
  916. ('bluesniff.foo.bar', [], ['fe80::a8b2:93ff:dead:beef'])]
  917. ret = {'fqdns': ['bluesniff.foo.bar', 'foo.bar.baz', 'rinzler.evil-corp.com']}
  918. with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock):
  919. fqdns = core.fqdns()
  920. self.assertIn('fqdns', fqdns)
  921. self.assertEqual(len(fqdns['fqdns']), len(ret['fqdns']))
  922. self.assertEqual(set(fqdns['fqdns']), set(ret['fqdns']))
  923. def test_core_virtual(self):
  924. '''
  925. test virtual grain with cmd virt-what
  926. '''
  927. virt = 'kvm'
  928. with patch.object(salt.utils.platform, 'is_windows',
  929. MagicMock(return_value=False)):
  930. with patch.object(salt.utils.path, 'which',
  931. MagicMock(return_value=True)):
  932. with patch.dict(core.__salt__, {'cmd.run_all':
  933. MagicMock(return_value={'pid': 78,
  934. 'retcode': 0,
  935. 'stderr': '',
  936. 'stdout': virt})}):
  937. osdata = {'kernel': 'test', }
  938. ret = core._virtual(osdata)
  939. self.assertEqual(ret['virtual'], virt)
  940. def test_solaris_sparc_s7zone(self):
  941. '''
  942. verify productname grain for s7 zone
  943. '''
  944. expectation = {
  945. 'productname': 'SPARC S7-2',
  946. 'product': 'SPARC S7-2',
  947. }
  948. with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtconf.s7-zone')) as sparc_return_data:
  949. this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
  950. this_sparc_return_data += '\n'
  951. self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
  952. def test_solaris_sparc_s7(self):
  953. '''
  954. verify productname grain for s7
  955. '''
  956. expectation = {
  957. 'productname': 'SPARC S7-2',
  958. 'product': 'SPARC S7-2',
  959. }
  960. with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtdiag.s7')) as sparc_return_data:
  961. this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
  962. this_sparc_return_data += '\n'
  963. self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
  964. def test_solaris_sparc_t5220(self):
  965. '''
  966. verify productname grain for t5220
  967. '''
  968. expectation = {
  969. 'productname': 'SPARC Enterprise T5220',
  970. 'product': 'SPARC Enterprise T5220',
  971. }
  972. with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtdiag.t5220')) as sparc_return_data:
  973. this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
  974. this_sparc_return_data += '\n'
  975. self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
  976. def test_solaris_sparc_t5220zone(self):
  977. '''
  978. verify productname grain for t5220 zone
  979. '''
  980. expectation = {
  981. 'productname': 'SPARC Enterprise T5220',
  982. 'product': 'SPARC Enterprise T5220',
  983. }
  984. with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtconf.t5220-zone')) as sparc_return_data:
  985. this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
  986. this_sparc_return_data += '\n'
  987. self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
  988. def _check_solaris_sparc_productname_grains(self, prtdata, expectation):
  989. '''
  990. verify product grains on solaris sparc
  991. '''
  992. import platform
  993. path_isfile_mock = MagicMock(side_effect=lambda x: x in ['/etc/release'])
  994. with salt.utils.files.fopen(os.path.join(OS_RELEASE_DIR, "solaris-11.3")) as os_release_file:
  995. os_release_content = os_release_file.readlines()
  996. uname_mock = MagicMock(return_value=(
  997. 'SunOS', 'testsystem', '5.11', '11.3', 'sunv4', 'sparc'
  998. ))
  999. with patch.object(platform, 'uname', uname_mock), \
  1000. patch.object(salt.utils.platform, 'is_proxy',
  1001. MagicMock(return_value=False)), \
  1002. patch.object(salt.utils.platform, 'is_linux',
  1003. MagicMock(return_value=False)), \
  1004. patch.object(salt.utils.platform, 'is_windows',
  1005. MagicMock(return_value=False)), \
  1006. patch.object(salt.utils.platform, 'is_smartos',
  1007. MagicMock(return_value=False)), \
  1008. patch.object(salt.utils.path, 'which_bin',
  1009. MagicMock(return_value=None)), \
  1010. patch.object(os.path, 'isfile', path_isfile_mock), \
  1011. patch('salt.utils.files.fopen',
  1012. mock_open(read_data=os_release_content)) as os_release_file, \
  1013. patch.object(core, '_sunos_cpudata',
  1014. MagicMock(return_value={
  1015. 'cpuarch': 'sparcv9',
  1016. 'num_cpus': '1',
  1017. 'cpu_model': 'MOCK_CPU_MODEL',
  1018. 'cpu_flags': []})), \
  1019. patch.object(core, '_memdata',
  1020. MagicMock(return_value={'mem_total': 16384})), \
  1021. patch.object(core, '_virtual',
  1022. MagicMock(return_value={})), \
  1023. patch.object(core, '_ps', MagicMock(return_value={})), \
  1024. patch.object(salt.utils.path, 'which',
  1025. MagicMock(return_value=True)), \
  1026. patch.dict(core.__salt__,
  1027. {'cmd.run': MagicMock(return_value=prtdata)}):
  1028. os_grains = core.os_data()
  1029. grains = {k: v for k, v in os_grains.items()
  1030. if k in set(['product', 'productname'])}
  1031. self.assertEqual(grains, expectation)
  1032. @patch('os.path.isfile')
  1033. @patch('os.path.isdir')
  1034. def test_core_virtual_unicode(self, mock_file, mock_dir):
  1035. '''
  1036. test virtual grain with unicode character in product_name file
  1037. '''
  1038. def path_side_effect(path):
  1039. if path == '/sys/devices/virtual/dmi/id/product_name':
  1040. return True
  1041. return False
  1042. virt = 'kvm'
  1043. mock_file.side_effect = path_side_effect
  1044. mock_dir.side_effect = path_side_effect
  1045. with patch.object(salt.utils.platform, 'is_windows',
  1046. MagicMock(return_value=False)):
  1047. with patch.object(salt.utils.path, 'which',
  1048. MagicMock(return_value=True)):
  1049. with patch.dict(core.__salt__, {'cmd.run_all':
  1050. MagicMock(return_value={'pid': 78,
  1051. 'retcode': 0,
  1052. 'stderr': '',
  1053. 'stdout': virt})}):
  1054. with patch('salt.utils.files.fopen',
  1055. mock_open(read_data='嗨')):
  1056. osdata = {'kernel': 'Linux', }
  1057. ret = core._virtual(osdata)
  1058. self.assertEqual(ret['virtual'], virt)
  1059. @patch('salt.utils.path.which', MagicMock(return_value='/usr/sbin/sysctl'))
  1060. def test_osx_memdata_with_comma(self):
  1061. '''
  1062. test osx memdata method when comma returns
  1063. '''
  1064. def _cmd_side_effect(cmd):
  1065. if 'hw.memsize' in cmd:
  1066. return '4294967296'
  1067. elif 'vm.swapusage' in cmd:
  1068. return 'total = 1024,00M used = 160,75M free = 863,25M (encrypted)'
  1069. with patch.dict(core.__salt__, {'cmd.run': MagicMock(side_effect=_cmd_side_effect)}):
  1070. ret = core._osx_memdata()
  1071. assert ret['swap_total'] == 1024
  1072. assert ret['mem_total'] == 4096
  1073. @patch('salt.utils.path.which', MagicMock(return_value='/usr/sbin/sysctl'))
  1074. def test_osx_memdata(self):
  1075. '''
  1076. test osx memdata
  1077. '''
  1078. def _cmd_side_effect(cmd):
  1079. if 'hw.memsize' in cmd:
  1080. return '4294967296'
  1081. elif 'vm.swapusage' in cmd:
  1082. return 'total = 0.00M used = 0.00M free = 0.00M (encrypted)'
  1083. with patch.dict(core.__salt__, {'cmd.run': MagicMock(side_effect=_cmd_side_effect)}):
  1084. ret = core._osx_memdata()
  1085. assert ret['swap_total'] == 0
  1086. assert ret['mem_total'] == 4096