idmtools-platform-comps 0.0.0.dev0__py3-none-any.whl → 0.0.2__py3-none-any.whl
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.
- idmtools_platform_comps/__init__.py +25 -8
- idmtools_platform_comps/cli/__init__.py +4 -0
- idmtools_platform_comps/cli/cli_functions.py +50 -0
- idmtools_platform_comps/cli/comps.py +492 -0
- idmtools_platform_comps/comps_cli.py +48 -0
- idmtools_platform_comps/comps_operations/__init__.py +6 -0
- idmtools_platform_comps/comps_operations/asset_collection_operations.py +263 -0
- idmtools_platform_comps/comps_operations/experiment_operations.py +569 -0
- idmtools_platform_comps/comps_operations/simulation_operations.py +678 -0
- idmtools_platform_comps/comps_operations/suite_operations.py +228 -0
- idmtools_platform_comps/comps_operations/workflow_item_operations.py +269 -0
- idmtools_platform_comps/comps_platform.py +309 -0
- idmtools_platform_comps/plugin_info.py +168 -0
- idmtools_platform_comps/ssmt_operations/__init__.py +6 -0
- idmtools_platform_comps/ssmt_operations/simulation_operations.py +77 -0
- idmtools_platform_comps/ssmt_operations/workflow_item_operations.py +73 -0
- idmtools_platform_comps/ssmt_platform.py +44 -0
- idmtools_platform_comps/ssmt_work_items/__init__.py +4 -0
- idmtools_platform_comps/ssmt_work_items/comps_work_order_task.py +29 -0
- idmtools_platform_comps/ssmt_work_items/comps_workitems.py +113 -0
- idmtools_platform_comps/ssmt_work_items/icomps_workflowitem.py +71 -0
- idmtools_platform_comps/ssmt_work_items/work_order.py +54 -0
- idmtools_platform_comps/utils/__init__.py +4 -0
- idmtools_platform_comps/utils/assetize_output/__init__.py +4 -0
- idmtools_platform_comps/utils/assetize_output/assetize_output.py +125 -0
- idmtools_platform_comps/utils/assetize_output/assetize_ssmt_script.py +144 -0
- idmtools_platform_comps/utils/base_singularity_work_order.json +6 -0
- idmtools_platform_comps/utils/download/__init__.py +4 -0
- idmtools_platform_comps/utils/download/download.py +178 -0
- idmtools_platform_comps/utils/download/download_ssmt.py +81 -0
- idmtools_platform_comps/utils/download_experiment.py +116 -0
- idmtools_platform_comps/utils/file_filter_workitem.py +519 -0
- idmtools_platform_comps/utils/general.py +358 -0
- idmtools_platform_comps/utils/linux_mounts.py +73 -0
- idmtools_platform_comps/utils/lookups.py +123 -0
- idmtools_platform_comps/utils/package_version.py +489 -0
- idmtools_platform_comps/utils/python_requirements_ac/__init__.py +4 -0
- idmtools_platform_comps/utils/python_requirements_ac/create_asset_collection.py +155 -0
- idmtools_platform_comps/utils/python_requirements_ac/install_requirements.py +109 -0
- idmtools_platform_comps/utils/python_requirements_ac/requirements_to_asset_collection.py +374 -0
- idmtools_platform_comps/utils/python_version.py +40 -0
- idmtools_platform_comps/utils/scheduling.py +154 -0
- idmtools_platform_comps/utils/singularity_build.py +491 -0
- idmtools_platform_comps/utils/spatial_output.py +76 -0
- idmtools_platform_comps/utils/ssmt_utils/__init__.py +6 -0
- idmtools_platform_comps/utils/ssmt_utils/common.py +70 -0
- idmtools_platform_comps/utils/ssmt_utils/file_filter.py +568 -0
- idmtools_platform_comps/utils/sweeping.py +162 -0
- idmtools_platform_comps-0.0.2.dist-info/METADATA +100 -0
- idmtools_platform_comps-0.0.2.dist-info/RECORD +62 -0
- idmtools_platform_comps-0.0.2.dist-info/entry_points.txt +9 -0
- idmtools_platform_comps-0.0.2.dist-info/licenses/LICENSE.TXT +3 -0
- {idmtools_platform_comps-0.0.0.dev0.dist-info → idmtools_platform_comps-0.0.2.dist-info}/top_level.txt +1 -0
- ssmt_image/Dockerfile +52 -0
- ssmt_image/Makefile +21 -0
- ssmt_image/__init__.py +6 -0
- ssmt_image/bootstrap.sh +30 -0
- ssmt_image/build_docker_image.py +161 -0
- ssmt_image/pip.conf +3 -0
- ssmt_image/push_docker_image.py +49 -0
- ssmt_image/requirements.txt +9 -0
- idmtools_platform_comps-0.0.0.dev0.dist-info/METADATA +0 -41
- idmtools_platform_comps-0.0.0.dev0.dist-info/RECORD +0 -5
- {idmtools_platform_comps-0.0.0.dev0.dist-info → idmtools_platform_comps-0.0.2.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""idmtools CompsWorkOrderTask.
|
|
2
|
+
|
|
3
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
4
|
+
"""
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from idmtools.assets import AssetCollection
|
|
7
|
+
from idmtools.entities.itask import ITask
|
|
8
|
+
from idmtools.entities.simulation import Simulation
|
|
9
|
+
from idmtools_platform_comps.ssmt_work_items.work_order import IWorkOrder
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class CompsWorkOrderTask(ITask):
|
|
14
|
+
"""
|
|
15
|
+
Defines a task that is purely work order driven, like Singularity build.
|
|
16
|
+
"""
|
|
17
|
+
work_order: IWorkOrder = field(default=None)
|
|
18
|
+
|
|
19
|
+
def gather_common_assets(self) -> AssetCollection:
|
|
20
|
+
"""Gather common assets."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
def gather_transient_assets(self) -> AssetCollection:
|
|
24
|
+
"""Gather transient assets."""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
def reload_from_simulation(self, simulation: Simulation):
|
|
28
|
+
"""Reload simulation."""
|
|
29
|
+
pass
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""idmtools SSMTWorkItem. This is the base of most comps workitems.
|
|
2
|
+
|
|
3
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
4
|
+
"""
|
|
5
|
+
from logging import getLogger, DEBUG
|
|
6
|
+
from dataclasses import dataclass, field, InitVar
|
|
7
|
+
from uuid import UUID
|
|
8
|
+
from idmtools.assets.file_list import FileList
|
|
9
|
+
from idmtools.entities.command_task import CommandTask
|
|
10
|
+
from idmtools_platform_comps.ssmt_work_items.icomps_workflowitem import ICOMPSWorkflowItem
|
|
11
|
+
|
|
12
|
+
logger = getLogger(__name__)
|
|
13
|
+
user_logger = getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class SSMTWorkItem(ICOMPSWorkflowItem):
|
|
18
|
+
"""
|
|
19
|
+
Defines the SSMT WorkItem.
|
|
20
|
+
|
|
21
|
+
Notes:
|
|
22
|
+
- We have lots of workitem bases. We need to consolidate these a bit.
|
|
23
|
+
"""
|
|
24
|
+
docker_image: str = field(default=None)
|
|
25
|
+
command: InitVar[str] = None
|
|
26
|
+
|
|
27
|
+
def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList, command: str):
|
|
28
|
+
"""Constructor."""
|
|
29
|
+
if command and not self.task:
|
|
30
|
+
self.task = CommandTask(command)
|
|
31
|
+
else:
|
|
32
|
+
user_logger.warning("You provided both a task and a command. Only using the task")
|
|
33
|
+
super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
|
|
34
|
+
|
|
35
|
+
self.work_item_type = self.work_item_type or 'DockerWorker'
|
|
36
|
+
|
|
37
|
+
def get_base_work_order(self):
|
|
38
|
+
"""
|
|
39
|
+
Builder basic work order.
|
|
40
|
+
|
|
41
|
+
Returns: work order as a dictionary
|
|
42
|
+
"""
|
|
43
|
+
base_wo = {
|
|
44
|
+
"WorkItem_Type": self.work_item_type,
|
|
45
|
+
"Execution": {
|
|
46
|
+
"ImageName": self.get_comps_ssmt_image_name(),
|
|
47
|
+
"Command": str(self.task.command)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return base_wo
|
|
52
|
+
|
|
53
|
+
def get_comps_ssmt_image_name(self):
|
|
54
|
+
"""
|
|
55
|
+
Build comps ssmt docker image name.
|
|
56
|
+
|
|
57
|
+
Returns: final validated name
|
|
58
|
+
"""
|
|
59
|
+
if self.docker_image:
|
|
60
|
+
return self.docker_image
|
|
61
|
+
|
|
62
|
+
if self.platform.docker_image:
|
|
63
|
+
return self.platform.docker_image
|
|
64
|
+
|
|
65
|
+
SSMT_PRODUCTION_IMAGE = 'docker-production.packages.idmod.org/idmtools/comps_ssmt_worker'
|
|
66
|
+
SSMT_STAGING_IMAGE = 'docker-staging.packages.idmod.org/idmtools/comps_ssmt_worker'
|
|
67
|
+
|
|
68
|
+
from idmtools_platform_comps.utils.package_version import get_latest_ssmt_image_version_from_artifactory
|
|
69
|
+
from idmtools_platform_comps import __version__
|
|
70
|
+
|
|
71
|
+
# Determine the default ssmt docker image
|
|
72
|
+
if "comps.idmod.org" in self.platform.endpoint.lower():
|
|
73
|
+
ssmt_image = SSMT_PRODUCTION_IMAGE
|
|
74
|
+
else:
|
|
75
|
+
ssmt_image = SSMT_STAGING_IMAGE
|
|
76
|
+
|
|
77
|
+
release = get_latest_ssmt_image_version_from_artifactory(base_version=__version__)
|
|
78
|
+
|
|
79
|
+
docker_image = f'{ssmt_image}:{release}'
|
|
80
|
+
if logger.isEnabledFor(DEBUG):
|
|
81
|
+
logger.debug(f'docker_image in use: {docker_image}')
|
|
82
|
+
|
|
83
|
+
return docker_image
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass
|
|
87
|
+
class InputDataWorkItem(ICOMPSWorkflowItem):
|
|
88
|
+
"""
|
|
89
|
+
Idm InputDataWorkItem.
|
|
90
|
+
|
|
91
|
+
Notes:
|
|
92
|
+
- TODO add examples
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList):
|
|
96
|
+
"""Constructor."""
|
|
97
|
+
super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
|
|
98
|
+
self.work_item_type = self.work_item_type or 'InputDataWorker'
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class VisToolsWorkItem(ICOMPSWorkflowItem):
|
|
103
|
+
"""
|
|
104
|
+
Idm VisToolsWorkItem.
|
|
105
|
+
|
|
106
|
+
Notes:
|
|
107
|
+
- TODO add examples
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList):
|
|
111
|
+
"""Constructor."""
|
|
112
|
+
super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
|
|
113
|
+
self.work_item_type = self.work_item_type or 'VisTools'
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""idmtools ICOMPSWorkflowItem.
|
|
2
|
+
|
|
3
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
4
|
+
"""
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
import json
|
|
7
|
+
from abc import ABC
|
|
8
|
+
from dataclasses import field, dataclass
|
|
9
|
+
from idmtools.assets.file_list import FileList
|
|
10
|
+
from idmtools.entities.iworkflow_item import IWorkflowItem
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class ICOMPSWorkflowItem(IWorkflowItem, ABC):
|
|
15
|
+
"""
|
|
16
|
+
Interface of idmtools work item.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
name: str = field(default="idmtools workflow item")
|
|
20
|
+
work_order: dict = field(default_factory=lambda: {})
|
|
21
|
+
work_item_type: str = field(default=None)
|
|
22
|
+
plugin_key: str = field(default="1.0.0.0_RELEASE")
|
|
23
|
+
|
|
24
|
+
def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList):
|
|
25
|
+
"""Constructor."""
|
|
26
|
+
super().__post_init__(item_name, asset_collection_id, asset_files, user_files)
|
|
27
|
+
self.work_order = self.work_order or {}
|
|
28
|
+
|
|
29
|
+
def __repr__(self):
|
|
30
|
+
"""Workitem as string."""
|
|
31
|
+
return f"<WorkItem {self.uid}>"
|
|
32
|
+
|
|
33
|
+
def get_base_work_order(self):
|
|
34
|
+
"""Get the base work order."""
|
|
35
|
+
base_wo = {"WorkItem_Type": self.work_item_type}
|
|
36
|
+
return base_wo
|
|
37
|
+
|
|
38
|
+
def load_work_order(self, wo_file):
|
|
39
|
+
"""Load work order from a file."""
|
|
40
|
+
self.work_order = json.load(open(wo_file, 'rb'))
|
|
41
|
+
|
|
42
|
+
def set_work_order(self, wo):
|
|
43
|
+
"""
|
|
44
|
+
Update wo for the name with value.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
wo: user wo
|
|
48
|
+
Returns: None
|
|
49
|
+
"""
|
|
50
|
+
self.work_order = wo
|
|
51
|
+
|
|
52
|
+
def update_work_order(self, name, value):
|
|
53
|
+
"""
|
|
54
|
+
Update wo for the name with value.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
name: wo arg name
|
|
58
|
+
value: wo arg value
|
|
59
|
+
|
|
60
|
+
Returns: None
|
|
61
|
+
"""
|
|
62
|
+
self.work_order[name] = value
|
|
63
|
+
|
|
64
|
+
def clear_wo_args(self):
|
|
65
|
+
"""
|
|
66
|
+
Clear all existing wo args.
|
|
67
|
+
|
|
68
|
+
Returns: None
|
|
69
|
+
|
|
70
|
+
"""
|
|
71
|
+
self.work_order = {}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""idmtools WorkOrder classes.
|
|
2
|
+
|
|
3
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
4
|
+
"""
|
|
5
|
+
from abc import ABC
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import List, Dict
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass()
|
|
11
|
+
class IWorkOrder(ABC):
|
|
12
|
+
"""Base workorder type."""
|
|
13
|
+
WorkItem_Type: str = field()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass()
|
|
17
|
+
class ExecutionDefinition:
|
|
18
|
+
"""Define the execution definition for workorders."""
|
|
19
|
+
Command: str = field()
|
|
20
|
+
ImageName: str = field(default='DockerWorker')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass()
|
|
24
|
+
class DockerWorkOrder(IWorkOrder):
|
|
25
|
+
"""Define the docker worker."""
|
|
26
|
+
WorkItem_Type: str = field(default='DockerWorker')
|
|
27
|
+
Execution: ExecutionDefinition = field(default_factory=ExecutionDefinition)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass()
|
|
31
|
+
class BuildFlags:
|
|
32
|
+
"""Define build flags."""
|
|
33
|
+
section: List[str] = field(default_factory=lambda: ['all'])
|
|
34
|
+
library: str = field(default='https://library.sylabs.io')
|
|
35
|
+
Switches: List['str'] = field(default_factory=lambda: [])
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass()
|
|
39
|
+
class BuildDefinition:
|
|
40
|
+
"""Define options for build definitions."""
|
|
41
|
+
Type: str = field(default='singularity')
|
|
42
|
+
Input: str = field(default=None)
|
|
43
|
+
Flags: BuildFlags = field(default_factory=BuildFlags)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass()
|
|
47
|
+
class ImageBuilderWorkOrder(IWorkOrder):
|
|
48
|
+
"""Defines our Image Builder service workorder."""
|
|
49
|
+
WorkItem_Type: str = field(default='ImageBuilderWorker')
|
|
50
|
+
Build: str = field(default=BuildDefinition)
|
|
51
|
+
Output: str = field(default='image.sif')
|
|
52
|
+
Tags: Dict[str, str] = field(default_factory=lambda: dict(type='singularity'))
|
|
53
|
+
AdditionalMounts: List[str] = field(default_factory=list)
|
|
54
|
+
StaticEnvironment: Dict[str, str] = field(default_factory=dict)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""idmtools assetize output work item.
|
|
2
|
+
|
|
3
|
+
Notes:
|
|
4
|
+
- TODO add example heres
|
|
5
|
+
|
|
6
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
7
|
+
"""
|
|
8
|
+
from logging import getLogger
|
|
9
|
+
from pathlib import PurePath
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Union, Dict
|
|
13
|
+
from idmtools.assets import AssetCollection
|
|
14
|
+
from idmtools.assets.file_list import FileList
|
|
15
|
+
from idmtools.entities.iplatform import IPlatform
|
|
16
|
+
from idmtools.entities.relation_type import RelationType
|
|
17
|
+
from idmtools.core.enums import EntityStatus
|
|
18
|
+
from idmtools_platform_comps.utils.file_filter_workitem import FileFilterWorkItem
|
|
19
|
+
|
|
20
|
+
logger = getLogger(__name__)
|
|
21
|
+
user_logger = getLogger('user')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(repr=False)
|
|
25
|
+
class AssetizeOutput(FileFilterWorkItem):
|
|
26
|
+
"""
|
|
27
|
+
AssetizeOutput allows creating assets from previously ran items in COMPS.
|
|
28
|
+
|
|
29
|
+
Notes:
|
|
30
|
+
- TODO link examples here.
|
|
31
|
+
"""
|
|
32
|
+
# Dictionary of tags to apply to the results asset collection
|
|
33
|
+
asset_tags: Dict[str, str] = field(default_factory=dict)
|
|
34
|
+
#: The asset collection created by Assetize
|
|
35
|
+
asset_collection: AssetCollection = field(default=None)
|
|
36
|
+
|
|
37
|
+
def __post_init__(self, item_name: str, asset_collection_id: UUID, asset_files: FileList, user_files: FileList, command: str):
|
|
38
|
+
"""Constructor AssetizeOutput init."""
|
|
39
|
+
self._ssmt_script = str(PurePath(__file__).parent.joinpath("assetize_ssmt_script.py"))
|
|
40
|
+
super().__post_init__(item_name, asset_collection_id, asset_files, user_files, command)
|
|
41
|
+
|
|
42
|
+
def _extra_command_args(self, command: str):
|
|
43
|
+
"""Add our tags to the command."""
|
|
44
|
+
for name, value in self.asset_tags.items():
|
|
45
|
+
command += f' --asset-tag "{name}={value}"'
|
|
46
|
+
return command
|
|
47
|
+
|
|
48
|
+
def _filter_workitem_pre_creation(self, platform):
|
|
49
|
+
"""
|
|
50
|
+
Callback to allow for pre-creation calls.
|
|
51
|
+
|
|
52
|
+
In our case, we check if tags exist. If no tags exists, we use our defalts ones.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
platform: Platform we are creating on.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
None
|
|
59
|
+
"""
|
|
60
|
+
super(AssetizeOutput, self)._filter_workitem_pre_creation(platform)
|
|
61
|
+
if len(self.asset_tags) == 0:
|
|
62
|
+
self.__generate_tags()
|
|
63
|
+
|
|
64
|
+
def __generate_tags(self):
|
|
65
|
+
"""
|
|
66
|
+
Add the defaults tags to the WorkItem.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
None
|
|
70
|
+
"""
|
|
71
|
+
for experiment in self.related_experiments:
|
|
72
|
+
self.asset_tags['AssetizedOutputfromFromExperiment'] = str(experiment.id)
|
|
73
|
+
for simulation in self.related_simulations:
|
|
74
|
+
self.asset_tags['AssetizedOutputfromFromSimulation'] = str(simulation.id)
|
|
75
|
+
for work_item in self.related_work_items:
|
|
76
|
+
self.asset_tags['AssetizedOutputfromFromWorkItem'] = str(work_item.id)
|
|
77
|
+
for ac in self.related_asset_collections:
|
|
78
|
+
self.asset_tags['AssetizedOutputfromAssetCollection'] = str(ac.id)
|
|
79
|
+
|
|
80
|
+
def run(self, wait_until_done: bool = False, platform: 'IPlatform' = None, wait_on_done_progress: bool = True, **run_opts) -> Union[AssetCollection, None]:
|
|
81
|
+
"""
|
|
82
|
+
Run the AssetizeOutput.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
wait_until_done: Wait until Done will wait for the workitem to complete
|
|
86
|
+
platform: Platform Object
|
|
87
|
+
wait_on_done_progress: When set to true, a progress bar will be shown from the item
|
|
88
|
+
**run_opts: Additional options to pass to Run on platform
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
AssetCollection created if item succeeds
|
|
92
|
+
"""
|
|
93
|
+
p = super()._check_for_platform_from_context(platform)
|
|
94
|
+
if 'wait_on_done' in run_opts:
|
|
95
|
+
raise TypeError("The 'wait_on_done' parameter has been removed in idmtools 1.8.0. Please update your code with 'wait_until_done'.")
|
|
96
|
+
p.run_items(self, wait_on_done_progress=wait_on_done_progress, **run_opts)
|
|
97
|
+
if wait_until_done:
|
|
98
|
+
return self.wait(wait_on_done_progress=wait_on_done_progress, platform=p)
|
|
99
|
+
|
|
100
|
+
def wait(self, wait_on_done_progress: bool = True, timeout: int = None, refresh_interval=None, platform: 'IPlatform' = None) -> Union[AssetCollection, None]:
|
|
101
|
+
"""
|
|
102
|
+
Waits on Assetize Workitem to finish. This first waits on any dependent items to finish(Experiment/Simulation/WorkItems).
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
wait_on_done_progress: When set to true, a progress bar will be shown from the item
|
|
106
|
+
timeout: Timeout for waiting on item. If none, wait will be forever
|
|
107
|
+
refresh_interval: How often to refresh progress
|
|
108
|
+
platform: Platform
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
AssetCollection created if item succeeds
|
|
112
|
+
"""
|
|
113
|
+
# wait on related items before we wait on our item
|
|
114
|
+
p = super()._check_for_platform_from_context(platform)
|
|
115
|
+
opts = dict(wait_on_done_progress=wait_on_done_progress, timeout=timeout, refresh_interval=refresh_interval, platform=p)
|
|
116
|
+
self._wait_on_children(**opts)
|
|
117
|
+
|
|
118
|
+
super().wait(**opts)
|
|
119
|
+
if self.status == EntityStatus.SUCCEEDED and not self.dry_run:
|
|
120
|
+
# If we succeeded, get our AC
|
|
121
|
+
comps_workitem = self.get_platform_object(force=True)
|
|
122
|
+
acs = comps_workitem.get_related_asset_collections(RelationType.Created)
|
|
123
|
+
if acs:
|
|
124
|
+
self.asset_collection = AssetCollection.from_id(acs[0].id, platform=p)
|
|
125
|
+
return self.asset_collection
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""idmtools ssmt script.
|
|
2
|
+
|
|
3
|
+
This script is used on server side only and not meant to be ran on a local machine.
|
|
4
|
+
|
|
5
|
+
Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
|
|
6
|
+
"""
|
|
7
|
+
# flake8: noqa F405 F403
|
|
8
|
+
import sys
|
|
9
|
+
from argparse import Namespace
|
|
10
|
+
from logging import getLogger
|
|
11
|
+
from COMPS.Data.WorkItem import RelationType
|
|
12
|
+
from typing import List, Dict
|
|
13
|
+
import os
|
|
14
|
+
from COMPS.Data import AssetCollectionFile, WorkItem
|
|
15
|
+
|
|
16
|
+
# we have to support two ways to load the utils. The first is load from Assets
|
|
17
|
+
# the fallback is the installed package
|
|
18
|
+
# this allows us to move forward with changes to utils without need for new images
|
|
19
|
+
try:
|
|
20
|
+
from file_filter import *
|
|
21
|
+
from common import *
|
|
22
|
+
except (FileNotFoundError, ImportError):
|
|
23
|
+
from idmtools_platform_comps.utils.ssmt_utils.file_filter import *
|
|
24
|
+
from idmtools_platform_comps.utils.ssmt_utils.common import *
|
|
25
|
+
|
|
26
|
+
logger = getLogger(__name__)
|
|
27
|
+
user_logger = getLogger('user')
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class NoFileFound(Exception):
|
|
31
|
+
doc_link: str = "platforms/comps/errors.html#errors"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def create_asset_collection(file_list: SetOfAssets, ac_files: List[AssetCollectionFile], tags: Dict[str, str]): # pragma: no cover
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
file_list:
|
|
39
|
+
ac_files: AC Files
|
|
40
|
+
tags: Tags to add
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
asset_collection = AssetCollection()
|
|
46
|
+
asset_collection.set_tags(tags)
|
|
47
|
+
# Maps checksum to AssetCollectionFile and the path on disk to file
|
|
48
|
+
asset_collection_map: Dict[uuid.UUID, Tuple[AssetCollectionFile, str, int]] = dict()
|
|
49
|
+
for file in file_list:
|
|
50
|
+
fn = os.path.basename(file[1])
|
|
51
|
+
acf = AssetCollectionFile(file_name=fn, relative_path=file[1].replace(fn, "").strip("/"), md5_checksum=file[2])
|
|
52
|
+
asset_collection_map[file[2]] = (acf, file[0], file[3])
|
|
53
|
+
asset_collection.add_asset(acf)
|
|
54
|
+
|
|
55
|
+
# add files from acs
|
|
56
|
+
for f in ac_files:
|
|
57
|
+
asset_collection.add_asset(f)
|
|
58
|
+
|
|
59
|
+
# do initial save to see what assets are in comps
|
|
60
|
+
missing_files = asset_collection.save(return_missing_files=True)
|
|
61
|
+
if missing_files:
|
|
62
|
+
user_logger.info(f"{len(missing_files)} not currently in COMPS as Assets")
|
|
63
|
+
|
|
64
|
+
ac2 = AssetCollection()
|
|
65
|
+
new_files = 0
|
|
66
|
+
total_to_upload = 0
|
|
67
|
+
for checksum, asset_details in asset_collection_map.items():
|
|
68
|
+
if checksum in missing_files:
|
|
69
|
+
new_files += 1
|
|
70
|
+
total_to_upload += asset_details[2]
|
|
71
|
+
acf = AssetCollectionFile(file_name=asset_details[0].file_name, relative_path=asset_details[0].relative_path)
|
|
72
|
+
ac2.add_asset(acf, asset_details[1])
|
|
73
|
+
else:
|
|
74
|
+
ac2.add_asset(asset_details[0])
|
|
75
|
+
user_logger.info(f"Saving {new_files} totaling {humanfriendly.format_size(total_to_upload)} assets to comps")
|
|
76
|
+
ac2.set_tags(tags)
|
|
77
|
+
ac2.save()
|
|
78
|
+
asset_collection = ac2
|
|
79
|
+
return asset_collection
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def get_argument_parser():
|
|
83
|
+
p = get_common_parser("AssetizeOutputs")
|
|
84
|
+
p.add_argument("--asset-tag", action='append', help="List of tags as value pairs. Eg: ABC=123")
|
|
85
|
+
return p
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def build_asset_tags(parsed_args: Namespace) -> Dict[str, str]:
|
|
89
|
+
"""
|
|
90
|
+
Builds our Asset tag dic from tags
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
parsed_args: Parse Arg
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Dict of tags
|
|
97
|
+
"""
|
|
98
|
+
asset_tags = dict()
|
|
99
|
+
if parsed_args.asset_tag:
|
|
100
|
+
for tag in parsed_args.asset_tag:
|
|
101
|
+
name, value = tag.split("=")
|
|
102
|
+
asset_tags[name] = value
|
|
103
|
+
return asset_tags
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__": # pragma: no cover
|
|
107
|
+
# build our argument parser and then parse the command line
|
|
108
|
+
parser = get_argument_parser()
|
|
109
|
+
args = parser.parse_args()
|
|
110
|
+
|
|
111
|
+
# Set our JOB config global with config provided
|
|
112
|
+
JOB_CONFIG = vars(args)
|
|
113
|
+
# register our error handler
|
|
114
|
+
sys.excepthook = get_error_handler_dump_config_and_error(JOB_CONFIG)
|
|
115
|
+
print(args)
|
|
116
|
+
|
|
117
|
+
# Parse the common arguments common to filter scripts
|
|
118
|
+
entity_filter_func, fn_format_func = parse_filter_args_common(args)
|
|
119
|
+
# Parse our Tags
|
|
120
|
+
asset_tags = build_asset_tags(args)
|
|
121
|
+
|
|
122
|
+
# login
|
|
123
|
+
client = login_to_env()
|
|
124
|
+
|
|
125
|
+
# Load our workitem
|
|
126
|
+
wi = WorkItem.get(os.environ['COMPS_WORKITEM_GUID'])
|
|
127
|
+
|
|
128
|
+
# Gather all our files in Experiments, Simulations, and Asset Collections
|
|
129
|
+
files, files_from_ac = filter_files_and_assets(args, entity_filter_func, wi, fn_format_func)
|
|
130
|
+
if len(files) == 0 and len(files_from_ac) == 0:
|
|
131
|
+
raise NoFileFound("No files found with patterns specified. Please verify your filters.")
|
|
132
|
+
|
|
133
|
+
ensure_no_duplicates(files_from_ac, files)
|
|
134
|
+
|
|
135
|
+
if args.dry_run:
|
|
136
|
+
print_results(files_from_ac, files)
|
|
137
|
+
else:
|
|
138
|
+
ac = create_asset_collection(files, files_from_ac, tags=asset_tags)
|
|
139
|
+
|
|
140
|
+
with open('asset_collection.id', 'w') as o:
|
|
141
|
+
user_logger.info(ac.id)
|
|
142
|
+
o.write(str(ac.id))
|
|
143
|
+
|
|
144
|
+
wi.add_related_asset_collection(ac.id, RelationType.Created)
|