Skip to content

Commit 3bdfd38

Browse files
Merge pull request #328 from PierreBeucher/infra-fixes
Various infra fixes and small improvements
2 parents fccfce2 + c2b0f7f commit 3bdfd38

15 files changed

Lines changed: 258 additions & 108 deletions

File tree

ansible/roles/nvidia-driver/tasks/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
apt:
88
name: "linux-modules-extra-{{ ansible_kernel }}"
99
state: present
10+
update_cache: true
1011

1112
- name: unload nouveau
1213
modprobe:

ansible/roles/wolf/defaults/main.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,8 @@ wolf_project_dir: "{{ ansible_user_dir }}/wolf"
1717
# Where Wolf container data are stored
1818
wolf_data_dir: "/var/lib/cloudypad/wolf"
1919

20-
wolf_legacy_data_dir: "/etc/wolf"
20+
wolf_legacy_data_dir: "/etc/wolf"
21+
22+
# Whether to pull app images in parallel for faster subsequent startup when using Wolf
23+
# Disabled by default to avoid pulling images when not needed
24+
wolf_app_preheat_images_pull: false

ansible/roles/wolf/tasks/main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
apt:
88
name: "linux-modules-extra-{{ ansible_kernel }}"
99
state: present
10+
update_cache: true
1011

1112
- name: Ensure uinput module enabled
1213
community.general.modprobe:
@@ -138,11 +139,13 @@
138139
files: docker-compose.nvidia.yml
139140

140141
- name: Copy Docker Compose preheat pull file
142+
when: wolf_app_preheat_images_pull
141143
ansible.builtin.template:
142144
src: docker-compose.app-preheat.yml
143145
dest: "{{ wolf_project_dir }}/docker-compose.app-preheat.yml"
144146

145147
- name: Pull images using preheat Compose file
148+
when: wolf_app_preheat_images_pull
146149
community.docker.docker_compose_v2_pull:
147150
project_src: /tmp
148151
files: "{{ wolf_project_dir }}/docker-compose.app-preheat.yml"

containers/sunshine/overlay/cloudy/bin/setup-nvidia-driver.sh

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
set -e
1515

16-
NVIDIA_DATA_DIR=$CLOUDYPAD_DATA_DIR/nvidia/
16+
NVIDIA_DATA_DIR="$CLOUDYPAD_DATA_DIR/nvidia"
1717
mkdir -p $NVIDIA_DATA_DIR
1818

1919
if [ -z "${NVIDIA_DRIVER_VERSION}" ]; then
@@ -31,13 +31,20 @@ NVIDIA_INSTALLER="$NVIDIA_DATA_DIR/nvidia-${NVIDIA_DRIVER_TYPE}-${NVIDIA_DRIVER_
3131
# Create a marker file in XDG_RUNTIME_DIR to indicate that the driver is installed
3232
# This is used to avoid reinstalling the driver on container restart
3333
# But driver should be installed in freshly created container
34+
# As runtime dir is emptied when container is recreated
3435
NVIDIA_INSTALL_MARKER="$XDG_RUNTIME_DIR/nvidia-driver-${NVIDIA_DRIVER_TYPE}-${NVIDIA_DRIVER_VERSION}.installed"
3536

37+
3638
echo "Checking Nvidia driver ${NVIDIA_DRIVER_VERSION} (${NVIDIA_DRIVER_TYPE}) component installation..."
3739

38-
# Check if the file already exists
39-
if [ ! -f "$NVIDIA_INSTALLER" ]; then
40-
echo "NVIDIA driver version ${NVIDIA_DRIVER_VERSION} (type: '${NVIDIA_DRIVER_TYPE}') not found. Downloading..."
40+
# Check if installer file is not downloaded yet
41+
# Create a marker file in NVIDIA_DATA_DIR to indicate that the driver has been downloaded successfully
42+
# Use marker file to avoid checking if plain .run file exists as sometime file may be partially downloaded
43+
# but failed in the middle, causing a corrupted file and/or a file with incorrect permissions
44+
NVIDIA_DOWNLOAD_MARKER="$NVIDIA_DATA_DIR/nvidia-driver-${NVIDIA_DRIVER_TYPE}-${NVIDIA_DRIVER_VERSION}.downloaded"
45+
46+
if [ ! -f "$NVIDIA_DOWNLOAD_MARKER" ]; then
47+
echo "NVIDIA driver version ${NVIDIA_DRIVER_VERSION} (type: '${NVIDIA_DRIVER_TYPE}') not downloaded yet. Downloading..."
4148

4249
echo "Removing old NVIDIA driver installers..."
4350
find "$NVIDIA_DATA_DIR" -type f -name "nvidia-*.run" -exec rm -f {} +
@@ -54,8 +61,11 @@ if [ ! -f "$NVIDIA_INSTALLER" ]; then
5461
chmod +x "$NVIDIA_INSTALLER"
5562

5663
echo "Downloaded $NVIDIA_INSTALLER"
64+
65+
# Create a marker file to indicate that the driver has been downloaded successfully
66+
touch "$NVIDIA_DOWNLOAD_MARKER"
5767
else
58-
echo "NVIDIA driver installer file already exists: $NVIDIA_INSTALLER"
68+
echo "NVIDIA driver installer file already downloaded: $NVIDIA_INSTALLER ($NVIDIA_DOWNLOAD_MARKER file exists)"
5969
fi
6070

6171
# Check if the installation marker file exists
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/usr/bin/env bash
22

33
# Can be used by user to stop session
4-
gnome-terminal -- bash -c "stop-container-exit-prompt.sh"
4+
xterm stop-container-exit-prompt.sh

containers/sunshine/overlay/cloudy/conf/xfce4-default/panel/launcher-5/exit.desktop

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Version=1.0
33
Type=Application
44
Name=Exit to host
5-
Comment=comment
5+
Comment=Exit to host
66
Exec=/cloudy/bin/stop-container-user.sh
77
Icon=system-shutdown
88
Path=

docs/src/contributing/contribution-guide.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,10 @@ Instance is reachable via `192.168.56.43`.
442442
To pair, connect to the Sunshine web UI and use Moonlight manually:
443443

444444
```sh
445+
# A TLS certificate warning is shown as certificate is self-signed
446+
# login: sunshine
447+
# password: @!/:,?!*#'€`_\µ$="foo
448+
# or 'sunshine'
445449
https://192.168.56.43:47990/
446450
```
447451

src/cli/updater.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ export class InteractiveInstanceUpdater<ST extends InstanceStateV1, A extends Up
5353

5454
const manager = await this.providerClient.getInstanceManager(instanceName)
5555

56-
// ensure instance is started for deployment
57-
// as deployment will not necessarily start instance if it's stopped
58-
await manager.start()
59-
6056
await manager.deploy()
6157
}
6258

src/core/manager.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,14 @@ const ALWAYS_ANSIBLE_ADDITIONAL_ARGS = ['-e', '\'ansible_ssh_common_args="-o Str
259259
*
260260
* The concrete instance type is not known by this class: a per-provider factory is used
261261
* to build each sub-managers.
262+
*
263+
* Each action function (stop, start, configure, provision, etc.) is a wrapper with retry around
264+
* low-level action functions (doStart, doStop, doConfigure, doProvision, etc.).
265+
* - a top-level action like deploy() may rely on other top-level actions like configure()
266+
* or call underlying low-level actions like doConfigure wrapped in a retry().
267+
* They may also container logic like retry pattern, starting instance before configuring, etc.
268+
* - a low-level action like doConfigure() must NOT call another low-level NOR top-level action.
269+
* These functions should only strictly do the required action without any mre logic.
262270
*/
263271
export class GenericInstanceManager<ST extends InstanceStateV1> implements InstanceManager {
264272

@@ -295,9 +303,23 @@ export class GenericInstanceManager<ST extends InstanceStateV1> implements Insta
295303
[currentState.configuration.input.ansible.additionalArgs] : undefined
296304

297305
await this.addEvent(InstanceEventEnum.ConfigurationBegin)
306+
307+
// before configuring, check instance is running as it's possible user would call configure() directly without starting the instance first
308+
// start it if needed
309+
const currentStatus = await this.getInstanceStatus()
310+
if(currentStatus.serverStatus !== ServerRunningStatus.Running){
311+
312+
this.logger.debug(`About to run configuration for instance ${this.name()} but it's not running, starting it first...`)
313+
314+
await this.doWithRetry(async () => {
315+
await this.doStart({ wait: true })
316+
}, 'Pre-configure start', opts)
317+
}
318+
298319
await this.doWithRetry(async () => {
299320
await this.doConfigure(configurationAnsibleAdditionalArgs)
300321
}, 'Configuration', opts)
322+
301323
await this.addEvent(InstanceEventEnum.ConfigurationEnd)
302324
}
303325

@@ -331,6 +353,15 @@ export class GenericInstanceManager<ST extends InstanceStateV1> implements Insta
331353

332354
this.logger.debug(`Starting instance ${this.name()}`)
333355

356+
// if deleteInstanceServerOnStop is enabled, instance server may have been deleted on last instance stop
357+
// so we need to re-provision and re-configure instance using specific Ansible args
358+
await this.doWithRetry(async () => {
359+
if(this.args.options?.deleteInstanceServerOnStop?.enabled){
360+
await this.doProvision(opts)
361+
await this.doConfigure(this.args.options.deleteInstanceServerOnStop.postStartReconfigurationAnsibleAdditionalArgs)
362+
}
363+
}, 'Pre-start reconfiguration', opts)
364+
334365
await this.addEvent(InstanceEventEnum.StartBegin)
335366
await this.doWithRetry(async () => {
336367
await this.doStart(opts)
@@ -401,6 +432,7 @@ export class GenericInstanceManager<ST extends InstanceStateV1> implements Insta
401432
const configurator = await this.buildConfigurator({
402433
additionalAnsibleArgs: ALWAYS_ANSIBLE_ADDITIONAL_ARGS.concat(additionalAnsibleArgs ?? [])
403434
})
435+
404436
const output = await configurator.configure()
405437

406438
this.logger.debug(`Configuration output for instance ${this.name()}: ${JSON.stringify(output)}`)
@@ -431,13 +463,6 @@ export class GenericInstanceManager<ST extends InstanceStateV1> implements Insta
431463
*/
432464
async doStart(opts?: StartOptions): Promise<void> {
433465

434-
// if deleteInstanceServerOnStop is enabled, instance server may have been deleted on last instance stop
435-
// so we need to re-provision and re-configure instance using specific Ansible args
436-
if(this.args.options?.deleteInstanceServerOnStop?.enabled){
437-
await this.doProvision(opts)
438-
await this.doConfigure(this.args.options.deleteInstanceServerOnStop.postStartReconfigurationAnsibleAdditionalArgs)
439-
}
440-
441466
// always start instance as provisioning and configuring may not start the server for all providers
442467
// and startOptions logic is ported by runner
443468
const runner = await this.buildRunner()

src/core/moonlight/pairer/sunshine.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,11 @@ export class SunshineMoonlightPairer extends AbstractMoonlightPairer implements
2828
}
2929

3030
private buildSshClient(): SSHClient {
31+
this.logger.debug(`Building SSH client with args: ${JSON.stringify(this.args.ssh)}`)
3132
return new SSHClient(this.args.ssh);
3233
}
3334

34-
protected async doPair(pin: string) {
35-
36-
const ssh = this.buildSshClient()
37-
35+
protected async doPair(pin: string) {
3836
// try to pair for 2 min by punshing through Sunshine API with our pin
3937
// Using plain curl + SSH command as Sunshine Web UI is not reachable directly
4038
// A simple but effective enough method

0 commit comments

Comments
 (0)