sbcli-dev 3.9.1__zip → 3.9.3__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.
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/PKG-INFO +1 -1
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/env_var +1 -1
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/sbcli_dev.egg-info/PKG-INFO +1 -1
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/cluster_ops.py +4 -1
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/lvol_controller.py +5 -19
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/distr_controller.py +4 -4
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/kv_store.py +6 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/base_model.py +4 -1
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/health_check_service.py +5 -2
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/storage_node_ops.py +59 -73
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_lvol.py +1 -1
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_storage_node.py +3 -3
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/README.md +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/pyproject.toml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/sbcli_dev.egg-info/SOURCES.txt +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/sbcli_dev.egg-info/dependency_links.txt +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/sbcli_dev.egg-info/entry_points.txt +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/sbcli_dev.egg-info/requires.txt +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/sbcli_dev.egg-info/top_level.txt +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/setup.cfg +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/setup.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_cli/cli.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_cli/main.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/__init__.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/cnode_client.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/compute_node_ops.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/constants.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/__init__.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/caching_node_controller.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/cluster_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/device_controller.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/device_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/events_controller.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/health_controller.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/lvol_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/mgmt_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/pool_controller.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/pool_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/snapshot_controller.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/snapshot_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/storage_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/tasks_controller.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/controllers/tasks_events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/mgmt_node_ops.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/__init__.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/caching_node.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/cluster.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/compute_node.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/deployer.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/events.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/global_settings.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/iface.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/job_schedule.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/lvol_model.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/mgmt_node.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/nvme_device.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/pool.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/port_stat.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/snapshot.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/stats.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/models/storage_node.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/pci_utils.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/rpc_client.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/__init__.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/alerting/alert_resources.yaml.j2 +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/alerting/alert_rules.yaml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/clean_local_storage_deploy.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/config_docker.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/dashboard.yml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/dashboards/cluster.json +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/dashboards/devices.json +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/dashboards/lvols.json +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/dashboards/node-exporter.json +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/dashboards/nodes.json +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/dashboards/pools.json +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/datasource.yml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/db_config_double.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/db_config_single.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/deploy_stack.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/docker-compose-swarm-monitoring.yml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/docker-compose-swarm.yml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/haproxy.cfg +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/install_deps.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/objstore.yml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/prometheus.yml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/run_ssh.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/set_db_config.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/stack_deploy_wait.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/__init__.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/cached_lvol_stat_collector.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/caching_node_monitor.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/cap_monitor.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/capacity_and_stats_collector.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/device_monitor.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/distr_event_collector.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/install_service.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/log_agg_service.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/lvol_monitor.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/lvol_stat_collector.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/main_distr_event_collector.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/mgmt_node_monitor.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/new_device_discovery.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/port_stat_collector.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/remove_service.sh +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/service_template.service +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/spdk_http_proxy_server.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/storage_node_monitor.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/tasks_runner_failed_migration.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/tasks_runner_migration.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/tasks_runner_new_dev_migration.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/tasks_runner_node_add.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/tasks_runner_restart.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/shell_utils.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/snode_client.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/utils.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/__init__.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/app.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/auth_middleware.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/__init__.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/caching_node_ops.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/caching_node_ops_k8s.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/node_api_basic.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/node_api_caching_docker.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/node_api_caching_ks.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/snode_ops.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/snode_ops_k8s.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_caching_node.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_cluster.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_deployer.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_device.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_mgmt_node.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_pool.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/blueprints/web_api_snapshot.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/caching_node_app.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/caching_node_app_k8s.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/node_utils.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/node_webapp.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/snode_app.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/snode_app_k8s.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/delete.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/deploy.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/deploy_cnode.yaml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/deploy_spdk.yaml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/is_up.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/list_deps.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/rpac.yaml +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/static/tst.py +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/templates/caching_deploy_spdk.yaml.j2 +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/templates/storage_deploy_spdk.yaml.j2 +0 -0
- {sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_web/utils.py +0 -0
|
@@ -170,7 +170,10 @@ def create_cluster(blk_size, page_size_in_blocks, cli_pass,
|
|
|
170
170
|
c.distr_bs = distr_bs
|
|
171
171
|
c.distr_chunk_bs = distr_chunk_bs
|
|
172
172
|
c.ha_type = ha_type
|
|
173
|
-
|
|
173
|
+
if grafana_endpoint:
|
|
174
|
+
c.grafana_endpoint = grafana_endpoint
|
|
175
|
+
else:
|
|
176
|
+
c.grafana_endpoint = f"http://{DEV_IP}/grafana"
|
|
174
177
|
c.enable_node_affinity = enable_node_affinity
|
|
175
178
|
|
|
176
179
|
alerts_template_folder = os.path.join(TOP_DIR, "simplyblock_core/scripts/alerting/")
|
|
@@ -165,25 +165,6 @@ def validate_add_lvol_func(name, size, host_id_or_name, pool_id_or_name,
|
|
|
165
165
|
return True, ""
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
def get_jm_names(snode):
|
|
169
|
-
return [snode.jm_device.jm_bdev] if snode.jm_device else []
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
def get_ha_jm_names(current_node, snode_list):
|
|
173
|
-
jm_list = []
|
|
174
|
-
if current_node.jm_device:
|
|
175
|
-
jm_list.append(current_node.jm_device.jm_bdev)
|
|
176
|
-
else:
|
|
177
|
-
jm_list.append("JM_LOCAL")
|
|
178
|
-
|
|
179
|
-
for node in snode_list:
|
|
180
|
-
if node.get_id() == current_node.get_id():
|
|
181
|
-
continue
|
|
182
|
-
name = f"remote_{node.jm_device.jm_bdev}n1"
|
|
183
|
-
jm_list.append(name)
|
|
184
|
-
return jm_list[:3]
|
|
185
|
-
|
|
186
|
-
|
|
187
168
|
def _get_next_3_nodes(cluster_id, lvol_size=0):
|
|
188
169
|
snodes = db_controller.get_storage_nodes_by_cluster_id(cluster_id)
|
|
189
170
|
# online_nodes = []
|
|
@@ -365,6 +346,11 @@ def add_lvol_ha(name, size, host_id_or_name, ha_type, pool_id_or_name, use_comp,
|
|
|
365
346
|
logger.error("Storage nodes are less than 3 in ha cluster")
|
|
366
347
|
return False, "Storage nodes are less than 3 in ha cluster"
|
|
367
348
|
|
|
349
|
+
if host_node and host_node.status != StorageNode.STATUS_ONLINE:
|
|
350
|
+
mgs = f"Storage node is not online. ID: {host_node.get_id()} status: {host_node.status}"
|
|
351
|
+
logger.error(mgs)
|
|
352
|
+
return False, mgs
|
|
353
|
+
|
|
368
354
|
cluster_size_prov_util = int(((cluster_size_prov+size) / cluster_size_total) * 100)
|
|
369
355
|
|
|
370
356
|
if cl.prov_cap_crit and cl.prov_cap_crit < cluster_size_prov_util:
|
|
@@ -27,7 +27,7 @@ def send_node_status_event(node, node_status):
|
|
|
27
27
|
if node.status != node.STATUS_ONLINE:
|
|
28
28
|
continue
|
|
29
29
|
logger.info(f"Sending to: {node.get_id()}")
|
|
30
|
-
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=
|
|
30
|
+
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=10)
|
|
31
31
|
ret = rpc_client.distr_status_events_update(events)
|
|
32
32
|
|
|
33
33
|
|
|
@@ -47,7 +47,7 @@ def send_dev_status_event(device, dev_status):
|
|
|
47
47
|
if node.status != node.STATUS_ONLINE:
|
|
48
48
|
continue
|
|
49
49
|
logger.info(f"Sending to: {node.get_id()}")
|
|
50
|
-
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=
|
|
50
|
+
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=10)
|
|
51
51
|
ret = rpc_client.distr_status_events_update(events)
|
|
52
52
|
if not ret:
|
|
53
53
|
logger.warning("Failed to send event update")
|
|
@@ -194,7 +194,7 @@ def parse_distr_cluster_map(map_string):
|
|
|
194
194
|
def send_cluster_map_to_node(node):
|
|
195
195
|
db_controller = DBController()
|
|
196
196
|
snodes = db_controller.get_storage_nodes_by_cluster_id(node.cluster_id)
|
|
197
|
-
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=
|
|
197
|
+
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=10)
|
|
198
198
|
cluster_map_data = get_distr_cluster_map(snodes, node)
|
|
199
199
|
cluster_map_data['UUID_node_target'] = node.get_id()
|
|
200
200
|
ret = rpc_client.distr_send_cluster_map(cluster_map_data)
|
|
@@ -212,7 +212,7 @@ def send_cluster_map_add_node(snode):
|
|
|
212
212
|
if node.status != node.STATUS_ONLINE:
|
|
213
213
|
continue
|
|
214
214
|
logger.info(f"Sending to: {node.get_id()}")
|
|
215
|
-
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=5
|
|
215
|
+
rpc_client = RPCClient(node.mgmt_ip, node.rpc_port, node.rpc_username, node.rpc_password, timeout=5)
|
|
216
216
|
|
|
217
217
|
cluster_map_data = get_distr_cluster_map([snode], node)
|
|
218
218
|
cl_map = {
|
|
@@ -316,3 +316,9 @@ class DBController:
|
|
|
316
316
|
for dev in snode.nvme_devices:
|
|
317
317
|
total_node_capacity += dev.size
|
|
318
318
|
return total_node_capacity
|
|
319
|
+
|
|
320
|
+
def get_jm_device_by_id(self, jm_id):
|
|
321
|
+
for node in self.get_storage_nodes():
|
|
322
|
+
if node.jm_device and node.jm_device.get_id() == jm_id:
|
|
323
|
+
return node.jm_device
|
|
324
|
+
return None
|
|
@@ -101,7 +101,10 @@ class BaseModel(object):
|
|
|
101
101
|
return objects[0]
|
|
102
102
|
return None
|
|
103
103
|
|
|
104
|
-
def write_to_db(self, kv_store):
|
|
104
|
+
def write_to_db(self, kv_store=None):
|
|
105
|
+
if not kv_store:
|
|
106
|
+
from simplyblock_core.kv_store import KVStore
|
|
107
|
+
kv_store = KVStore()
|
|
105
108
|
try:
|
|
106
109
|
prefix = "%s/%s/%s" % (self.object_type, self.name, self.get_id())
|
|
107
110
|
st = json.dumps(self.to_dict())
|
|
@@ -55,6 +55,9 @@ while True:
|
|
|
55
55
|
|
|
56
56
|
if snode.status not in [StorageNode.STATUS_ONLINE, StorageNode.STATUS_UNREACHABLE]:
|
|
57
57
|
logger.info(f"Node status is: {snode.status}, skipping")
|
|
58
|
+
set_node_health_check(snode, False)
|
|
59
|
+
for dev in snode.nvme_devices:
|
|
60
|
+
set_device_health_check(cluster_id, dev, False)
|
|
58
61
|
continue
|
|
59
62
|
|
|
60
63
|
# 1- check node ping
|
|
@@ -117,7 +120,7 @@ while True:
|
|
|
117
120
|
|
|
118
121
|
if snode.jm_device:
|
|
119
122
|
jm_device = snode.jm_device
|
|
120
|
-
logger.info(f"Node
|
|
123
|
+
logger.info(f"Node JM: {jm_device}")
|
|
121
124
|
ret = health_controller.check_jm_device(jm_device.get_id())
|
|
122
125
|
if ret:
|
|
123
126
|
logger.info(f"Checking jm bdev: {jm_device.jm_bdev} ... ok")
|
|
@@ -133,7 +136,7 @@ while True:
|
|
|
133
136
|
logger.info(f"Checking bdev: {remote_device.remote_bdev} ... ok")
|
|
134
137
|
else:
|
|
135
138
|
logger.info(f"Checking bdev: {remote_device.remote_bdev} ... not found")
|
|
136
|
-
node_remote_devices_check &= bool(ret)
|
|
139
|
+
# node_remote_devices_check &= bool(ret)
|
|
137
140
|
|
|
138
141
|
lvstore_check = True
|
|
139
142
|
if snode.lvstore and snode.lvstore_stack:
|
|
@@ -781,37 +781,45 @@ def _connect_to_remote_devs(this_node):
|
|
|
781
781
|
return remote_devices
|
|
782
782
|
|
|
783
783
|
|
|
784
|
-
def _connect_to_remote_jm_devs(this_node):
|
|
784
|
+
def _connect_to_remote_jm_devs(this_node, jm_ids=[]):
|
|
785
785
|
db_controller = DBController()
|
|
786
786
|
|
|
787
787
|
rpc_client = RPCClient(
|
|
788
788
|
this_node.mgmt_ip, this_node.rpc_port,
|
|
789
789
|
this_node.rpc_username, this_node.rpc_password, timeout=5, retry=2)
|
|
790
790
|
|
|
791
|
+
node_bdevs = rpc_client.get_bdevs()
|
|
792
|
+
node_bdev_names = [b['name'] for b in node_bdevs]
|
|
791
793
|
remote_devices = []
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
794
|
+
if jm_ids:
|
|
795
|
+
for jm_id in jm_ids:
|
|
796
|
+
jm_dev = db_controller.get_jm_device_by_id(jm_id)
|
|
797
|
+
remote_devices.append(jm_dev)
|
|
798
|
+
elif len(this_node.remote_jm_devices) > 0:
|
|
799
|
+
remote_devices = this_node.remote_jm_devices
|
|
800
|
+
else:
|
|
801
|
+
for node in db_controller.get_storage_nodes_by_cluster_id(this_node.cluster_id):
|
|
802
|
+
if node.get_id() == this_node.get_id() or node.status != StorageNode.STATUS_ONLINE:
|
|
803
|
+
continue
|
|
804
|
+
if node.jm_device:
|
|
805
|
+
remote_devices.append(node.jm_device)
|
|
806
|
+
|
|
807
|
+
for jm_dev in remote_devices:
|
|
808
|
+
name = f"remote_{jm_dev.jm_bdev}"
|
|
809
|
+
bdev_name = f"{name}n1"
|
|
810
|
+
jm_dev.remote_bdev = bdev_name
|
|
811
|
+
if bdev_name in node_bdev_names:
|
|
812
|
+
logger.info(f"bdev found {bdev_name}")
|
|
813
|
+
jm_dev.status = JMDevice.STATUS_ONLINE
|
|
814
|
+
else:
|
|
815
|
+
logger.info(f"Connecting {this_node.get_id()} to {name}")
|
|
816
|
+
ret = rpc_client.bdev_nvme_attach_controller_tcp(
|
|
817
|
+
name, jm_dev.nvmf_nqn, jm_dev.nvmf_ip, jm_dev.nvmf_port)
|
|
803
818
|
if ret:
|
|
804
|
-
|
|
819
|
+
jm_dev.status = JMDevice.STATUS_ONLINE
|
|
805
820
|
else:
|
|
806
|
-
logger.
|
|
807
|
-
|
|
808
|
-
name, node.jm_device.nvmf_nqn, node.jm_device.nvmf_ip, node.jm_device.nvmf_port)
|
|
809
|
-
if not ret:
|
|
810
|
-
logger.error(f"failed to connect to remote JM {node.jm_device.jm_bdev}")
|
|
811
|
-
continue
|
|
812
|
-
|
|
813
|
-
node.jm_device.remote_bdev = bdev_name
|
|
814
|
-
remote_devices.append(node.jm_device)
|
|
821
|
+
logger.error(f"failed to connect to remote JM {name}")
|
|
822
|
+
jm_dev.status = JMDevice.STATUS_UNAVAILABLE
|
|
815
823
|
|
|
816
824
|
return remote_devices
|
|
817
825
|
|
|
@@ -929,6 +937,9 @@ def add_node(cluster_id, node_ip, iface_name, data_nics_list,
|
|
|
929
937
|
except Exception:
|
|
930
938
|
pass
|
|
931
939
|
max_prov = int(utils.parse_size(max_prov))
|
|
940
|
+
if max_prov <= 0:
|
|
941
|
+
logger.error(f"Incorrect max-prov value {max_prov}")
|
|
942
|
+
return False
|
|
932
943
|
number_of_split = num_partitions_per_dev if num_partitions_per_dev else 1
|
|
933
944
|
number_of_alceml_devices = number_of_devices * number_of_split
|
|
934
945
|
# for jm
|
|
@@ -1206,7 +1217,8 @@ def add_node(cluster_id, node_ip, iface_name, data_nics_list,
|
|
|
1206
1217
|
else:
|
|
1207
1218
|
node.remote_devices.append(dev)
|
|
1208
1219
|
|
|
1209
|
-
if node.enable_ha_jm:
|
|
1220
|
+
if snode.jm_device and node.enable_ha_jm:
|
|
1221
|
+
node.remote_jm_devices.append(snode.jm_device)
|
|
1210
1222
|
node.remote_jm_devices = _connect_to_remote_jm_devs(node)
|
|
1211
1223
|
node.write_to_db(kv_store)
|
|
1212
1224
|
logger.info(f"connected to devices count: {len(node.remote_devices)}")
|
|
@@ -1445,6 +1457,9 @@ def restart_storage_node(
|
|
|
1445
1457
|
except Exception:
|
|
1446
1458
|
pass
|
|
1447
1459
|
snode.max_prov = int(utils.parse_size(max_prov))
|
|
1460
|
+
if snode.max_prov <= 0:
|
|
1461
|
+
logger.error(f"Incorrect max-prov value {max_prov}")
|
|
1462
|
+
return False
|
|
1448
1463
|
if spdk_image:
|
|
1449
1464
|
snode.spdk_image = spdk_image
|
|
1450
1465
|
|
|
@@ -2534,28 +2549,32 @@ def recreate_lvstore(snode):
|
|
|
2534
2549
|
return True
|
|
2535
2550
|
|
|
2536
2551
|
|
|
2537
|
-
def
|
|
2552
|
+
def get_next_ha_jms(current_node):
|
|
2538
2553
|
db_controller = DBController(KVStore())
|
|
2539
|
-
jm_list = []
|
|
2540
|
-
if current_node.jm_device:
|
|
2541
|
-
jm_list.append(current_node.jm_device.jm_bdev)
|
|
2542
|
-
else:
|
|
2543
|
-
jm_list.append("JM_LOCAL")
|
|
2544
|
-
|
|
2545
2554
|
jm_count = {}
|
|
2546
2555
|
for node in db_controller.get_storage_nodes_by_cluster_id(current_node.cluster_id):
|
|
2547
2556
|
if node.get_id() == current_node.get_id() or node.status != StorageNode.STATUS_ONLINE:
|
|
2548
2557
|
continue
|
|
2549
2558
|
if node.jm_device:
|
|
2550
|
-
jm_count[node.jm_device.
|
|
2559
|
+
jm_count[node.jm_device.get_id()] = 1 + jm_count.get(node.jm_device.get_id(), 0)
|
|
2551
2560
|
for rem_jm_device in node.remote_jm_devices:
|
|
2552
|
-
|
|
2561
|
+
if rem_jm_device.get_id() != current_node.jm_device.get_id():
|
|
2562
|
+
jm_count[rem_jm_device.get_id()] = 1 + jm_count.get(rem_jm_device.get_id(), 0)
|
|
2553
2563
|
|
|
2554
2564
|
jm_count = dict(sorted(jm_count.items(), key=lambda x: x[1]))
|
|
2565
|
+
return list(jm_count.keys())[:2]
|
|
2555
2566
|
|
|
2556
|
-
jm_list.append(f"remote_{list(jm_count.keys())[0].jm_bdev}n1")
|
|
2557
|
-
jm_list.append(f"remote_{list(jm_count.keys())[1].jm_bdev}n1")
|
|
2558
2567
|
|
|
2568
|
+
def get_node_jm_names(current_node):
|
|
2569
|
+
jm_list = []
|
|
2570
|
+
if current_node.jm_device:
|
|
2571
|
+
jm_list.append(current_node.jm_device.jm_bdev)
|
|
2572
|
+
else:
|
|
2573
|
+
jm_list.append("JM_LOCAL")
|
|
2574
|
+
|
|
2575
|
+
if current_node.enable_ha_jm:
|
|
2576
|
+
for jm_dev in current_node.remote_jm_devices[:2]:
|
|
2577
|
+
jm_list.append(f"remote_{jm_dev.jm_bdev}n1")
|
|
2559
2578
|
return jm_list
|
|
2560
2579
|
|
|
2561
2580
|
|
|
@@ -2569,13 +2588,10 @@ def create_lvstore(snode, ndcs, npcs, distr_bs, distr_chunk_bs, page_size_in_blo
|
|
|
2569
2588
|
strip_size_kb = utils.nearest_upper_power_of_2(strip_size_kb)
|
|
2570
2589
|
jm_vuid = 0
|
|
2571
2590
|
if snode.enable_ha_jm:
|
|
2572
|
-
if len(nodes) > 3:
|
|
2573
|
-
nodes = nodes[:3]
|
|
2574
|
-
jm_names = lvol_controller.get_ha_jm_names(snode, nodes)
|
|
2575
2591
|
jm_vuid = utils.get_random_vuid()
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2592
|
+
online_jms = get_next_ha_jms(snode)
|
|
2593
|
+
snode.remote_jm_devices = _connect_to_remote_jm_devs(snode, online_jms)
|
|
2594
|
+
snode.write_to_db()
|
|
2579
2595
|
|
|
2580
2596
|
for _ in range(snode.number_of_distribs):
|
|
2581
2597
|
distrib_vuid = utils.get_random_vuid()
|
|
@@ -2588,7 +2604,6 @@ def create_lvstore(snode, ndcs, npcs, distr_bs, distr_chunk_bs, page_size_in_blo
|
|
|
2588
2604
|
"name": distrib_name,
|
|
2589
2605
|
"params": {
|
|
2590
2606
|
"name": distrib_name,
|
|
2591
|
-
"jm_names": jm_names,
|
|
2592
2607
|
"jm_vuid": jm_vuid,
|
|
2593
2608
|
"vuid": distrib_vuid,
|
|
2594
2609
|
"ndcs": ndcs,
|
|
@@ -2616,14 +2631,6 @@ def create_lvstore(snode, ndcs, npcs, distr_bs, distr_chunk_bs, page_size_in_blo
|
|
|
2616
2631
|
},
|
|
2617
2632
|
"distribs_list": distrib_list
|
|
2618
2633
|
},
|
|
2619
|
-
# {
|
|
2620
|
-
# "type": "bdev_ptnonexcl",
|
|
2621
|
-
# "name": "raid_PT",
|
|
2622
|
-
# "params": {
|
|
2623
|
-
# "name": "raid_PT",
|
|
2624
|
-
# "base_bdev_name": raid_device
|
|
2625
|
-
# }
|
|
2626
|
-
# },
|
|
2627
2634
|
{
|
|
2628
2635
|
"type": "bdev_lvstore",
|
|
2629
2636
|
"name": lvs_name,
|
|
@@ -2645,13 +2652,11 @@ def create_lvstore(snode, ndcs, npcs, distr_bs, distr_chunk_bs, page_size_in_blo
|
|
|
2645
2652
|
logger.error(err)
|
|
2646
2653
|
return False
|
|
2647
2654
|
|
|
2648
|
-
|
|
2649
2655
|
snode.lvstore = lvs_name
|
|
2650
2656
|
snode.lvstore_stack = lvstore_stack
|
|
2651
2657
|
snode.raid = raid_device
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
time.sleep(3)
|
|
2658
|
+
snode.write_to_db()
|
|
2659
|
+
time.sleep(1)
|
|
2655
2660
|
return True
|
|
2656
2661
|
|
|
2657
2662
|
|
|
@@ -2671,6 +2676,7 @@ def _create_bdev_stack(snode, lvstore_stack=None):
|
|
|
2671
2676
|
params = bdev['params']
|
|
2672
2677
|
|
|
2673
2678
|
if type == "bdev_distr":
|
|
2679
|
+
params['jm_names'] = get_node_jm_names(snode)
|
|
2674
2680
|
if snode.distrib_cpu_cores:
|
|
2675
2681
|
distrib_cpu_mask = utils.decimal_to_hex_power_of_2(snode.distrib_cpu_cores[snode.distrib_cpu_index])
|
|
2676
2682
|
params['distrib_cpu_mask'] = distrib_cpu_mask
|
|
@@ -2687,26 +2693,6 @@ def _create_bdev_stack(snode, lvstore_stack=None):
|
|
|
2687
2693
|
|
|
2688
2694
|
elif type == "bdev_ptnonexcl":
|
|
2689
2695
|
ret = rpc_client.bdev_PT_NoExcl_create(**params)
|
|
2690
|
-
if ret:
|
|
2691
|
-
try:
|
|
2692
|
-
# add pass through
|
|
2693
|
-
pt_name = "raid_PT"
|
|
2694
|
-
subsystem_nqn = snode.subsystem + ":dev:raid"
|
|
2695
|
-
logger.info("creating raid subsystem %s", subsystem_nqn)
|
|
2696
|
-
ret = rpc_client.subsystem_create(subsystem_nqn, 'sbcli-cn', 'sbcli-cn')
|
|
2697
|
-
for iface in snode.data_nics:
|
|
2698
|
-
if iface.ip4_address:
|
|
2699
|
-
tr_type = iface.get_transport_type()
|
|
2700
|
-
logger.info("adding listener for %s on IP %s" % (subsystem_nqn, iface.ip4_address))
|
|
2701
|
-
ret = rpc_client.listeners_create(subsystem_nqn, tr_type, iface.ip4_address, "4420")
|
|
2702
|
-
break
|
|
2703
|
-
logger.info(f"add {pt_name} to subsystem")
|
|
2704
|
-
ret = rpc_client.nvmf_subsystem_add_ns(subsystem_nqn, pt_name)
|
|
2705
|
-
if not ret:
|
|
2706
|
-
logger.error(f"Failed to add: {pt_name} to the subsystem: {subsystem_nqn}")
|
|
2707
|
-
return False
|
|
2708
|
-
except:
|
|
2709
|
-
pass
|
|
2710
2696
|
|
|
2711
2697
|
elif type == "bdev_raid":
|
|
2712
2698
|
distribs_list = bdev["distribs_list"]
|
|
@@ -230,7 +230,7 @@ def resize_lvol(uuid):
|
|
|
230
230
|
|
|
231
231
|
cl_data = request.get_json()
|
|
232
232
|
if 'size' not in cl_data:
|
|
233
|
-
return utils.get_response(None, "missing required param:
|
|
233
|
+
return utils.get_response(None, "missing required param: size", 400)
|
|
234
234
|
|
|
235
235
|
new_size = utils.parse_size(cl_data['size'])
|
|
236
236
|
|
|
@@ -195,8 +195,8 @@ def storage_node_add():
|
|
|
195
195
|
max_lvol = int(req_data['max_lvol'])
|
|
196
196
|
max_snap = int(req_data.get('max_snap', 500))
|
|
197
197
|
max_prov = req_data['max_prov']
|
|
198
|
-
number_of_distribs = req_data.get('number_of_distribs', 4)
|
|
199
|
-
|
|
198
|
+
number_of_distribs = int(req_data.get('number_of_distribs', 4))
|
|
199
|
+
disable_ha_jm = bool(req_data.get('disable_ha_jm', False))
|
|
200
200
|
|
|
201
201
|
spdk_image = None
|
|
202
202
|
if 'spdk_image' in req_data:
|
|
@@ -262,7 +262,7 @@ def storage_node_add():
|
|
|
262
262
|
"enable_test_device": False,
|
|
263
263
|
"number_of_distribs": number_of_distribs,
|
|
264
264
|
"namespace": namespace,
|
|
265
|
-
"enable_ha_jm":
|
|
265
|
+
"enable_ha_jm": not disable_ha_jm})
|
|
266
266
|
|
|
267
267
|
return utils.get_response(True)
|
|
268
268
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/alerting/alert_resources.yaml.j2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/scripts/docker-compose-swarm-monitoring.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/capacity_and_stats_collector.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/tasks_runner_failed_migration.py
RENAMED
|
File without changes
|
|
File without changes
|
{sbcli_dev-3.9.1 → sbcli_dev-3.9.3}/simplyblock_core/services/tasks_runner_new_dev_migration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|