File: actions.py

package info (click to toggle)
python-spython 0.3.13-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 736 kB
  • sloc: python: 3,299; sh: 61; makefile: 28
file content (295 lines) | stat: -rw-r--r-- 9,696 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# Copyright (C) 2017-2022 Vanessa Sochat.

# This Source Code Form is subject to the terms of the
# Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed
# with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

import os

from spython.logger import bot
from spython.utils import stream_command


def run(
    self,
    bundle,
    container_id=None,
    log_path=None,
    pid_file=None,
    singularity_options=None,
    log_format="kubernetes",
):
    """run is a wrapper to create, start, attach, and delete a container.

    Equivalent command line example:
      singularity oci run -b ~/bundle mycontainer

    Parameters
    ==========
    bundle: the full path to the bundle folder
    container_id: an optional container_id. If not provided, use same
                  container_id used to generate OciImage instance
    log_path: the path to store the log.
    pid_file: specify the pid file path to use
    log_format: defaults to kubernetes. Can also be "basic" or "json"
    singularity_options: a list of options to provide to the singularity client
    """
    return self._run(
        bundle,
        container_id=container_id,
        log_path=log_path,
        pid_file=pid_file,
        command="run",
        log_format=log_format,
        singularity_options=singularity_options,
    )


def create(
    self,
    bundle,
    container_id=None,
    empty_process=False,
    log_path=None,
    pid_file=None,
    sync_socket=None,
    log_format="kubernetes",
    singularity_options=None,
):
    """use the client to create a container from a bundle directory. The bundle
    directory should have a config.json. You must be the root user to
    create a runtime.

    Equivalent command line example:
       singularity oci create [create options...] <container_ID>

    Parameters
    ==========
    bundle: the full path to the bundle folder
    container_id: an optional container_id. If not provided, use same
                  container_id used to generate OciImage instance
    empty_process: run container without executing container process (for
                   example, for a pod container waiting for signals). This
                   is a specific use case for tools like Kubernetes
    log_path: the path to store the log.
    pid_file: specify the pid file path to use
    sync_socket: the path to the unix socket for state synchronization.
    log_format: defaults to kubernetes. Can also be "basic" or "json"
    singularity_options: a list of options to provide to the singularity client
    """
    return self._run(
        bundle,
        container_id=container_id,
        empty_process=empty_process,
        log_path=log_path,
        pid_file=pid_file,
        sync_socket=sync_socket,
        command="create",
        log_format=log_format,
        singularity_options=singularity_options,
    )


def _run(
    self,
    bundle,
    container_id=None,
    empty_process=False,
    log_path=None,
    pid_file=None,
    sync_socket=None,
    command="run",
    log_format="kubernetes",
    singularity_options=None,
):
    """_run is the base function for run and create, the only difference
    between the two being that run does not have an option for sync_socket.

    Equivalent command line example:
       singularity oci create [create options...] <container_ID>

    Parameters
    ==========
    bundle: the full path to the bundle folder
    container_id: an optional container_id. If not provided, use same
                  container_id used to generate OciImage instance
    empty_process: run container without executing container process (for
                   example, for a pod container waiting for signals). This
                   is a specific use case for tools like Kubernetes
    log_path: the path to store the log.
    pid_file: specify the pid file path to use
    sync_socket: the path to the unix socket for state synchronization.
    command: the command (run or create) to use (default is run)
    log_format: defaults to kubernetes. Can also be "basic" or "json"
    singularity_options: a list of options to provide to the singularity client

    """
    container_id = self.get_container_id(container_id)

    # singularity oci create
    cmd = self._init_command(command, singularity_options)

    # Check that the bundle exists
    if not os.path.exists(bundle):
        bot.exit("Bundle not found at %s" % bundle)

    # Add the bundle
    cmd = cmd + ["--bundle", bundle]

    # Additional Logging Files
    cmd = cmd + ["--log-format", log_format]

    if log_path is not None:
        cmd = cmd + ["--log-path", log_path]
    if pid_file is not None:
        cmd = cmd + ["--pid-file", pid_file]
    if sync_socket is not None:
        cmd = cmd + ["--sync-socket", sync_socket]
    if empty_process:
        cmd.append("--empty-process")

    # Finally, add the container_id
    cmd.append(container_id)

    # Generate the instance
    self._send_command(cmd, sudo=True)

    # Get the status to report to the user!
    return self.state(container_id, sudo=True, sync_socket=sync_socket)


def delete(self, container_id=None, sudo=None, singularity_options=None):
    """delete an instance based on container_id.

    Parameters
    ==========
    container_id: the container_id to delete
    singularity_options: a list of options to provide to the singularity client
    sudo: whether to issue the command with sudo (or not)
          a container started with sudo will belong to the root user
          If started by a user, the user needs to control deleting it
          if the user doesn't set to True/False, we use client self.sudo

    Returns
    =======
    return_code: the return code from the delete command. 0 indicates a
                 successful delete, 255 indicates not.
    """
    sudo = self._get_sudo(sudo)
    container_id = self.get_container_id(container_id)

    # singularity oci delete
    cmd = self._init_command("delete", singularity_options)

    # Add the container_id
    cmd.append(container_id)

    # Delete the container, return code goes to user (message to screen)
    return self._run_and_return(cmd, sudo=sudo)


def attach(self, container_id=None, sudo=False, singularity_options=None):
    """attach to a container instance based on container_id

    Parameters
    ==========
    container_id: the container_id to delete
    singularity_options: a list of options to provide to the singularity client
    sudo: whether to issue the command with sudo (or not)
          a container started with sudo will belong to the root user
          If started by a user, the user needs to control deleting it

    Returns
    =======
    return_code: the return code from the delete command. 0 indicates a
                 successful delete, 255 indicates not.
    """
    sudo = self._get_sudo(sudo)
    container_id = self.get_container_id(container_id)

    # singularity oci attach
    cmd = self._init_command("attach", singularity_options)

    # Add the container_id
    cmd.append(container_id)

    # Delete the container, return code goes to user (message to screen)
    return self._run_and_return(cmd, sudo)


def execute(
    self,
    command=None,
    container_id=None,
    sudo=False,
    stream=False,
    singularity_options=None,
):
    """execute a command to a container instance based on container_id

    Parameters
    ==========
    container_id: the container_id to delete
    command: the command to execute to the container
    singularity_options: a list of options to provide to the singularity client
    sudo: whether to issue the command with sudo (or not)
          a container started with sudo will belong to the root user
          If started by a user, the user needs to control deleting it
    stream: if True, return an iterate to iterate over results of exec.
            default is False, will return full output as string.

    Returns
    =======
    return_code: the return code from the delete command. 0 indicates a
                 successful delete, 255 indicates not.
    """
    sudo = self._get_sudo(sudo)
    container_id = self.get_container_id(container_id)

    # singularity oci delete
    cmd = self._init_command("exec", singularity_options)

    # Add the container_id
    cmd.append(container_id)

    if command is not None:
        if not isinstance(command, list):
            command = [command]

        cmd = cmd + command

        # Execute the command, return response to user
        if stream:
            return stream_command(cmd, sudo=sudo)
        return self._run_command(cmd, sudo=sudo, quiet=True)


def update(self, container_id, from_file=None, sudo=False, singularity_options=None):
    """update container cgroup resources for a specific container_id,
    The container must have state "running" or "created."

    Singularity Example:
        singularity oci update [update options...] <container_ID>
        singularity oci update --from-file cgroups-update.json mycontainer

    Parameters
    ==========
    container_id: the container_id to update cgroups for
    from_file: a path to an OCI JSON resource file to update from.
    singularity_options: a list of options to provide to the singularity client

    """
    sudo = self._get_sudo(sudo)
    container_id = self.get_container_id(container_id)

    # singularity oci delete
    cmd = self._init_command("update", singularity_options)

    if from_file is not None:
        cmd = cmd + ["--from-file", from_file]

    # Add the container_id
    cmd.append(container_id)

    # Delete the container, return code goes to user (message to screen)
    return self._run_and_return(cmd, sudo)