osism 0.20250709.0__tar.gz → 0.20250804.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. osism-0.20250804.0/.zuul.yaml +135 -0
  2. osism-0.20250804.0/ChangeLog +7 -0
  3. {osism-0.20250709.0 → osism-0.20250804.0}/Containerfile +1 -1
  4. {osism-0.20250709.0 → osism-0.20250804.0}/Dockerfile +1 -1
  5. {osism-0.20250709.0/osism.egg-info → osism-0.20250804.0}/PKG-INFO +5 -5
  6. {osism-0.20250709.0 → osism-0.20250804.0}/Pipfile +2 -2
  7. {osism-0.20250709.0 → osism-0.20250804.0}/Pipfile.lock +20 -19
  8. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/baremetal.py +202 -2
  9. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/compose.py +1 -1
  10. osism-0.20250804.0/osism/commands/console.py +177 -0
  11. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/container.py +1 -1
  12. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/log.py +1 -1
  13. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/netbox.py +33 -10
  14. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/sonic.py +197 -2
  15. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/__init__.py +43 -0
  16. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/__init__.py +2 -2
  17. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/config.py +3 -3
  18. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/ironic.py +27 -5
  19. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/interface.py +10 -0
  20. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/utils.py +9 -2
  21. {osism-0.20250709.0 → osism-0.20250804.0}/osism/utils/__init__.py +34 -1
  22. osism-0.20250804.0/osism/utils/ssh.py +250 -0
  23. {osism-0.20250709.0 → osism-0.20250804.0/osism.egg-info}/PKG-INFO +5 -5
  24. {osism-0.20250709.0 → osism-0.20250804.0}/osism.egg-info/SOURCES.txt +1 -0
  25. {osism-0.20250709.0 → osism-0.20250804.0}/osism.egg-info/entry_points.txt +6 -0
  26. osism-0.20250804.0/osism.egg-info/pbr.json +1 -0
  27. {osism-0.20250709.0 → osism-0.20250804.0}/osism.egg-info/requires.txt +4 -4
  28. {osism-0.20250709.0 → osism-0.20250804.0}/playbooks/build.yml +28 -0
  29. {osism-0.20250709.0 → osism-0.20250804.0}/requirements.ansible.txt +1 -1
  30. osism-0.20250804.0/requirements.netbox-manager.txt +1 -0
  31. {osism-0.20250709.0 → osism-0.20250804.0}/requirements.txt +3 -3
  32. {osism-0.20250709.0 → osism-0.20250804.0}/requirements.yml +2 -2
  33. {osism-0.20250709.0 → osism-0.20250804.0}/setup.cfg +6 -0
  34. osism-0.20250709.0/.zuul.yaml +0 -103
  35. osism-0.20250709.0/ChangeLog +0 -7
  36. osism-0.20250709.0/osism/commands/console.py +0 -89
  37. osism-0.20250709.0/osism.egg-info/pbr.json +0 -1
  38. osism-0.20250709.0/requirements.netbox-manager.txt +0 -1
  39. {osism-0.20250709.0 → osism-0.20250804.0}/.flake8 +0 -0
  40. {osism-0.20250709.0 → osism-0.20250804.0}/.github/renovate.json +0 -0
  41. {osism-0.20250709.0 → osism-0.20250804.0}/.github/workflows/publish.yml +0 -0
  42. {osism-0.20250709.0 → osism-0.20250804.0}/.hadolint.yaml +0 -0
  43. {osism-0.20250709.0 → osism-0.20250804.0}/AUTHORS +0 -0
  44. {osism-0.20250709.0 → osism-0.20250804.0}/LICENSE +0 -0
  45. {osism-0.20250709.0 → osism-0.20250804.0}/README.md +0 -0
  46. {osism-0.20250709.0 → osism-0.20250804.0}/files/change.sh +0 -0
  47. {osism-0.20250709.0 → osism-0.20250804.0}/files/cleanup-ansible-collections.sh +0 -0
  48. {osism-0.20250709.0 → osism-0.20250804.0}/files/clustershell/clush.conf +0 -0
  49. {osism-0.20250709.0 → osism-0.20250804.0}/files/clustershell/groups.conf +0 -0
  50. {osism-0.20250709.0 → osism-0.20250804.0}/files/data/SCS-Spec.MandatoryFlavors.verbose.yaml +0 -0
  51. {osism-0.20250709.0 → osism-0.20250804.0}/files/netbox-manager/settings.toml +0 -0
  52. {osism-0.20250709.0 → osism-0.20250804.0}/files/redfishMockupCreate.py +0 -0
  53. {osism-0.20250709.0 → osism-0.20250804.0}/files/run-ansible-console.sh +0 -0
  54. {osism-0.20250709.0 → osism-0.20250804.0}/files/sonic/config_db.json +0 -0
  55. {osism-0.20250709.0 → osism-0.20250804.0}/files/sonic/port_config/Accton-AS4625-54T.ini +0 -0
  56. {osism-0.20250709.0 → osism-0.20250804.0}/files/sonic/port_config/Accton-AS5835-54T.ini +0 -0
  57. {osism-0.20250709.0 → osism-0.20250804.0}/files/sonic/port_config/Accton-AS5835-54X.ini +0 -0
  58. {osism-0.20250709.0 → osism-0.20250804.0}/files/sonic/port_config/Accton-AS7326-56X.ini +0 -0
  59. {osism-0.20250709.0 → osism-0.20250804.0}/files/sonic/port_config/Accton-AS7726-32X.ini +0 -0
  60. {osism-0.20250709.0 → osism-0.20250804.0}/files/sonic/port_config/Accton-AS9716-32D.ini +0 -0
  61. {osism-0.20250709.0 → osism-0.20250804.0}/osism/__init__.py +0 -0
  62. {osism-0.20250709.0 → osism-0.20250804.0}/osism/__main__.py +0 -0
  63. {osism-0.20250709.0 → osism-0.20250804.0}/osism/api.py +0 -0
  64. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/__init__.py +0 -0
  65. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/apply.py +0 -0
  66. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/compute.py +0 -0
  67. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/configuration.py +0 -0
  68. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/get.py +0 -0
  69. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/manage.py +0 -0
  70. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/noset.py +0 -0
  71. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/reconciler.py +0 -0
  72. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/redfish.py +0 -0
  73. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/server.py +0 -0
  74. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/service.py +0 -0
  75. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/set.py +0 -0
  76. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/status.py +0 -0
  77. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/sync.py +0 -0
  78. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/task.py +0 -0
  79. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/validate.py +0 -0
  80. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/vault.py +0 -0
  81. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/volume.py +0 -0
  82. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/wait.py +0 -0
  83. {osism-0.20250709.0 → osism-0.20250804.0}/osism/commands/worker.py +0 -0
  84. {osism-0.20250709.0 → osism-0.20250804.0}/osism/data/__init__.py +0 -0
  85. {osism-0.20250709.0 → osism-0.20250804.0}/osism/data/enums.py +0 -0
  86. {osism-0.20250709.0 → osism-0.20250804.0}/osism/data/playbooks.py +0 -0
  87. {osism-0.20250709.0 → osism-0.20250804.0}/osism/main.py +0 -0
  88. {osism-0.20250709.0 → osism-0.20250804.0}/osism/services/__init__.py +0 -0
  89. {osism-0.20250709.0 → osism-0.20250804.0}/osism/services/listener.py +0 -0
  90. {osism-0.20250709.0 → osism-0.20250804.0}/osism/settings.py +0 -0
  91. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/ansible.py +0 -0
  92. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/ceph.py +0 -0
  93. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/netbox.py +0 -0
  94. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/redfish.py +0 -0
  95. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/__init__.py +0 -0
  96. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/bgp.py +0 -0
  97. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/cache.py +0 -0
  98. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/config_generator.py +0 -0
  99. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/connections.py +0 -0
  100. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/constants.py +0 -0
  101. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/device.py +0 -0
  102. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/exporter.py +0 -0
  103. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor/sonic/sync.py +0 -0
  104. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/conductor.py +0 -0
  105. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/kolla.py +0 -0
  106. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/kubernetes.py +0 -0
  107. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/netbox.py +0 -0
  108. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/openstack.py +0 -0
  109. {osism-0.20250709.0 → osism-0.20250804.0}/osism/tasks/reconciler.py +0 -0
  110. {osism-0.20250709.0 → osism-0.20250804.0}/osism.egg-info/dependency_links.txt +0 -0
  111. {osism-0.20250709.0 → osism-0.20250804.0}/osism.egg-info/not-zip-safe +0 -0
  112. {osism-0.20250709.0 → osism-0.20250804.0}/osism.egg-info/top_level.txt +0 -0
  113. {osism-0.20250709.0 → osism-0.20250804.0}/playbooks/pre.yml +0 -0
  114. {osism-0.20250709.0 → osism-0.20250804.0}/playbooks/test-setup.yml +0 -0
  115. {osism-0.20250709.0 → osism-0.20250804.0}/requirements.openstack-flavor-manager.txt +0 -0
  116. {osism-0.20250709.0 → osism-0.20250804.0}/requirements.openstack-image-manager.txt +0 -0
  117. {osism-0.20250709.0 → osism-0.20250804.0}/setup.py +0 -0
@@ -0,0 +1,135 @@
1
+ ---
2
+ - secret:
3
+ name: SECRET_CONTAINER_IMAGE_PYTHON_OSISM
4
+ data:
5
+ DTRACK_API_KEY: !encrypted/pkcs1-oaep
6
+ - IIS/8v/oGBcvweZ4NIDfaKsj3eRP9vwCqInWCk80L17vUjjPW5GecP2hhVX4XejlWUjtj
7
+ 2z+OsLk+ZPb4nlW5BHLU68AT7OWE8+wtjj7JBvxuwXdWjS0z9fFoedB4ZOeZMzckh0AuA
8
+ Yw+EThCfHJBG5kDh4ZIc+bxFTmKecBue8U+3WcaRmGHloAnLsOiRszjfolP7qQysNljS3
9
+ Jg+GBr6r5/8coBTO+2sJxQkbcGgij3BwuhwT5NOkBMfSdGXZQEwqWrE2PoRVSGoQTDEPz
10
+ OcLdVqOOa2oQSy1epMqhX8zmuYh/xlgpTw0SQKkAMjqqZ4OqTdBn50GmM9rYT5ngwzoeD
11
+ JC4wClKNpW4IunuMiZoWD2wM+SX4sa7gqCfIVWvFhHI2ZWvIzDlcySj0e6s48QasgW7EJ
12
+ yZdiVJLb6VbZ/v+FaibzBBS/fDigZifCu9lXtDRy6lyhaZFRM2+KZ8fsne04sI+J7EQK6
13
+ eTBSE4+/tvX9EkN2Q8q33nm69KSXA2w5KzEGxNJUlomE4hPs+qoqpedbmWjc8ln6TnZJz
14
+ A4JRbxxn3EtkGkZ/isaHlDA155MtQVwzN1Dv5Yt5mWFJ+PflzYxrVQKtQhl3h4jN9zw8J
15
+ P/5fjqkOCuQg/WOtSSoAiJDnuxEaM6by75lKo1KHjFjDWqqfE00iU1dFPmLR10=
16
+ DOCKER_USERNAME: !encrypted/pkcs1-oaep
17
+ - RQR+j7chhH5Zikl2Fc4wxx4wQJJ/gA6nMrPO23EVUlcpypEwfXZpaJ+NNX+11evlbAm74
18
+ RZlrgrdqiYak/dwQ2XINMipvIzP/tgklMywbMXjkvKSUQ5m3as9z8PTbH82gI61zOc8rH
19
+ Nk97AVXk7kVcL8evsnkwdt3a4SvUHqb3VPX0r9iLu/r+pB0K/3zbuEeshJJv5mqsA8gJ4
20
+ o1UjNDwRLyzTmXaQnBCM+OZWGcrFu6xWGNjqEyGOPYlfxClF7gSYKfI/JiMfzWsAi0tm1
21
+ LNFnqJqWhqiJbB2El3ANNeVjRydUoEgVUYomNEt7LOrYfy/8h/0+W8cprl0pJ31LqsjMo
22
+ 1ffDeuNwy9yL07jCgST9ifrZBaMlaa7W+b7zKZR4tLR04AH+xFXpXF1i5WAGXp+pWFXyt
23
+ upQuFBQKnRaKhbL+xssFUOjyyA6EXmeSqcksrxkja0XPq2SKIbhvt2yHzVnOUX38qJ51S
24
+ a3Lg/XjQ6AcT6ihXUnmHefpbq2ZU/OxX5W10hsbUi+4C1R8yfAxlSpjiiXgsRYorbtP5m
25
+ 7L5hjXA0Jxk4elr8F/kU+wARxRf4Nye/qeKgSmnorXBkCzobN1IYeXZRMdiRPSIwOz35a
26
+ k0eqSsLw4YjxVe9Bno6ECFZwpnVMg+LCCgvzprrq/PzzJ+HBRuci4t4n8tJdQg=
27
+ DOCKER_PASSWORD: !encrypted/pkcs1-oaep
28
+ - cT1OVP/NSzK1LO7t4TYjzvRvRVmoyjWcGdDKpITx+wOITxDi5lH1tULX43WlSwFZEs/w1
29
+ U/xNBFW56Xq0CrIbvFnReJ6KbRlioAT0fViuKIEMqWzT3L1STI8lMsKkXDBvyX8k+mu35
30
+ y4ne7z+8QRd0UAb+domNr2AWzSZ7taBWykpUEWwsfsZiAam9Ef8BX//BFI2joVOx7BJq9
31
+ C+k96yVyX0DXJa7ic5wzOOXn9CUmeq1zDrQJtJzFE+4+EK+LK6TfJO/HX7JFkF1+Okqhq
32
+ onkniBPoz/T6LKBwHzbbvin/LYgZ0DWqT2OCQFKBXKjUoI5jieGh4utBmDonR8PXTV8MK
33
+ ZWde+KBZeuR6EpHL+q9f+kvxZH+zIj4uLLy6yspPtZV4BKtKLvcH9OOcgPnJ8xgIETabf
34
+ sEN60u2R170XT9KR4FsrrGY9ABlJF4VGSfB0yWonZhtZgrpCcHIt43IliXHWo+0FE+WNk
35
+ uvegHv5fzAs0NNLZLPU2oz1QBaH/bTM9kBitautoOFtZlyoDmKAZBm/NHRg8TrShVQOhj
36
+ hZ5iGPnCE1Yzl4Rz2qhmrzfVBjta2guLUeGwXZUeDFQb59NYRydBJCZkFohws98dGCXGl
37
+ 0lOnRF6gyYWknU+FGATGL4o5Q7S5H143xmxrlpiC1qSAW37Y1Zf3k4RqI71iY4=
38
+ COSIGN_PASSWORD: !encrypted/pkcs1-oaep
39
+ - kybkfT+M+IZbYsEm8jEuZdt1ROA1oxH17wwQB15dvPfKF5PZanb0XHmLRgzbGEXKriKip
40
+ 5fmbaI4RNBlRgfgRGdG2B67cRGosdXaR6ecbcqXZW6p7IXCMFOK6rgEkExv2aAYowQ4v0
41
+ OXxoDquxpxEWhhitEcVAuMO2Bnl7zNjO5oskE32Jy8YHIDCnSAmHe0SQ3yx9qaQHb9GcU
42
+ Aodz5DwLaHupsSxLFaHbXSI8Z75eSYmTiJ4npge6uETRjpY4fiodlgs1/7Rbm+q8pBhMC
43
+ Wbzyb27T3YflMZnHHKq791BoKTxNESLghY+iLNLnVHBL/hukcv1DjAS1Zw5M9WIDFk1CA
44
+ lUCFPOVSKz8ioFVbV7KFLXJw6datjLohklV+Z/vgJfVsMl4JGNCV/hTpwsqsoJkW1jedi
45
+ KA5AX0LPyc6hcKh1tY2UCNMjuPhXnwcMUeclYopHH1znGsPciZMt2G8MXbnXexYNo4IYR
46
+ ByTDczzHthElw/h7ibcLiG4DqsDob36UBLX5NgMKaPd1oUsDFjiHTJeoeLVbv95EbOWhz
47
+ Z99fDeEc9FMqJNfnt3aQg0tX93yTaB00K2hkXWD8Qndh1VssG6UTLc3feWEPNcSWBODc1
48
+ v/VsvdnDvTX2Gs9S1japastbI2lwnkEjS1piYDO05eAJ9l/5bBMUyX+ofQ6y4I=
49
+ COSIGN_PRIVATE_KEY: !encrypted/pkcs1-oaep
50
+ - hRj4LuJ0aFo5EGxg+5XxKr7VDOYTWz6PRk+dmBim8FrsWW1negdcR9XfowDTe/w0Drtr1
51
+ RNp6i3204a+dmCyW4Kfs4T874LPIdoX6cAcJ1tf02e+7jrZP73caorMqFQinY+4g3nB9B
52
+ Kf/K5jMbJeUBwO3zV2ltY1yP6yz+fMYNLLjqcoVmCk/KQdoxmG6QfaGOHxO02HURk6lwA
53
+ dzGk52c7M5y6HHH1AhbV5P7g79txq/qX+yzYirlT9hTGmE4oDDQ/5P06n9AT6/MKV/UTf
54
+ M0y70eMjierVVEOONPRNw3AHaE434gKE0OiKrnSm/mDEvxHUUa+JhoM44s26HkxSAvfqh
55
+ ci9TypLlX3vzf5Dba4a1ti1B/zdT3qaJHaWtWRom91XNdcAs4T1OPrFpsITtVMyF4ahiZ
56
+ DgCuSRs5C3ZRnBghSxuC1p+c23/BM7IEaJ+1ESC5V7Z+chnpyob8ASbcyd+2UKRHMUU22
57
+ I8Nl0Cz0tV2HF7OOwb+uTs8nnHhz4bo5P8erslEaVxRJTzX+jt0S5fpEChiMxdtQpsooe
58
+ hf7Z1dvEER3lm9/BfmOf2lCjhB29pRJAG15sS2R7VzDjk8SWOsPW9X/SXt/Tebj+iwBhB
59
+ N9WPEUd18duWdWziciRQrmoCtYHwYF2yv8rVekmP4xXQbfcnaYSWr0mcFrxxLc=
60
+ - Qy3Z86vQT7boCbjI9p8SS/FRr6M6gc/5GNMNcyVktbTZe83ZKrPyc3mUb5g/nMZ3S6a8Y
61
+ PvfiZIOG9Ip3rPir9cPZ1gMTFYBT+5go2/+WD5i6AguXGmFO5N/vJLH7QqXRVNy9wkQtW
62
+ eGZGrTfkTXfEbcf4ALPEWU7z/AX231CJBjohpY/wAB+Rdb8rui+t1qli5hDQUfws9IGzc
63
+ JQWwOeppAyo1KL9Nl7SF/1reXExILx0K71roqwSPIqw9d7BXbV4OKc1iidyEh881sWfcj
64
+ otJkYehvAHJJRDtyLvEllSRcTQgMSGm28I/Hdf24wOhL4G5BRom6htcxXp93EzherVtjF
65
+ LqdOUhofUcI3LYsBynE9mTc8s7C4bYz5VS+BngYk0HGiCpgIcYQVuZZtSeXzN7u3cmqJb
66
+ ACY8PO6uIbIpa2qjuVJy3r+fRdtdzF0dUZV7vy2/ULruROQ1bSVW4WVXi1B2wz1cAH8De
67
+ jmadwR2jFJC3/+kSw0run6WYBXbnsA51xOwqurBX6tMjgeb2mw+Qq4U9azTleEyIDdiz4
68
+ xPRs0Ww0g9CGKX6vV+MHjw5pwb1THXqCZwdxldVQ/DFvZZQDbyCbJ8m1FQVbDtvnBqCsn
69
+ eBqHgBOjkegoG5Ooj+00gvZj83jPkmbkFf58nEd7lVBiG2JN/RqLvCQhKoEqQ8=
70
+
71
+ - semaphore:
72
+ name: semaphore-container-image-python-osism-push
73
+ max: 1
74
+
75
+ - job:
76
+ name: container-image-python-osism-build
77
+ pre-run: playbooks/pre.yml
78
+ run: playbooks/build.yml
79
+ vars:
80
+ docker_namespace: osism
81
+ docker_registry: osism.harbor.regio.digital
82
+
83
+ - job:
84
+ name: container-image-python-osism-push
85
+ semaphores:
86
+ - name: semaphore-container-image-python-osism-push
87
+ pre-run: playbooks/pre.yml
88
+ run: playbooks/build.yml
89
+ vars:
90
+ docker_namespace: osism
91
+ docker_registry: osism.harbor.regio.digital
92
+ push_image: true
93
+ push_sbom: true
94
+ secrets:
95
+ - name: secret
96
+ secret: SECRET_CONTAINER_IMAGE_PYTHON_OSISM
97
+
98
+ - job:
99
+ name: python-osism-test-setup
100
+ pre-run: playbooks/pre.yml
101
+ run: playbooks/test-setup.yml
102
+
103
+ - project:
104
+ merge-mode: squash-merge
105
+ default-branch: main
106
+ check:
107
+ jobs:
108
+ - flake8
109
+ - hadolint
110
+ - mypy
111
+ - python-black
112
+ - container-image-python-osism-build
113
+ - python-osism-test-setup
114
+ gate:
115
+ jobs:
116
+ - flake8
117
+ - hadolint
118
+ - python-black
119
+ periodic-daily:
120
+ jobs:
121
+ - flake8
122
+ - hadolint
123
+ - mypy
124
+ - python-black
125
+ - python-osism-test-setup
126
+ periodic-midnight:
127
+ jobs:
128
+ - container-image-python-osism-push
129
+ post:
130
+ jobs:
131
+ - container-image-python-osism-push:
132
+ branches: main
133
+ tag:
134
+ jobs:
135
+ - container-image-python-osism-push
@@ -0,0 +1,7 @@
1
+ CHANGES
2
+ =======
3
+
4
+ v0.20250804.0
5
+ -------------
6
+
7
+ * Add baremetal command entry points to CLI (#1605)
@@ -7,7 +7,7 @@ FROM ${IMAGE}:${PYTHON_VERSION}-alpine${ALPINE_VERSION}
7
7
  ENV PYTHONWARNINGS="ignore::UserWarning"
8
8
 
9
9
  COPY . /src
10
- COPY --from=ghcr.io/astral-sh/uv:0.7.19 /uv /usr/local/bin/uv
10
+ COPY --from=ghcr.io/astral-sh/uv:0.8.4 /uv /usr/local/bin/uv
11
11
 
12
12
  COPY files/data /data
13
13
  COPY files/change.sh /change.sh
@@ -7,7 +7,7 @@ FROM ${IMAGE}:${PYTHON_VERSION}-alpine${ALPINE_VERSION}
7
7
  ENV PYTHONWARNINGS="ignore::UserWarning"
8
8
 
9
9
  COPY . /src
10
- COPY --from=ghcr.io/astral-sh/uv:0.7.19 /uv /usr/local/bin/uv
10
+ COPY --from=ghcr.io/astral-sh/uv:0.8.4 /uv /usr/local/bin/uv
11
11
 
12
12
  COPY files/data /data
13
13
  COPY files/change.sh /change.sh
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: osism
3
- Version: 0.20250709.0
3
+ Version: 0.20250804.0
4
4
  Summary: OSISM manager interface
5
5
  Home-page: https://github.com/osism/python-osism
6
6
  Author: OSISM GmbH
@@ -22,7 +22,7 @@ Requires-Python: >=3.8
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  Requires-Dist: ClusterShell==1.9.3
25
- Requires-Dist: GitPython==3.1.44
25
+ Requires-Dist: GitPython==3.1.45
26
26
  Requires-Dist: Jinja2==3.1.6
27
27
  Requires-Dist: PyYAML==6.0.2
28
28
  Requires-Dist: ara==1.7.2
@@ -31,7 +31,7 @@ Requires-Dist: cliff==4.10.0
31
31
  Requires-Dist: deepdiff==8.5.0
32
32
  Requires-Dist: docker==7.1.0
33
33
  Requires-Dist: dtrack-auditor==1.5.0
34
- Requires-Dist: fastapi==0.116.0
34
+ Requires-Dist: fastapi==0.116.1
35
35
  Requires-Dist: flower==2.0.1
36
36
  Requires-Dist: hiredis==3.2.1
37
37
  Requires-Dist: jc==1.25.5
@@ -49,7 +49,7 @@ Requires-Dist: pytest-testinfra==10.2.2
49
49
  Requires-Dist: python-dateutil==2.9.0.post0
50
50
  Requires-Dist: setuptools==80.9.0
51
51
  Requires-Dist: sqlmodel==0.0.24
52
- Requires-Dist: sushy==5.6.0
52
+ Requires-Dist: sushy==5.7.0
53
53
  Requires-Dist: tabulate==0.9.0
54
54
  Requires-Dist: transitions==0.9.3
55
55
  Requires-Dist: uvicorn[standard]==0.35.0
@@ -57,7 +57,7 @@ Requires-Dist: validators==0.35.0
57
57
  Requires-Dist: watchdog==6.0.0
58
58
  Provides-Extra: ansible
59
59
  Requires-Dist: ansible-runner==2.4.1; extra == "ansible"
60
- Requires-Dist: ansible-core==2.18.6; extra == "ansible"
60
+ Requires-Dist: ansible-core==2.19.0; extra == "ansible"
61
61
  Provides-Extra: openstack-image-manager
62
62
  Requires-Dist: openstack-image-manager==0.20250508.0; extra == "openstack-image-manager"
63
63
  Dynamic: author
@@ -5,7 +5,7 @@ name = "pypi"
5
5
 
6
6
  [packages]
7
7
  ClusterShell = "==1.9.3"
8
- GitPython = "==3.1.44"
8
+ GitPython = "==3.1.45"
9
9
  Jinja2 = "==3.1.6"
10
10
  PyYAML = "==6.0.2"
11
11
  ansible-runner = "==2.4.1"
@@ -33,7 +33,7 @@ pytest-testinfra = "==10.2.2"
33
33
  python-dateutil = "==2.9.0.post0"
34
34
  setuptools = "==80.9.0"
35
35
  sqlmodel = "==0.0.24"
36
- sushy = "==5.6.0"
36
+ sushy = "==5.7.0"
37
37
  transitions = "==0.9.3"
38
38
  validators = "==0.35.0"
39
39
  watchdog = "==6.0.0"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "_meta": {
3
3
  "hash": {
4
- "sha256": "0734ea0b094ceaebe6736f81feb34d4c2eeca718c6dd9eeabb51bfa09c8465dc"
4
+ "sha256": "e6716817deb1ee55e4957e574c60f419c03e085d19e177fb253c089a8a43a6dd"
5
5
  },
6
6
  "pipfile-spec": 6,
7
7
  "requires": {},
@@ -142,11 +142,11 @@
142
142
  },
143
143
  "certifi": {
144
144
  "hashes": [
145
- "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057",
146
- "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"
145
+ "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2",
146
+ "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995"
147
147
  ],
148
148
  "markers": "python_version >= '3.7'",
149
- "version": "==2025.6.15"
149
+ "version": "==2025.7.14"
150
150
  },
151
151
  "cffi": {
152
152
  "hashes": [
@@ -486,12 +486,12 @@
486
486
  },
487
487
  "gitpython": {
488
488
  "hashes": [
489
- "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110",
490
- "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"
489
+ "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c",
490
+ "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77"
491
491
  ],
492
492
  "index": "pypi",
493
493
  "markers": "python_version >= '3.7'",
494
- "version": "==3.1.44"
494
+ "version": "==3.1.45"
495
495
  },
496
496
  "google-auth": {
497
497
  "hashes": [
@@ -1002,18 +1002,19 @@
1002
1002
  },
1003
1003
  "orderly-set": {
1004
1004
  "hashes": [
1005
- "sha256:a1fb5a4fdc5e234e9e8d8e5c1bbdbc4540f4dfe50d12bf17c8bc5dbf1c9c878d",
1006
- "sha256:b5e21d21680bd9ef456885db800c5cb4f76a03879880c0175e1b077fb166fd83"
1005
+ "sha256:46f0b801948e98f427b412fcabb831677194c05c3b699b80de260374baa0b1e7",
1006
+ "sha256:e87185c8e4d8afa64e7f8160ee2c542a475b738bc891dc3f58102e654125e6ce"
1007
1007
  ],
1008
1008
  "markers": "python_version >= '3.8'",
1009
- "version": "==5.4.1"
1009
+ "version": "==5.5.0"
1010
1010
  },
1011
1011
  "os-service-types": {
1012
1012
  "hashes": [
1013
- "sha256:0505c72205690910077fb72b88f2a1f07533c8d39f2fe75b29583481764965d6",
1014
- "sha256:31800299a82239363995b91f1ebf9106ac7758542a1e4ef6dc737a5932878c6c"
1013
+ "sha256:890ce74f132ca334c2b23f0025112b47c6926da6d28c2f75bcfc0a83dea3603e",
1014
+ "sha256:bc0418bf826de1639c7f54b2c752827ea9aa91cbde560d0b0bf6339d97270b3b"
1015
1015
  ],
1016
- "version": "==1.7.0"
1016
+ "markers": "python_version >= '3.10'",
1017
+ "version": "==1.8.0"
1017
1018
  },
1018
1019
  "packaging": {
1019
1020
  "hashes": [
@@ -1624,12 +1625,12 @@
1624
1625
  },
1625
1626
  "sushy": {
1626
1627
  "hashes": [
1627
- "sha256:77be2b48bbdecd5d2d72a9c04c722219ea059c76b7d55a56441249a579f09df5",
1628
- "sha256:bb836a71f9edd402dd154b2b7f60257836847efc77760cd6082cd137323a1f7d"
1628
+ "sha256:67363d5b436cb74c13e66af866a0b005f5ced5ad0e0a780db7e3a1ea327b2f03",
1629
+ "sha256:c4476ffde00f2201487e99ab138148f36c8d4efbb08b3ecbe2a5e00a752da249"
1629
1630
  ],
1630
1631
  "index": "pypi",
1631
1632
  "markers": "python_version >= '3.9'",
1632
- "version": "==5.6.0"
1633
+ "version": "==5.7.0"
1633
1634
  },
1634
1635
  "tornado": {
1635
1636
  "hashes": [
@@ -1659,11 +1660,11 @@
1659
1660
  },
1660
1661
  "typing-extensions": {
1661
1662
  "hashes": [
1662
- "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4",
1663
- "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af"
1663
+ "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36",
1664
+ "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"
1664
1665
  ],
1665
1666
  "markers": "python_version >= '3.9'",
1666
- "version": "==4.14.0"
1667
+ "version": "==4.14.1"
1667
1668
  },
1668
1669
  "typing-inspection": {
1669
1670
  "hashes": [
@@ -4,6 +4,8 @@ from cliff.command import Command
4
4
 
5
5
  import tempfile
6
6
  import os
7
+ import subprocess
8
+ import threading
7
9
  from loguru import logger
8
10
  import openstack
9
11
  from tabulate import tabulate
@@ -13,6 +15,9 @@ from openstack.baremetal import configdrive as configdrive_builder
13
15
 
14
16
  from osism.commands import get_cloud_connection
15
17
  from osism import utils
18
+ from osism.tasks.conductor.netbox import get_nb_device_query_list_ironic
19
+ from osism.tasks import netbox
20
+ from osism.utils.ssh import cleanup_ssh_known_hosts_for_node
16
21
 
17
22
 
18
23
  class BaremetalList(Command):
@@ -57,6 +62,8 @@ class BaremetalList(Command):
57
62
  for b in baremetal
58
63
  ]
59
64
 
65
+ result.sort(key=lambda x: x[0])
66
+
60
67
  print(
61
68
  tabulate(
62
69
  result,
@@ -206,7 +213,7 @@ class BaremetalDeploy(Command):
206
213
 
207
214
  playbook = []
208
215
  play = {
209
- "name": "Run bootstrap - part 2",
216
+ "name": "Run bootstrap",
210
217
  "hosts": "localhost",
211
218
  "connection": "local",
212
219
  "gather_facts": True,
@@ -216,6 +223,15 @@ class BaremetalDeploy(Command):
216
223
  "osism.commons.hosts",
217
224
  "osism.commons.operator",
218
225
  ],
226
+ "tasks": [
227
+ {
228
+ "name": "Restart rsyslog service after hostname change",
229
+ "ansible.builtin.systemd": {
230
+ "name": "rsyslog",
231
+ "state": "restarted",
232
+ },
233
+ }
234
+ ],
219
235
  }
220
236
  play["vars"].update(
221
237
  {"hostname_name": node.name, "hosts_type": "template"}
@@ -321,9 +337,30 @@ class BaremetalUndeploy(Command):
321
337
  if not node:
322
338
  continue
323
339
 
324
- if node.provision_state in ["active", "deploy failed", "error"]:
340
+ if node.provision_state in [
341
+ "active",
342
+ "wait call-back",
343
+ "deploy failed",
344
+ "error",
345
+ ]:
325
346
  try:
326
347
  node = conn.baremetal.set_node_provision_state(node.id, "undeploy")
348
+ logger.info(
349
+ f"Successfully initiated undeploy for node {node.name} ({node.id})"
350
+ )
351
+
352
+ # Clean up SSH known_hosts entries for the undeployed node
353
+ logger.info(f"Cleaning up SSH known_hosts entries for {node.name}")
354
+ result = cleanup_ssh_known_hosts_for_node(node.name)
355
+ if result:
356
+ logger.info(
357
+ f"SSH known_hosts cleanup completed successfully for {node.name}"
358
+ )
359
+ else:
360
+ logger.warning(
361
+ f"SSH known_hosts cleanup completed with warnings for {node.name}"
362
+ )
363
+
327
364
  except Exception as exc:
328
365
  logger.warning(
329
366
  f"Node {node.name} ({node.id}) could not be moved to available state: {exc}"
@@ -333,3 +370,166 @@ class BaremetalUndeploy(Command):
333
370
  logger.warning(
334
371
  f"Node {node.name} ({node.id}) not in supported provision state"
335
372
  )
373
+
374
+
375
+ class BaremetalPing(Command):
376
+ def get_parser(self, prog_name):
377
+ parser = super(BaremetalPing, self).get_parser(prog_name)
378
+ parser.add_argument(
379
+ "name",
380
+ nargs="?",
381
+ type=str,
382
+ help="Ping specific baremetal node by name",
383
+ )
384
+ return parser
385
+
386
+ def _ping_host(self, host, results, host_name):
387
+ """Ping a host 3 times and store results."""
388
+ try:
389
+ result = subprocess.run(
390
+ ["ping", "-c", "3", "-W", "5", host],
391
+ capture_output=True,
392
+ text=True,
393
+ timeout=20,
394
+ )
395
+
396
+ if result.returncode == 0:
397
+ output_lines = result.stdout.strip().split("\n")
398
+ stats_line = [line for line in output_lines if "packet loss" in line]
399
+ if stats_line:
400
+ loss_info = stats_line[0]
401
+ if "0% packet loss" in loss_info:
402
+ status = "SUCCESS"
403
+ else:
404
+ status = f"PARTIAL ({loss_info.split(',')[2].strip()})"
405
+ else:
406
+ status = "SUCCESS"
407
+
408
+ time_lines = [
409
+ line
410
+ for line in output_lines
411
+ if "round-trip" in line or "rtt" in line
412
+ ]
413
+ if time_lines:
414
+ time_info = (
415
+ time_lines[0].split("=")[-1].strip()
416
+ if "=" in time_lines[0]
417
+ else "N/A"
418
+ )
419
+ else:
420
+ time_info = "N/A"
421
+ else:
422
+ status = "FAILED"
423
+ time_info = "N/A"
424
+
425
+ except (
426
+ subprocess.TimeoutExpired,
427
+ subprocess.CalledProcessError,
428
+ Exception,
429
+ ) as e:
430
+ status = "ERROR"
431
+ time_info = str(e)[:50]
432
+
433
+ results[host_name] = {"host": host, "status": status, "time_info": time_info}
434
+
435
+ def take_action(self, parsed_args):
436
+ name = parsed_args.name
437
+
438
+ if not utils.nb:
439
+ logger.error("NetBox connection not available")
440
+ return
441
+
442
+ conn = get_cloud_connection()
443
+
444
+ try:
445
+ if name:
446
+ devices = [utils.nb.dcim.devices.get(name=name)]
447
+ if not devices[0]:
448
+ logger.error(f"Device {name} not found in NetBox")
449
+ return
450
+ else:
451
+ # Use the NETBOX_FILTER_CONDUCTOR_IRONIC setting to get devices
452
+ devices = set()
453
+ nb_device_query_list = get_nb_device_query_list_ironic()
454
+ for nb_device_query in nb_device_query_list:
455
+ devices |= set(netbox.get_devices(**nb_device_query))
456
+ devices = list(devices)
457
+
458
+ # Additionally filter by power state and provision state
459
+ filtered_devices = []
460
+ for device in devices:
461
+ if (
462
+ hasattr(device, "custom_fields")
463
+ and device.custom_fields
464
+ and device.custom_fields.get("power_state") == "power on"
465
+ and device.custom_fields.get("provision_state") == "active"
466
+ ):
467
+ filtered_devices.append(device)
468
+ devices = filtered_devices
469
+
470
+ if not devices:
471
+ logger.info(
472
+ "No devices found matching criteria (managed-by-ironic, power on, active)"
473
+ )
474
+ return
475
+
476
+ ping_candidates = []
477
+ for device in devices:
478
+ if device.primary_ip4:
479
+ ip_address = str(device.primary_ip4.address).split("/")[0]
480
+ ping_candidates.append({"name": device.name, "ip": ip_address})
481
+ else:
482
+ logger.warning(f"Device {device.name} has no primary IPv4 address")
483
+
484
+ if not ping_candidates:
485
+ logger.info("No devices found with primary IPv4 addresses")
486
+ return
487
+
488
+ logger.info(f"Pinging {len(ping_candidates)} nodes (3 pings each)...")
489
+
490
+ results = {}
491
+ threads = []
492
+
493
+ for candidate in ping_candidates:
494
+ thread = threading.Thread(
495
+ target=self._ping_host,
496
+ args=(candidate["ip"], results, candidate["name"]),
497
+ )
498
+ threads.append(thread)
499
+ thread.start()
500
+
501
+ for thread in threads:
502
+ thread.join()
503
+
504
+ table_data = []
505
+ success_count = 0
506
+ failed_count = 0
507
+
508
+ for device_name in sorted(results.keys()):
509
+ result = results[device_name]
510
+ table_data.append(
511
+ [device_name, result["host"], result["status"], result["time_info"]]
512
+ )
513
+
514
+ if result["status"] == "SUCCESS":
515
+ success_count += 1
516
+ elif result["status"].startswith("PARTIAL"):
517
+ failed_count += 1
518
+ else:
519
+ failed_count += 1
520
+
521
+ print(
522
+ tabulate(
523
+ table_data,
524
+ headers=["Name", "IP Address", "Status", "Time Info"],
525
+ tablefmt="psql",
526
+ )
527
+ )
528
+
529
+ print(
530
+ f"\nSummary: {success_count} successful, {failed_count} failed/partial out of {len(ping_candidates)} total"
531
+ )
532
+
533
+ except Exception as e:
534
+ logger.error(f"Error during ping operation: {e}")
535
+ return
@@ -26,7 +26,7 @@ class Run(Command):
26
26
  ssh_command = (
27
27
  f"docker compose --project-directory=/opt/{environment} {arguments}"
28
28
  )
29
- ssh_options = "-o StrictHostKeyChecking=no -o LogLevel=ERROR"
29
+ ssh_options = "-o StrictHostKeyChecking=no -o LogLevel=ERROR -o UserKnownHostsFile=/share/known_hosts"
30
30
 
31
31
  # FIXME: use paramiko or something else more Pythonic + make operator user + key configurable
32
32
  subprocess.call(