Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support org storage size parameter #2560

Merged
merged 4 commits into from
Jan 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.D/2560.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support organization storage size parameter.
1 change: 1 addition & 0 deletions CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ Name | Description|
|_\--default-credits AMOUNT_|Default credits amount to set \(`unlimited' stands for no limit) \[default: unlimited]|
|_\--default-jobs AMOUNT_|Default maximum running jobs quota \(`unlimited' stands for no limit) \[default: unlimited]|
|_\-j, --jobs AMOUNT_|Maximum running jobs quota \(`unlimited' stands for no limit) \[default: unlimited]|
|_\--storage-size AMOUNT_|Storage size, ignored for storage types with elastic storage size|



Expand Down
1 change: 1 addition & 0 deletions neuro-cli/docs/admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ Add org access to specified cluster.
| _--default-credits AMOUNT_ | Default credits amount to set \(`unlimited' stands for no limit\) _\[default: unlimited\]_ |
| _--default-jobs AMOUNT_ | Default maximum running jobs quota \(`unlimited' stands for no limit\) _\[default: unlimited\]_ |
| _-j, --jobs AMOUNT_ | Maximum running jobs quota \(`unlimited' stands for no limit\) _\[default: unlimited\]_ |
| _--storage-size AMOUNT_ | Storage size, ignored for storage types with elastic storage size |



Expand Down
25 changes: 21 additions & 4 deletions neuro-cli/src/neuro_cli/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ async def generate_cluster_config(root: Root, config: str, type: str) -> None:
max_size: 1
storage:
id: generalpurpose_bursting
instances:
- {}
"""


Expand Down Expand Up @@ -334,6 +336,8 @@ async def generate_aws(session: PromptSession[str]) -> str:
gpu_model: nvidia-tesla-v100
storage:
id: gcs-nfs
instances:
- {}
"""


Expand Down Expand Up @@ -372,7 +376,8 @@ async def generate_gcp(session: PromptSession[str]) -> str:
max_size: 1
storage:
id: premium_lrs
file_share_size_gib: {file_share_size_gib}
instances:
- size_mb: {file_share_size_mb}
"""


Expand All @@ -391,9 +396,10 @@ async def generate_azure(session: PromptSession[str]) -> str:
"Azure client secret: ", default=os.environ.get("AZURE_CLIENT_SECRET", "")
)
args["resource_group"] = await session.prompt_async("Azure resource group: ")
args["file_share_size_gib"] = await session.prompt_async(
args["file_share_size_gb"] = await session.prompt_async(
"Azure Files storage size (Gib): "
)
args["file_share_size_mb"] = args["file_share_size_gb"] * 1024
return AZURE_TEMPLATE.format_map(args)


Expand Down Expand Up @@ -426,7 +432,9 @@ async def generate_azure(session: PromptSession[str]) -> str:
disk_size_gb: 100
storage:
profile_name: {storage_profile_name}
size_gib: {storage_size_gib}
size_gib: {storage_size_gb}
instances:
- size_mb: {storage_size_mb}
"""


Expand Down Expand Up @@ -481,7 +489,8 @@ async def generate_vcd(root: Root, session: PromptSession[str]) -> str:
"Storage profile: ",
default=(cloud_provider.get("storage_profile_names") or [""])[0],
)
args["storage_size_gib"] = await session.prompt_async("Storage size (Gib): ")
args["storage_size_gb"] = await session.prompt_async("Storage size (Gib): ")
args["storage_size_mb"] = args["storage_size_gb"] * 1024
args["kubernetes_node_pool_id"] = cloud_provider["kubernetes_node_pool_id"]
args["platform_node_pool_id"] = cloud_provider["platform_node_pool_id"]
return VCD_TEMPLATE.format_map(args)
Expand Down Expand Up @@ -1259,6 +1268,12 @@ async def get_org_clusters(root: Root, cluster_name: str) -> None:
show_default=True,
help="Default maximum running jobs quota (`unlimited' stands for no limit)",
)
@option(
"--storage-size",
metavar="AMOUNT",
type=MEGABYTE,
help="Storage size, ignored for storage types with elastic storage size",
)
async def add_org_cluster(
root: Root,
cluster_name: str,
Expand All @@ -1267,6 +1282,7 @@ async def add_org_cluster(
jobs: str,
default_credits: str,
default_jobs: str,
storage_size: Optional[int],
) -> None:
"""
Add org access to specified cluster.
Expand All @@ -1279,6 +1295,7 @@ async def add_org_cluster(
quota=_Quota(total_running_jobs=_parse_jobs_value(jobs)),
default_credits=_parse_credits_value(default_credits),
default_quota=_Quota(_parse_jobs_value(default_jobs)),
storage_size_mb=storage_size,
)
if not root.quiet:
root.print(
Expand Down
46 changes: 33 additions & 13 deletions neuro-cli/src/neuro_cli/formatters/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
_Org,
_OrgCluster,
_OrgUserWithInfo,
_Storage,
)

from neuro_cli.formatters.config import format_quota_details
Expand Down Expand Up @@ -155,7 +156,13 @@ def __call__(
),
)
if cloud_provider.storage:
table.add_row("Storage", cloud_provider.storage.description)
table.add_row(
"Storage",
Styled(
_format_storage(cloud_provider.storage),
style="reset",
),
)
else:
table.add_row("Status", "Setup failed (not found in platform-config)")
if admin_cluster:
Expand All @@ -179,7 +186,6 @@ def __call__(
def _format_node_pools(node_pools: Iterable[_NodePool]) -> Table:
is_scalable = _is_scalable(node_pools)
has_preemptible = _has_preemptible(node_pools)
has_tpu = _has_tpu(node_pools)
has_idle = _has_idle(node_pools)

table = Table(
Expand All @@ -193,8 +199,6 @@ def _format_node_pools(node_pools: Iterable[_NodePool]) -> Table:
if has_preemptible:
table.add_column("Preemptible", justify="center")
table.add_column("GPU", justify="right")
if has_tpu:
table.add_column("TPU", justify="center")
if is_scalable:
table.add_column("Min", justify="right")
table.add_column("Max", justify="right")
Expand All @@ -219,8 +223,6 @@ def _format_node_pools(node_pools: Iterable[_NodePool]) -> Table:
if has_preemptible:
row.append("√" if node_pool.is_preemptible else "×")
row.append(_gpu(node_pool))
if has_tpu:
row.append("√" if node_pool.is_tpu_enabled else "×")
if is_scalable:
row.append(str(node_pool.min_size))
row.append(str(node_pool.max_size))
Expand All @@ -231,6 +233,31 @@ def _format_node_pools(node_pools: Iterable[_NodePool]) -> Table:
return table


def _format_storage(storage: _Storage) -> Table:
table = Table(
box=box.SIMPLE_HEAVY,
show_edge=True,
)
table.add_column("Name", style="bold", justify="left")
table.add_column("Type", style="bold", justify="left")
for instance in storage.instances:
if instance.size_mb is not None:
table.add_column("Size", style="bold", justify="left")
has_size = True
break
else:
has_size = False
for instance in storage.instances:
row = [instance.name or "<default>", storage.description]
if has_size:
if instance.size_mb is None:
row.append("")
else:
row.append(format_size(instance.size_mb * 1024 ** 2))
table.add_row(*row)
return table


def _is_scalable(node_pools: Iterable[_NodePool]) -> bool:
for node_pool in node_pools:
if node_pool.min_size != node_pool.max_size:
Expand All @@ -245,13 +272,6 @@ def _has_preemptible(node_pools: Iterable[_NodePool]) -> bool:
return False


def _has_tpu(node_pools: Iterable[_NodePool]) -> bool:
for node_pool in node_pools:
if node_pool.is_tpu_enabled:
return True
return False


def _has_idle(node_pools: Iterable[_NodePool]) -> bool:
for node_pool in node_pools:
if node_pool.idle_size:
Expand Down
12 changes: 12 additions & 0 deletions neuro-cli/tests/e2e/test_e2e_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ def test_remove_org_user_does_not_exist(helper: Helper, tmp_test_org: str) -> No


@pytest.mark.e2e
@pytest.mark.skip
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skip cluster-org tests for now as they require infrastructure provisioning until some kind of fake cluster is implemented.

def test_list_org_clusters(
helper: Helper, tmp_test_org: str, tmp_test_cluster: str
) -> None:
Expand All @@ -388,6 +389,7 @@ def test_list_org_clusters(


@pytest.mark.e2e
@pytest.mark.skip
def test_remove_org_cluster(
helper: Helper, tmp_test_org: str, tmp_test_cluster: str
) -> None:
Expand All @@ -413,6 +415,7 @@ def tmp_test_org_cluster(


@pytest.mark.e2e
@pytest.mark.skip
def test_list_org_cluster_users_added_members(
helper: Helper, tmp_test_org_cluster: Tuple[str, str], test_user_names: List[str]
) -> None:
Expand All @@ -437,6 +440,7 @@ def test_list_org_cluster_users_added_members(


@pytest.mark.e2e
@pytest.mark.skip
def test_remove_org_cluster_user_remove_oneself(
helper: Helper,
tmp_test_org_cluster: Tuple[str, str],
Expand All @@ -461,6 +465,7 @@ def test_remove_org_cluster_user_remove_oneself(


@pytest.mark.e2e
@pytest.mark.skip
def test_add_org_cluster_user_non_org_user_fails(
helper: Helper, tmp_test_org_cluster: Tuple[str, str], test_user_names: List[str]
) -> None:
Expand All @@ -483,6 +488,7 @@ def test_add_org_cluster_user_non_org_user_fails(


@pytest.mark.e2e
@pytest.mark.skip
def test_org_cluster_user_default_unlimited_quota(
helper: Helper, tmp_test_org_cluster: Tuple[str, str], test_user_names: List[str]
) -> None:
Expand All @@ -500,6 +506,7 @@ def test_org_cluster_user_default_unlimited_quota(


@pytest.mark.e2e
@pytest.mark.skip
def test_org_cluster_user_set_quota_during_add(
helper: Helper, tmp_test_org_cluster: Tuple[str, str], test_user_names: List[str]
) -> None:
Expand Down Expand Up @@ -529,6 +536,7 @@ def test_org_cluster_user_set_quota_during_add(


@pytest.mark.e2e
@pytest.mark.skip
def test_org_cluster_user_default_set_balance_and_quota(
helper: Helper, tmp_test_org_cluster: Tuple[str, str], test_user_names: List[str]
) -> None:
Expand Down Expand Up @@ -570,6 +578,7 @@ def test_org_cluster_user_default_set_balance_and_quota(


@pytest.mark.e2e
@pytest.mark.skip
def test_org_cluster_default_unlimited_quota(
helper: Helper,
tmp_test_cluster: str,
Expand All @@ -584,6 +593,7 @@ def test_org_cluster_default_unlimited_quota(


@pytest.mark.e2e
@pytest.mark.skip
def test_org_cluster_set_quota_during_add(
helper: Helper,
tmp_test_cluster: str,
Expand All @@ -609,6 +619,7 @@ def test_org_cluster_set_quota_during_add(


@pytest.mark.e2e
@pytest.mark.skip
def test_org_cluster_set_balance_and_quota(
helper: Helper,
tmp_test_cluster: str,
Expand Down Expand Up @@ -636,6 +647,7 @@ def test_org_cluster_set_balance_and_quota(


@pytest.mark.e2e
@pytest.mark.skip
def test_org_cluster_set_balance_and_quota_to_unlimited(
helper: Helper,
tmp_test_cluster: str,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
default
Status Deployed
Cloud gcp
Region us-central1
Zones us-central1-a, us-central1-c
Storage Filestore
default
Status Deployed
Cloud gcp
Region us-central1
Zones us-central1-a, us-central1-c
Storage
Name Type Size
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
<default> Filestore 1.0G
org Filestore 2.0G

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
default
Status Deployed
Cloud gcp
Region us-central1
Zones us-central1-a, us-central1-c
Storage
Name Type
━━━━━━━━━━━━━━━━━━━━━━━
<default> Filestore
org Filestore

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
default
Status Deployed
Cloud gcp
Region us-central1
Node pools
Machine CPU Memory Disk Preemptible GPU TPU Min Max Idle
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
n1-highmem-8 7.0 45.0G 150.0G √ 1 2 1
n1-highmem-8 7.0 45.0G 150.0G × × 1 2 0
default
Status Deployed
Cloud gcp
Region us-central1
Node pools
Machine CPU Memory Disk Preemptible GPU Min Max Idle
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
n1-highmem-8 7.0 45.0G 150.0G √ 1 2 1
n1-highmem-8 7.0 45.0G 150.0G × 1 2 0

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Loading