sbcli-pre 1.2.5__zip → 1.2.6__zip

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 (141) hide show
  1. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/PKG-INFO +1 -1
  2. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/env_var +1 -1
  3. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/sbcli_pre.egg-info/PKG-INFO +1 -1
  4. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/sbcli_pre.egg-info/SOURCES.txt +5 -3
  5. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_cli/cli.py +113 -115
  6. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/cluster_ops.py +138 -235
  7. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/constants.py +5 -7
  8. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/caching_node_controller.py +8 -6
  9. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/cluster_events.py +9 -0
  10. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/device_controller.py +56 -63
  11. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/events_controller.py +5 -3
  12. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/health_controller.py +30 -40
  13. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/lvol_controller.py +51 -38
  14. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/pool_controller.py +8 -4
  15. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/snapshot_controller.py +9 -3
  16. sbcli_pre-1.2.6/simplyblock_core/controllers/tasks_controller.py +103 -0
  17. sbcli_pre-1.2.6/simplyblock_core/controllers/tasks_events.py +37 -0
  18. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/distr_controller.py +13 -9
  19. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/kv_store.py +47 -20
  20. sbcli_pre-1.2.6/simplyblock_core/mgmt_node_ops.py +205 -0
  21. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/events.py +9 -1
  22. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/job_schedule.py +6 -0
  23. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/nvme_device.py +42 -4
  24. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/storage_node.py +9 -1
  25. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/rpc_client.py +55 -10
  26. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/__init__.py +0 -4
  27. sbcli_pre-1.2.5/simplyblock_core/scripts/alerting/alert_resources.yaml → sbcli_pre-1.2.6/simplyblock_core/scripts/alerting/alert_resources.yaml.j2 +54 -5
  28. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/dashboards/cluster.json +1 -1
  29. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/deploy_stack.sh +9 -0
  30. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/docker-compose-swarm-monitoring.yml +32 -15
  31. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/docker-compose-swarm.yml +17 -2
  32. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/haproxy.cfg +15 -0
  33. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/install_deps.sh +3 -0
  34. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/stack_deploy_wait.sh +1 -1
  35. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/capacity_and_stats_collector.py +1 -1
  36. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/device_monitor.py +5 -46
  37. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/distr_event_collector.py +10 -11
  38. sbcli_pre-1.2.6/simplyblock_core/services/health_check_service.py +134 -0
  39. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/lvol_monitor.py +1 -1
  40. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/lvol_stat_collector.py +1 -1
  41. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/port_stat_collector.py +0 -1
  42. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/storage_node_monitor.py +49 -44
  43. sbcli_pre-1.2.6/simplyblock_core/services/tasks_runner_migration.py +61 -0
  44. sbcli_pre-1.2.5/simplyblock_core/services/job_tasks.py → sbcli_pre-1.2.6/simplyblock_core/services/tasks_runner_restart.py +95 -46
  45. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/snode_client.py +12 -0
  46. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/storage_node_ops.py +525 -336
  47. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/utils.py +46 -1
  48. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/snode_ops.py +103 -25
  49. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_cluster.py +20 -43
  50. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_device.py +10 -7
  51. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_lvol.py +9 -5
  52. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_pool.py +14 -5
  53. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_storage_node.py +3 -10
  54. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/node_utils.py +0 -2
  55. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/utils.py +8 -0
  56. sbcli_pre-1.2.5/simplyblock_core/mgmt_node_ops.py +0 -80
  57. sbcli_pre-1.2.5/simplyblock_core/scripts/apply_dashboard.sh +0 -22
  58. sbcli_pre-1.2.5/simplyblock_core/services/health_check_service.py +0 -136
  59. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/README.md +0 -0
  60. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/pyproject.toml +0 -0
  61. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/sbcli_pre.egg-info/dependency_links.txt +0 -0
  62. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/sbcli_pre.egg-info/entry_points.txt +0 -0
  63. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/sbcli_pre.egg-info/requires.txt +0 -0
  64. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/sbcli_pre.egg-info/top_level.txt +0 -0
  65. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/setup.cfg +0 -0
  66. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/setup.py +0 -0
  67. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_cli/main.py +0 -0
  68. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/__init__.py +0 -0
  69. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/cnode_client.py +0 -0
  70. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/compute_node_ops.py +0 -0
  71. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/__init__.py +0 -0
  72. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/device_events.py +0 -0
  73. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/lvol_events.py +0 -0
  74. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/mgmt_events.py +0 -0
  75. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/pool_events.py +0 -0
  76. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/snapshot_events.py +0 -0
  77. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/controllers/storage_events.py +0 -0
  78. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/__init__.py +0 -0
  79. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/base_model.py +0 -0
  80. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/caching_node.py +0 -0
  81. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/cluster.py +0 -0
  82. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/compute_node.py +0 -0
  83. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/deployer.py +0 -0
  84. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/global_settings.py +0 -0
  85. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/iface.py +0 -0
  86. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/lvol_model.py +0 -0
  87. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/mgmt_node.py +0 -0
  88. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/pool.py +0 -0
  89. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/port_stat.py +0 -0
  90. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/snapshot.py +0 -0
  91. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/models/stats.py +0 -0
  92. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/pci_utils.py +0 -0
  93. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/alerting/alert_rules.yaml +0 -0
  94. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/clean_local_storage_deploy.sh +0 -0
  95. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/config_docker.sh +0 -0
  96. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/dashboards/devices.json +0 -0
  97. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/dashboards/lvols.json +0 -0
  98. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/dashboards/node-exporter.json +0 -0
  99. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/dashboards/nodes.json +0 -0
  100. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/dashboards/pools.json +0 -0
  101. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/datasource.yml +0 -0
  102. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/db_config_double.sh +0 -0
  103. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/db_config_single.sh +0 -0
  104. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/prometheus.yml +0 -0
  105. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/run_ssh.sh +0 -0
  106. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/scripts/set_db_config.sh +0 -0
  107. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/__init__.py +0 -0
  108. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/caching_node_monitor.py +0 -0
  109. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/cap_monitor.py +0 -0
  110. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/install_service.sh +0 -0
  111. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/log_agg_service.py +0 -0
  112. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/mgmt_node_monitor.py +0 -0
  113. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/remove_service.sh +0 -0
  114. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/services/service_template.service +0 -0
  115. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_core/shell_utils.py +0 -0
  116. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/__init__.py +0 -0
  117. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/app.py +0 -0
  118. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/auth_middleware.py +0 -0
  119. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/__init__.py +0 -0
  120. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/caching_node_ops.py +0 -0
  121. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/caching_node_ops_k8s.py +0 -0
  122. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/node_api_basic.py +0 -0
  123. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/node_api_caching_docker.py +0 -0
  124. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/node_api_caching_ks.py +0 -0
  125. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_caching_node.py +0 -0
  126. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_deployer.py +0 -0
  127. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_mgmt_node.py +0 -0
  128. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/blueprints/web_api_snapshot.py +0 -0
  129. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/caching_node_app.py +0 -0
  130. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/caching_node_app_k8s.py +0 -0
  131. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/node_webapp.py +0 -0
  132. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/snode_app.py +0 -0
  133. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/delete.py +0 -0
  134. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/deploy.py +0 -0
  135. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/deploy_cnode.yaml +0 -0
  136. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/deploy_spdk.yaml +0 -0
  137. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/is_up.py +0 -0
  138. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/list_deps.py +0 -0
  139. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/rpac.yaml +0 -0
  140. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/static/tst.py +0 -0
  141. {sbcli_pre-1.2.5 → sbcli_pre-1.2.6}/simplyblock_web/templates/deploy_spdk.yaml.j2 +0 -0
@@ -23,7 +23,7 @@ def _generate_string(length):
23
23
  string.ascii_letters + string.digits) for _ in range(length))
24
24
 
25
25
 
26
- def add_pool(name, pool_max, lvol_max, max_rw_iops, max_rw_mbytes, max_r_mbytes, max_w_mbytes, has_secret):
26
+ def add_pool(name, pool_max, lvol_max, max_rw_iops, max_rw_mbytes, max_r_mbytes, max_w_mbytes, has_secret, cluster_id):
27
27
 
28
28
  if not name:
29
29
  logger.error("Pool name is empty!")
@@ -34,6 +34,11 @@ def add_pool(name, pool_max, lvol_max, max_rw_iops, max_rw_mbytes, max_r_mbytes,
34
34
  logger.error(f"Pool found with the same name: {name}")
35
35
  return False
36
36
 
37
+ cluster = db_controller.get_cluster_by_id(cluster_id)
38
+ if not cluster:
39
+ logger.error(f"Cluster not found: {cluster_id}")
40
+ return False
41
+
37
42
  pool_max = pool_max or 0
38
43
  lvol_max = lvol_max or 0
39
44
  max_rw_iops = max_rw_iops or 0
@@ -46,7 +51,6 @@ def add_pool(name, pool_max, lvol_max, max_rw_iops, max_rw_mbytes, max_r_mbytes,
46
51
  logger.error("max_rw_mbytes must be greater than max_w_mbytes and max_r_mbytes")
47
52
  return False
48
53
 
49
- cluster = db_controller.get_clusters()[0]
50
54
  logger.info("Adding pool")
51
55
  pool = Pool()
52
56
  pool.id = str(uuid.uuid4())
@@ -136,8 +140,8 @@ def delete_pool(uuid):
136
140
  return True
137
141
 
138
142
 
139
- def list_pools(is_json):
140
- pools = db_controller.get_pools()
143
+ def list_pools(is_json, cluster_id=None):
144
+ pools = db_controller.get_pools(cluster_id)
141
145
  data = []
142
146
  for pool in pools:
143
147
  data.append({
@@ -49,7 +49,7 @@ def add(lvol_id, snapshot_name):
49
49
  ret = rpc_client.bdev_distrib_create(
50
50
  base_name, new_vuid, lvol.ndcs, lvol.npcs, num_blocks,
51
51
  lvol.distr_bs, lvol_controller.get_jm_names(snode), lvol.distr_chunk_bs,
52
- None, None, lvol.distr_page_size)
52
+ None, None, lvol.distr_page_size, dev_cpu_mask=snode.dev_cpu_mask)
53
53
  if not ret:
54
54
  logger.error("Failed to create Distr bdev")
55
55
  return False, "Failed to create Distr bdev"
@@ -119,7 +119,12 @@ def delete(snapshot_uuid):
119
119
  logger.error(f"Snapshot not found {snapshot_uuid}")
120
120
  return False
121
121
 
122
- for lvol in db_controller.get_lvols():
122
+ snode = db_controller.get_storage_node_by_id(snap.lvol.node_id)
123
+ if not snode:
124
+ logger.error(f"Storage node not found {snap.lvol.node_id}")
125
+ return False
126
+
127
+ for lvol in db_controller.get_lvols(snode.cluster_id):
123
128
  if lvol.cloned_from_snap and lvol.cloned_from_snap == snapshot_uuid:
124
129
  logger.warning(f"Soft delete snapshot with clones, lvol ID: {lvol.get_id()}")
125
130
  snap.deleted = True
@@ -227,7 +232,8 @@ def clone(snapshot_id, clone_name, new_size=0):
227
232
  name = f"distr_{new_vuid}_1"
228
233
  ret = rpc_client.bdev_distrib_create(
229
234
  name, new_vuid, lvol.ndcs, lvol.npcs, num_blocks,
230
- lvol.distr_bs, jm_names, lvol.distr_chunk_bs, None, None, lvol.distr_page_size)
235
+ lvol.distr_bs, jm_names, lvol.distr_chunk_bs, None, None, lvol.distr_page_size,
236
+ dev_cpu_mask=snode.dev_cpu_mask)
231
237
  if not ret:
232
238
  msg="Failed to create Distr bdev"
233
239
  logger.error(msg)
@@ -0,0 +1,103 @@
1
+ # coding=utf-8
2
+ import logging
3
+ import time
4
+ import uuid
5
+
6
+ from simplyblock_core import kv_store, constants, utils
7
+ from simplyblock_core.controllers import tasks_events
8
+ from simplyblock_core.models.job_schedule import JobSchedule
9
+
10
+ logger = logging.getLogger()
11
+ db_controller = kv_store.DBController()
12
+
13
+
14
+ def _validate_new_task_node_restart(cluster_id, node_id):
15
+ tasks = db_controller.get_job_tasks(cluster_id)
16
+ for task in tasks:
17
+ if task.function_name == JobSchedule.FN_NODE_RESTART and task.node_id == node_id:
18
+ if task.status != JobSchedule.STATUS_DONE:
19
+ logger.info(f"Task found, skip adding new task: {task.get_id()}")
20
+ return False
21
+ return True
22
+
23
+
24
+ def _validate_new_task_dev_restart(cluster_id, node_id, device_id):
25
+ tasks = db_controller.get_job_tasks(cluster_id)
26
+ for task in tasks:
27
+ if task.function_name == JobSchedule.FN_DEV_RESTART and task.device_id == device_id:
28
+ if task.status != JobSchedule.STATUS_DONE:
29
+ logger.info(f"Task found, skip adding new task: {task.get_id()}")
30
+ return False
31
+ elif task.function_name == JobSchedule.FN_NODE_RESTART and task.node_id == node_id:
32
+ if task.status != JobSchedule.STATUS_DONE:
33
+ logger.info(f"Task found, skip adding new task: {task.get_id()}")
34
+ return False
35
+ return True
36
+
37
+
38
+ def _add_task(function_name, cluster_id, node_id, device_id):
39
+
40
+ if function_name in [JobSchedule.FN_DEV_RESTART, JobSchedule.FN_DEV_MIG]:
41
+ if not _validate_new_task_dev_restart(cluster_id, node_id, device_id):
42
+ return False
43
+ elif function_name == JobSchedule.FN_NODE_RESTART:
44
+ if not _validate_new_task_node_restart(cluster_id, node_id):
45
+ return False
46
+
47
+ task_obj = JobSchedule()
48
+ task_obj.uuid = str(uuid.uuid4())
49
+ task_obj.cluster_id = cluster_id
50
+ task_obj.node_id = node_id
51
+ task_obj.device_id = device_id
52
+ task_obj.date = int(time.time())
53
+ task_obj.function_name = function_name
54
+ task_obj.status = JobSchedule.STATUS_NEW
55
+ task_obj.write_to_db(db_controller.kv_store)
56
+ tasks_events.task_create(task_obj)
57
+ return task_obj.uuid
58
+
59
+
60
+ def add_device_mig_task(device_id):
61
+ device = db_controller.get_storage_devices(device_id)
62
+ return _add_task(JobSchedule.FN_DEV_MIG, device.cluster_id, device.node_id, device.get_id())
63
+
64
+
65
+ def add_device_to_auto_restart(device):
66
+ return _add_task(JobSchedule.FN_DEV_RESTART, device.cluster_id, device.node_id, device.get_id())
67
+
68
+
69
+ def add_node_to_auto_restart(node):
70
+ return _add_task(JobSchedule.FN_NODE_RESTART, node.cluster_id, node.get_id(), "")
71
+
72
+
73
+ def list_tasks(cluster_id):
74
+ cluster = db_controller.get_cluster_by_id(cluster_id)
75
+ if not cluster:
76
+ logger.error("Cluster not found: %s", cluster_id)
77
+ return False
78
+
79
+ data = []
80
+ tasks = db_controller.get_job_tasks(cluster_id)
81
+ for task in tasks:
82
+ data.append({
83
+ "Task ID": task.uuid,
84
+ "Target ID": task.device_id or task.node_id,
85
+ "Function": task.function_name,
86
+ "Retry": f"{task.retry}/{constants.TASK_EXEC_RETRY_COUNT}",
87
+ "Status": task.status,
88
+ "Result": task.function_result,
89
+ "Date": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(task.date)),
90
+ })
91
+ return utils.print_table(data)
92
+
93
+
94
+ def cancel_task(task_id):
95
+ task = db_controller.get_task_by_id(task_id)
96
+ if not task:
97
+ logger.error("Task not found: %s", task_id)
98
+ return False
99
+
100
+ task.canceled = True
101
+ task.write_to_db(db_controller.kv_store)
102
+ tasks_events.task_canceled(task)
103
+ return True
@@ -0,0 +1,37 @@
1
+ # coding=utf-8
2
+ import logging
3
+
4
+ from simplyblock_core.controllers import events_controller as ec
5
+ from simplyblock_core.kv_store import DBController
6
+
7
+ logger = logging.getLogger()
8
+ db_controller = DBController()
9
+
10
+
11
+ def _task_event(task, message, caused_by, event):
12
+ ec.log_event_cluster(
13
+ cluster_id=task.cluster_id,
14
+ domain=ec.DOMAIN_CLUSTER,
15
+ event=event,
16
+ db_object=task,
17
+ caused_by=caused_by,
18
+ message=message,
19
+ node_id=task.node_id,
20
+ status=task.status)
21
+
22
+
23
+ def task_create(task, caused_by=ec.CAUSED_BY_CLI):
24
+ _task_event(task, f"task created: {task.uuid}", caused_by, ec.EVENT_OBJ_CREATED)
25
+
26
+
27
+ def task_updated(task, caused_by=ec.CAUSED_BY_CLI):
28
+ _task_event(task, f"Task updated: {task.uuid}", caused_by, ec.EVENT_STATUS_CHANGE)
29
+
30
+
31
+ def task_status_change(task, new_state, old_status, caused_by=ec.CAUSED_BY_CLI):
32
+ _task_event(task, f"task status changed from: {old_status} to: {new_state}", caused_by, ec.EVENT_STATUS_CHANGE)
33
+
34
+
35
+ def task_canceled(task, caused_by=ec.CAUSED_BY_CLI):
36
+ _task_event(task, f"Task canceled: {task.uuid}", caused_by, ec.EVENT_STATUS_CHANGE)
37
+
@@ -10,8 +10,9 @@ from simplyblock_core.kv_store import DBController
10
10
  logger = logging.getLogger()
11
11
 
12
12
 
13
- def send_node_status_event(node_id, node_status):
13
+ def send_node_status_event(node, node_status):
14
14
  db_controller = DBController()
15
+ node_id = node.get_id()
15
16
  logging.info(f"Sending event updates, node: {node_id}, status: {node_status}")
16
17
  node_status_event = {
17
18
  "timestamp": datetime.datetime.now().isoformat("T", "seconds") + 'Z',
@@ -20,7 +21,7 @@ def send_node_status_event(node_id, node_status):
20
21
  "status": node_status}
21
22
  events = {"events": [node_status_event]}
22
23
  logger.debug(node_status_event)
23
- snodes = db_controller.get_storage_nodes()
24
+ snodes = db_controller.get_storage_nodes_by_cluster_id(node.cluster_id)
24
25
  for node in snodes:
25
26
  if node.status != node.STATUS_ONLINE:
26
27
  continue
@@ -29,8 +30,9 @@ def send_node_status_event(node_id, node_status):
29
30
  ret = rpc_client.distr_status_events_update(events)
30
31
 
31
32
 
32
- def send_dev_status_event(storage_ID, dev_status):
33
+ def send_dev_status_event(device, dev_status):
33
34
  db_controller = DBController()
35
+ storage_ID = device.cluster_device_order
34
36
  logging.info(f"Sending event updates, device: {storage_ID}, status: {dev_status}")
35
37
  node_status_event = {
36
38
  "timestamp": datetime.datetime.now().isoformat("T", "seconds") + 'Z',
@@ -39,7 +41,7 @@ def send_dev_status_event(storage_ID, dev_status):
39
41
  "status": dev_status}
40
42
  events = {"events": [node_status_event]}
41
43
  logger.debug(node_status_event)
42
- snodes = db_controller.get_storage_nodes()
44
+ snodes = db_controller.get_storage_nodes_by_cluster_id(device.cluster_id)
43
45
  for node in snodes:
44
46
  if node.status != node.STATUS_ONLINE:
45
47
  continue
@@ -52,7 +54,7 @@ def send_dev_status_event(storage_ID, dev_status):
52
54
 
53
55
  def disconnect_device(device):
54
56
  db_controller = DBController()
55
- snodes = db_controller.get_storage_nodes()
57
+ snodes = db_controller.get_storage_nodes_by_cluster_id(device.cluster_id)
56
58
  for node in snodes:
57
59
  if node.status != node.STATUS_ONLINE:
58
60
  continue
@@ -95,7 +97,9 @@ def get_distr_cluster_map(snodes, target_node):
95
97
  dev_map[dev.cluster_device_order] = {
96
98
  "UUID": dev.get_id(),
97
99
  "bdev_name": name,
98
- "status": dev.status}
100
+ "status": dev.status,
101
+ "physical_label": dev.physical_label
102
+ }
99
103
  dev_w_map.append({
100
104
  "weight": dev_w,
101
105
  "id": dev.cluster_device_order})
@@ -158,7 +162,7 @@ def parse_distr_cluster_map(map_string):
158
162
  "Actual Status": "",
159
163
  "Results": "",
160
164
  }
161
- sd = db_controller.get_storage_devices(device_id)
165
+ sd = db_controller.get_storage_device_by_id(device_id)
162
166
  if sd:
163
167
  data["Actual Status"] = sd.status
164
168
  if sd.status == status:
@@ -175,7 +179,7 @@ def parse_distr_cluster_map(map_string):
175
179
 
176
180
  def send_cluster_map_to_node(node):
177
181
  db_controller = DBController()
178
- snodes = db_controller.get_storage_nodes()
182
+ snodes = db_controller.get_storage_nodes_by_cluster_id(node.cluster_id)
179
183
  rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password)
180
184
  cluster_map_data = get_distr_cluster_map(snodes, node)
181
185
  cluster_map_data['UUID_node_target'] = node.get_id()
@@ -189,7 +193,7 @@ def send_cluster_map_to_node(node):
189
193
 
190
194
  def send_cluster_map_add_node(snode):
191
195
  db_controller = DBController()
192
- snodes = db_controller.get_storage_nodes()
196
+ snodes = db_controller.get_storage_nodes_by_cluster_id(snode.cluster_id)
193
197
  for node in snodes:
194
198
  if node.status != node.STATUS_ONLINE:
195
199
  continue
@@ -98,11 +98,19 @@ class DBController:
98
98
  nodes.append(n)
99
99
  return sorted(nodes, key=lambda x: x.create_dt)
100
100
 
101
+ def get_storage_node_by_system_id(self, system_id):
102
+ nodes = StorageNode().read_from_db(self.kv_store)
103
+ for node in nodes:
104
+ if node.system_uuid == system_id:
105
+ return node
106
+ return None
107
+
101
108
  def get_storage_node_by_id(self, id):
102
109
  ret = StorageNode().read_from_db(self.kv_store, id)
103
110
  if ret:
104
111
  return ret[0]
105
112
 
113
+ # todo: change this function for multi cluster
106
114
  def get_caching_nodes(self):
107
115
  ret = CachingNode().read_from_db(self.kv_store)
108
116
  ret = sorted(ret, key=lambda x: x.create_dt)
@@ -113,6 +121,12 @@ class DBController:
113
121
  if ret:
114
122
  return ret[0]
115
123
 
124
+ def get_caching_node_by_system_id(self, system_id):
125
+ nodes = CachingNode().read_from_db(self.kv_store)
126
+ for node in nodes:
127
+ if node.system_uuid == system_id:
128
+ return node
129
+
116
130
  def get_caching_node_by_hostname(self, hostname):
117
131
  nodes = self.get_caching_nodes()
118
132
  for node in nodes:
@@ -125,20 +139,15 @@ class DBController:
125
139
  if node.hostname == hostname:
126
140
  return node
127
141
 
128
- def get_storage_devices(self, id=""):
129
- # workaround because nvme devices are stored inside the node object itself.
142
+ def get_storage_device_by_id(self, id):
130
143
  nodes = self.get_storage_nodes()
131
- devices = []
132
- device = None
133
144
  for node in nodes:
134
- if node.nvme_devices:
135
- devices.extend(node.nvme_devices)
136
- for dev in node.nvme_devices:
137
- if dev.get_id() == id:
138
- device = dev
139
- if id:
140
- return device
141
- return devices
145
+ for dev in node.nvme_devices:
146
+ if dev.get_id() == id:
147
+ return dev
148
+
149
+ def get_storage_devices(self, id):
150
+ return self.get_storage_device_by_id(id)
142
151
 
143
152
  # Compute node functions
144
153
  def get_compute_node_by_id(self, id):
@@ -150,9 +159,15 @@ class DBController:
150
159
  ret = ComputeNode().read_from_db(self.kv_store)
151
160
  return ret
152
161
 
153
- def get_pools(self):
154
- ret = Pool().read_from_db(self.kv_store)
155
- return ret
162
+ def get_pools(self, cluster_id=None):
163
+ pools = []
164
+ if cluster_id:
165
+ for pool in Pool().read_from_db(self.kv_store):
166
+ if pool.cluster_id == cluster_id:
167
+ pools.append(pool)
168
+ else:
169
+ pools = Pool().read_from_db(self.kv_store)
170
+ return pools
156
171
 
157
172
  def get_pool_by_id(self, id):
158
173
  ret = Pool().read_from_db(self.kv_store, id)
@@ -165,9 +180,16 @@ class DBController:
165
180
  if pool.pool_name == name:
166
181
  return pool
167
182
 
168
- def get_lvols(self):
169
- ret = LVol().read_from_db(self.kv_store)
170
- return ret
183
+ def get_lvols(self, cluster_id=None):
184
+ lvols = []
185
+ if cluster_id:
186
+ for pool in self.get_pools(cluster_id):
187
+ if pool.cluster_id == cluster_id:
188
+ for lv_id in pool.lvols:
189
+ lvols.append(self.get_lvol_by_id(lv_id))
190
+ else:
191
+ lvols = LVol().read_from_db(self.kv_store)
192
+ return lvols
171
193
 
172
194
  def get_snapshots(self):
173
195
  ret = SnapShot().read_from_db(self.kv_store)
@@ -259,5 +281,10 @@ class DBController:
259
281
  def get_events(self, event_id=""):
260
282
  return EventObj().read_from_db(self.kv_store, id=event_id)
261
283
 
262
- def get_job_tasks(self, cluster_id):
263
- return JobSchedule().read_from_db(self.kv_store, id=cluster_id, reverse=True)
284
+ def get_job_tasks(self, cluster_id, reverse=True):
285
+ return JobSchedule().read_from_db(self.kv_store, id=cluster_id, reverse=reverse)
286
+
287
+ def get_task_by_id(self, task_id):
288
+ for task in self.get_job_tasks(""):
289
+ if task.uuid == task_id:
290
+ return task
@@ -0,0 +1,205 @@
1
+ # coding=utf-8
2
+ import json
3
+ import logging
4
+ import uuid
5
+ import time
6
+ import requests
7
+
8
+ import docker
9
+
10
+ from simplyblock_core import utils, scripts
11
+ from simplyblock_core.controllers import mgmt_events
12
+ from simplyblock_core.kv_store import DBController
13
+ from simplyblock_core.models.mgmt_node import MgmtNode
14
+
15
+
16
+ logger = logging.getLogger()
17
+
18
+
19
+ def deploy_mgmt_node(cluster_ip, cluster_id, ifname):
20
+
21
+ try:
22
+ resp = requests.get(f"http://{cluster_ip}/cluster/{cluster_id}")
23
+ resp_json = resp.json()
24
+ cluster_data = resp_json['results'][0]
25
+ logger.info(f"Cluster found! NQN:{cluster_data['nqn']}")
26
+ logger.debug(cluster_data)
27
+ except Exception as e:
28
+ logger.error("Error getting cluster data!")
29
+ logger.error(e)
30
+ return ""
31
+
32
+ logger.info("Installing dependencies...")
33
+ scripts.install_deps()
34
+ logger.info("Installing dependencies > Done")
35
+
36
+ if not ifname:
37
+ ifname = "eth0"
38
+
39
+ DEV_IP = utils.get_iface_ip(ifname)
40
+ if not DEV_IP:
41
+ logger.error(f"Error getting interface ip: {ifname}")
42
+ return False
43
+
44
+ logger.info(f"Node IP: {DEV_IP}")
45
+ ret = scripts.configure_docker(DEV_IP)
46
+
47
+ db_connection = cluster_data['db_connection']
48
+ scripts.set_db_config(db_connection)
49
+ time.sleep(1)
50
+ hostname = utils.get_hostname()
51
+ db_controller = DBController()
52
+ nodes = db_controller.get_mgmt_nodes(cluster_id=cluster_id)
53
+ if not nodes:
54
+ logger.error("No mgmt nodes was found in the cluster!")
55
+ return False
56
+ for node in nodes:
57
+ if node.hostname == hostname:
58
+ logger.error("Node already exists in the cluster")
59
+ return False
60
+
61
+ logger.info("Joining docker swarm...")
62
+ try:
63
+ cluster_docker = utils.get_docker_client(cluster_id)
64
+ docker_ip = cluster_docker.info()["Swarm"]["NodeAddr"]
65
+ join_token = cluster_docker.swarm.attrs['JoinTokens']['Manager']
66
+ node_docker = docker.DockerClient(base_url=f"tcp://{DEV_IP}:2375", version="auto")
67
+ if node_docker.info()["Swarm"]["LocalNodeState"] == "active":
68
+ logger.info("Node is part of another swarm, leaving swarm")
69
+ try:
70
+ cluster_docker.nodes.get(node_docker.info()["Swarm"]["NodeID"]).remove(force=True)
71
+ except:
72
+ pass
73
+ node_docker.swarm.leave(force=True)
74
+ time.sleep(5)
75
+
76
+ node_docker.swarm.join([f"{docker_ip}:2377"], join_token)
77
+
78
+ retries = 10
79
+ while retries > 0:
80
+ if node_docker.info()["Swarm"]["LocalNodeState"] == "active":
81
+ break
82
+ logger.info("Waiting for node to be active...")
83
+ retries -= 1
84
+ time.sleep(2)
85
+ logger.info("Joining docker swarm > Done")
86
+ time.sleep(5)
87
+
88
+ except Exception as e:
89
+ raise e
90
+
91
+ logger.info("Adding management node object")
92
+ node_id = add_mgmt_node(DEV_IP, cluster_id)
93
+
94
+ # check if ha setting is required
95
+ nodes = db_controller.get_mgmt_nodes(cluster_id=cluster_id)
96
+ if len(nodes) >= 3:
97
+ logger.info("Waiting for FDB container to be active...")
98
+ fdb_cont = None
99
+ retries = 30
100
+ while retries > 0 and fdb_cont is None:
101
+ logger.info("Looking for FDB container...")
102
+ for cont in node_docker.containers.list(all=True):
103
+ logger.debug(cont.attrs['Name'])
104
+ if cont.attrs['Name'].startswith("/app_fdb"):
105
+ fdb_cont = cont
106
+ break
107
+ if fdb_cont:
108
+ logger.info("FDB container found")
109
+ break
110
+ else:
111
+ retries -= 1
112
+ time.sleep(5)
113
+
114
+ if not fdb_cont:
115
+ logger.warning("FDB container was not found")
116
+ else:
117
+ retries = 10
118
+ while retries > 0:
119
+ info = node_docker.containers.get(fdb_cont.attrs['Id'])
120
+ status = info.attrs['State']["Status"]
121
+ is_running = info.attrs['State']["Running"]
122
+ if not is_running:
123
+ logger.info("Container is not running, waiting...")
124
+ time.sleep(3)
125
+ retries -= 1
126
+ else:
127
+ logger.info(f"Container status: {status}, Is Running: {is_running}")
128
+ break
129
+
130
+ logger.info("Configuring Double DB...")
131
+ time.sleep(3)
132
+ scripts.set_db_config_double()
133
+ for cl in db_controller.get_clusters():
134
+ cl.ha_type = "ha"
135
+ cl.write_to_db(db_controller.kv_store)
136
+
137
+ logger.info("Node joined the cluster")
138
+ return node_id
139
+
140
+
141
+ def add_mgmt_node(mgmt_ip, cluster_id=None):
142
+ db_controller = DBController()
143
+ hostname = utils.get_hostname()
144
+ node = db_controller.get_mgmt_node_by_hostname(hostname)
145
+ if node:
146
+ logger.error("Node already exists in the cluster")
147
+ return False
148
+
149
+ node = MgmtNode()
150
+ node.uuid = str(uuid.uuid4())
151
+ node.hostname = hostname
152
+ node.docker_ip_port = f"{mgmt_ip}:2375"
153
+ node.cluster_id = cluster_id
154
+ node.mgmt_ip = mgmt_ip
155
+ node.status = MgmtNode.STATUS_ONLINE
156
+ node.write_to_db(db_controller.kv_store)
157
+
158
+ mgmt_events.mgmt_add(node)
159
+ logger.info("Done")
160
+ return node.uuid
161
+
162
+
163
+ def list_mgmt_nodes(is_json):
164
+ db_controller = DBController()
165
+ nodes = db_controller.get_mgmt_nodes()
166
+ data = []
167
+ output = ""
168
+
169
+ for node in nodes:
170
+ logging.debug(node)
171
+ logging.debug("*" * 20)
172
+ data.append({
173
+ "UUID": node.get_id(),
174
+ "Hostname": node.hostname,
175
+ "IP": node.mgmt_ip,
176
+ "Status": node.status,
177
+ })
178
+
179
+ if not data:
180
+ return output
181
+
182
+ if is_json:
183
+ output = json.dumps(data, indent=2)
184
+ else:
185
+ output = utils.print_table(data)
186
+ return output
187
+
188
+
189
+ def remove_mgmt_node(uuid):
190
+ db_controller = DBController()
191
+ snode = db_controller.get_mgmt_node_by_id(uuid)
192
+ if not snode:
193
+ logger.error("can not find node")
194
+ return False
195
+
196
+ logging.info("Removing mgmt node")
197
+ snode.remove(db_controller.kv_store)
198
+
199
+ logger.info("Leaving swarm...")
200
+ node_docker = docker.DockerClient(base_url=f"tcp://{snode.docker_ip_port}", version="auto")
201
+ node_docker.swarm.leave()
202
+
203
+ mgmt_events.mgmt_remove(snode)
204
+ logging.info("done")
205
+
@@ -1,4 +1,6 @@
1
1
  # coding=utf-8
2
+ from datetime import datetime
3
+
2
4
  from simplyblock_core.models.base_model import BaseModel
3
5
 
4
6
 
@@ -25,7 +27,7 @@ class EventObj(BaseModel):
25
27
  "uuid": {"type": str, 'default': ""},
26
28
  "cluster_uuid": {"type": str, 'default': ""},
27
29
  "node_id": {"type": str, 'default': ""},
28
- "date": {"type": int, 'default': 0},
30
+ "date": {"type": int, 'default': 0}, # in milliseconds
29
31
 
30
32
  "event_level": {"type": str, 'default': LEVEL_INFO},
31
33
 
@@ -49,3 +51,9 @@ class EventObj(BaseModel):
49
51
 
50
52
  def get_id(self):
51
53
  return "%s/%s/%s" % (self.cluster_uuid, self.date, self.uuid)
54
+
55
+ def get_date_string(self):
56
+ if self.date > 1e10:
57
+ return str(datetime.fromtimestamp(self.date/1000))
58
+ else:
59
+ return str(datetime.fromtimestamp(self.date))
@@ -8,6 +8,10 @@ class JobSchedule(BaseModel):
8
8
  STATUS_RUNNING = 'running'
9
9
  STATUS_DONE = 'done'
10
10
 
11
+ FN_DEV_RESTART = "device_restart"
12
+ FN_NODE_RESTART = "node_restart"
13
+ FN_DEV_MIG = "device_migration"
14
+
11
15
  attributes = {
12
16
  "uuid": {"type": str, 'default': ""},
13
17
  "cluster_id": {"type": str, 'default': ""},
@@ -15,6 +19,8 @@ class JobSchedule(BaseModel):
15
19
  "device_id": {"type": str, 'default': ""},
16
20
  "date": {"type": int, 'default': 0},
17
21
 
22
+ "canceled": {"type": bool, 'default': False},
23
+
18
24
  "function_name": {"type": str, 'default': ""},
19
25
  "function_params": {"type": dict, 'default': {}},
20
26
  "function_result": {"type": str, 'default': ""},