7
7
import { inject , injectable } from "inversify" ;
8
8
import { v4 as uuidv4 } from "uuid" ;
9
9
import { WorkspaceDB } from "@gitpod/gitpod-db/lib" ;
10
- import { Disposable , GitpodServer , Snapshot } from "@gitpod/gitpod-protocol" ;
10
+ import { Disposable , Snapshot , WorkspaceInstance } from "@gitpod/gitpod-protocol" ;
11
11
import { StorageClient } from "../../../src/storage/storage-client" ;
12
12
import { ConsensusLeaderQorum } from "../../../src/consensus/consensus-leader-quorum" ;
13
13
import { log } from "@gitpod/gitpod-protocol/lib/util/logging" ;
14
14
import { repeat } from "@gitpod/gitpod-protocol/lib/util/repeat" ;
15
+ import { WorkspaceManagerClientProvider } from "@gitpod/ws-manager/lib/client-provider" ;
16
+ import { GetVolumeSnapshotRequest , TakeSnapshotRequest } from "@gitpod/ws-manager/lib" ;
17
+ import { Config } from "../../../src/config" ;
18
+ import { TraceContext } from "@gitpod/gitpod-protocol/lib/util/tracing" ;
15
19
16
20
const SNAPSHOT_TIMEOUT_SECONDS = 60 * 30 ;
17
21
const SNAPSHOT_POLL_INTERVAL_SECONDS = 5 ;
@@ -31,6 +35,9 @@ export class SnapshotService {
31
35
@inject ( WorkspaceDB ) protected readonly workspaceDb : WorkspaceDB ;
32
36
@inject ( StorageClient ) protected readonly storageClient : StorageClient ;
33
37
@inject ( ConsensusLeaderQorum ) protected readonly leaderQuorum : ConsensusLeaderQorum ;
38
+ @inject ( WorkspaceManagerClientProvider )
39
+ protected readonly workspaceManagerClientProvider : WorkspaceManagerClientProvider ;
40
+ @inject ( Config ) protected readonly config : Config ;
34
41
35
42
protected readonly runningSnapshots : Map < string , Promise < void > > = new Map ( ) ;
36
43
@@ -74,14 +81,24 @@ export class SnapshotService {
74
81
}
75
82
}
76
83
77
- public async createSnapshot ( options : GitpodServer . TakeSnapshotOptions , snapshotUrl : string ) : Promise < Snapshot > {
84
+ public async createSnapshot ( ctx : TraceContext , instance : WorkspaceInstance ) : Promise < Snapshot > {
85
+ const client = await this . workspaceManagerClientProvider . get (
86
+ instance . region ,
87
+ this . config . installationShortname ,
88
+ ) ;
89
+ const request = new TakeSnapshotRequest ( ) ;
90
+ request . setId ( instance . id ) ;
91
+ request . setReturnImmediately ( true ) ;
92
+
93
+ // this triggers the snapshots, but returns early! cmp. waitForSnapshot to wait for it's completion
94
+ const resp = await client . takeSnapshot ( ctx , request ) ;
78
95
const id = uuidv4 ( ) ;
79
96
return await this . workspaceDb . storeSnapshot ( {
80
97
id,
81
98
creationTime : new Date ( ) . toISOString ( ) ,
82
99
state : "pending" ,
83
- bucketId : snapshotUrl ,
84
- originalWorkspaceId : options . workspaceId ,
100
+ bucketId : resp . getUrl ( ) ,
101
+ originalWorkspaceId : instance . workspaceId ,
85
102
} ) ;
86
103
}
87
104
@@ -112,6 +129,24 @@ export class SnapshotService {
112
129
113
130
const { id : snapshotId , bucketId, originalWorkspaceId, creationTime } = opts . snapshot ;
114
131
const start = new Date ( creationTime ) . getTime ( ) ;
132
+ const workspace = await this . workspaceDb . findWorkspaceAndInstance ( originalWorkspaceId ) ;
133
+ if ( ! workspace ) {
134
+ const message = `Couldn't find original workspace for snapshot.` ;
135
+ await this . workspaceDb . updateSnapshot ( {
136
+ id : snapshotId ,
137
+ state : "error" ,
138
+ message,
139
+ } ) ;
140
+ throw new Error ( message ) ;
141
+ }
142
+ const client = await this . workspaceManagerClientProvider . get (
143
+ workspace . region ,
144
+ this . config . installationShortname ,
145
+ ) ;
146
+ const req = new GetVolumeSnapshotRequest ( ) ;
147
+ req . setId ( workspace . instanceId ) ;
148
+
149
+ const isPVC = workspace ?. config . _featureFlags ?. some ( ( f ) => f === "persistent_volume_claim" ) ;
115
150
while ( start + SNAPSHOT_TIMEOUT_SECONDS * 1000 > Date . now ( ) ) {
116
151
await new Promise ( ( resolve ) => setTimeout ( resolve , SNAPSHOT_POLL_INTERVAL_SECONDS * 1000 ) ) ;
117
152
@@ -126,13 +161,19 @@ export class SnapshotService {
126
161
if ( snapshot . state === "error" ) {
127
162
throw new Error ( `snapshot error: ${ snapshot . message } ` ) ;
128
163
}
164
+ let exists = false ;
165
+ if ( isPVC ) {
166
+ const response = await client . getVolumeSnapshot ( { } , req ) ;
167
+ exists = response . getReady ( ) ;
168
+ } else {
169
+ // pending: check if the snapshot is there
170
+ exists = await this . storageClient . workspaceSnapshotExists (
171
+ opts . workspaceOwner ,
172
+ originalWorkspaceId ,
173
+ bucketId ,
174
+ ) ;
175
+ }
129
176
130
- // pending: check if the snapshot is there
131
- const exists = await this . storageClient . workspaceSnapshotExists (
132
- opts . workspaceOwner ,
133
- originalWorkspaceId ,
134
- bucketId ,
135
- ) ;
136
177
if ( exists ) {
137
178
await this . workspaceDb . updateSnapshot ( {
138
179
id : snapshotId ,
0 commit comments