or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdbulk-operations.mdclient-connection.mdcommand-line-interface.mdexceptions.mdindex.mdlow-level-operations.mdutilities.md

bulk-operations.mddocs/

0

# Bulk Operations Service

1

2

High-level service for bulk operations with multi-threading, progress reporting, automatic retries, and comprehensive error handling for upload, download, delete, and copy operations.

3

4

## Capabilities

5

6

### SwiftService Class

7

8

Main service class providing high-level bulk operations with automatic threading, retries, and progress tracking.

9

10

```python { .api }

11

class SwiftService:

12

def __init__(self, options=None):

13

"""

14

Initialize Swift service with configuration options.

15

16

Parameters:

17

- options: dict, service configuration options

18

19

Service options include:

20

- auth_url: str, authentication URL

21

- username: str, username for authentication

22

- password: str, password for authentication

23

- auth_version: str, authentication version

24

- os_*: OpenStack identity options

25

- retries: int, number of operation retries

26

- object_dd_threads: int, object download/delete thread count

27

- object_uu_threads: int, object upload/update thread count

28

- container_threads: int, container operation thread count

29

- segment_threads: int, segment operation thread count

30

"""

31

32

def upload(self, container, objects, options=None):

33

"""

34

Upload objects to Swift.

35

36

Parameters:

37

- container: str, container name to upload to

38

- objects: iterable, SwiftUploadObject instances or file paths

39

- options: dict, upload-specific options

40

41

Yields:

42

dict: upload result for each object

43

44

Upload options include:

45

- leave_segments: bool, don't delete old segments on update

46

- changed: bool, only upload changed files

47

- skip_identical: bool, skip files with matching ETags

48

- fail_fast: bool, stop on first error

49

- dir_marker: bool, create directory marker objects

50

"""

51

52

def download(self, container=None, objects=None, options=None):

53

"""

54

Download objects from Swift.

55

56

Parameters:

57

- container: str, container name to download from (None for all containers)

58

- objects: iterable, object names to download (None for all objects)

59

- options: dict, download-specific options

60

61

Yields:

62

dict: download result for each object

63

64

Download options include:

65

- out_directory: str, local directory to download to

66

- prefix: str, only download objects with this prefix

67

- remove_prefix: bool, remove prefix from local file names

68

- no_download: bool, print download URLs without downloading

69

- skip_identical: bool, skip files with matching local copies

70

"""

71

72

def delete(self, container=None, objects=None, options=None):

73

"""

74

Delete objects and containers from Swift.

75

76

Parameters:

77

- container: str, container name to delete from (None for account)

78

- objects: iterable, object names to delete (None for all objects)

79

- options: dict, delete-specific options

80

81

Yields:

82

dict: delete result for each object/container

83

84

Delete options include:

85

- prefix: str, only delete objects with this prefix

86

- yes_all: bool, delete all containers and objects

87

- leave_segments: bool, don't delete segments of manifest objects

88

"""

89

90

def copy(self, container=None, objects=None, options=None):

91

"""

92

Copy objects in Swift.

93

94

Parameters:

95

- container: str, source container name

96

- objects: iterable, SwiftCopyObject instances

97

- options: dict, copy-specific options

98

99

Yields:

100

dict: copy result for each object

101

102

Copy options include:

103

- destination: str, destination container

104

- fresh_metadata: bool, don't copy existing metadata

105

"""

106

107

def post(self, container=None, objects=None, options=None):

108

"""

109

Update metadata for containers and objects.

110

111

Parameters:

112

- container: str, container name to update (None for account)

113

- objects: iterable, SwiftPostObject instances

114

- options: dict, post-specific options

115

116

Yields:

117

dict: post result for each container/object

118

"""

119

120

def list(self, container=None, options=None):

121

"""

122

List containers and objects.

123

124

Parameters:

125

- container: str, container name to list (None for containers)

126

- options: dict, list-specific options

127

128

Yields:

129

dict: listing result for each container/object

130

131

List options include:

132

- long: bool, include detailed information

133

- prefix: str, only list items with this prefix

134

- delimiter: str, delimiter for hierarchical listings

135

"""

136

137

def stat(self, container=None, objects=None, options=None):

138

"""

139

Display account, container, and object statistics.

140

141

Parameters:

142

- container: str, container name to stat (None for account)

143

- objects: iterable, object names to stat (None for container)

144

- options: dict, stat-specific options

145

146

Yields:

147

dict: stat result for each item

148

"""

149

150

def get_capabilities(self, url=None):

151

"""

152

Retrieve Swift cluster capabilities.

153

154

Parameters:

155

- url: str, Swift cluster URL (uses auth URL if None)

156

157

Returns:

158

dict: cluster capabilities

159

"""

160

```

161

162

### Operation Object Classes

163

164

Configuration objects for specifying bulk operation parameters.

165

166

```python { .api }

167

class SwiftUploadObject:

168

def __init__(

169

self,

170

source,

171

object_name=None,

172

options=None

173

):

174

"""

175

Specify object for upload operation.

176

177

Parameters:

178

- source: str, local file path or file-like object

179

- object_name: str, object name in Swift (derived from source if None)

180

- options: dict, per-object upload options

181

"""

182

183

class SwiftPostObject:

184

def __init__(

185

self,

186

object_name,

187

options=None

188

):

189

"""

190

Specify object for metadata update operation.

191

192

Parameters:

193

- object_name: str, object name to update

194

- options: dict, per-object options including headers

195

"""

196

197

class SwiftDeleteObject:

198

def __init__(

199

self,

200

object_name,

201

options=None

202

):

203

"""

204

Specify object for delete operation.

205

206

Parameters:

207

- object_name: str, object name to delete

208

- options: dict, per-object delete options

209

"""

210

211

class SwiftCopyObject:

212

def __init__(

213

self,

214

object_name,

215

source_container,

216

destination_container,

217

destination_object=None,

218

options=None

219

):

220

"""

221

Specify object for copy operation.

222

223

Parameters:

224

- object_name: str, source object name

225

- source_container: str, source container name

226

- destination_container: str, destination container name

227

- destination_object: str, destination object name (same as source if None)

228

- options: dict, per-object copy options

229

"""

230

```

231

232

### Error Classes

233

234

```python { .api }

235

class SwiftError(Exception):

236

def __init__(

237

self,

238

value,

239

container=None,

240

obj=None,

241

segment=None,

242

exc=None,

243

transaction_id=None

244

):

245

"""

246

Service-level error with operation context.

247

248

Parameters:

249

- value: str, error description

250

- container: str, container name involved in error

251

- obj: str, object name involved in error

252

- segment: str, segment name for large object operations

253

- exc: Exception, underlying exception

254

- transaction_id: str, Swift transaction ID

255

"""

256

```

257

258

### Service Configuration Functions

259

260

```python { .api }

261

def get_conn(options):

262

"""

263

Create Connection object from service options.

264

265

Parameters:

266

- options: dict, connection options

267

268

Returns:

269

Connection: configured connection object

270

"""

271

272

def process_options(options):

273

"""

274

Process and normalize authentication and service options.

275

276

Parameters:

277

- options: dict, raw options dictionary

278

279

Returns:

280

dict: processed options with normalized authentication settings

281

"""

282

```

283

284

## Usage Examples

285

286

### Basic Upload Operations

287

288

```python

289

from swiftclient.service import SwiftService, SwiftUploadObject

290

291

# Configure service

292

options = {

293

'auth_url': 'https://identity.example.com:5000/v3',

294

'username': 'myuser',

295

'password': 'mypassword',

296

'auth_version': '3',

297

'os_project_name': 'myproject',

298

'os_user_domain_name': 'mydomain',

299

'os_project_domain_name': 'mydomain',

300

}

301

302

with SwiftService(options=options) as swift:

303

# Upload individual files

304

upload_objects = [

305

SwiftUploadObject('local/file1.txt'),

306

SwiftUploadObject('local/file2.txt', object_name='remote/file2.txt'),

307

SwiftUploadObject('local/image.jpg', options={'content-type': 'image/jpeg'}),

308

]

309

310

for result in swift.upload('documents', upload_objects):

311

if result['success']:

312

print(f"Uploaded: {result['object']}")

313

else:

314

print(f"Failed to upload {result['object']}: {result['error']}")

315

316

# Upload directory recursively

317

for result in swift.upload('backup', ['./my_directory']):

318

if result['success']:

319

print(f"Uploaded: {result['object']}")

320

```

321

322

### Bulk Download Operations

323

324

```python

325

# Download entire container

326

download_options = {

327

'out_directory': './downloads',

328

'skip_identical': True,

329

}

330

331

with SwiftService(options=options) as swift:

332

for result in swift.download('documents', options=download_options):

333

if result['success']:

334

print(f"Downloaded: {result['object']} -> {result['path']}")

335

else:

336

print(f"Failed to download {result['object']}: {result['error']}")

337

338

# Download specific objects

339

object_names = ['file1.txt', 'images/photo1.jpg', 'data/dataset.csv']

340

for result in swift.download('documents', object_names, options=download_options):

341

if result['success']:

342

print(f"Downloaded: {result['object']}")

343

```

344

345

### Bulk Delete Operations

346

347

```python

348

# Delete specific objects

349

delete_objects = ['old_file1.txt', 'temp/old_file2.txt', 'cache/temp.dat']

350

351

with SwiftService(options=options) as swift:

352

for result in swift.delete('documents', delete_objects):

353

if result['success']:

354

print(f"Deleted: {result['object']}")

355

else:

356

print(f"Failed to delete {result['object']}: {result['error']}")

357

358

# Delete all objects with prefix

359

delete_options = {'prefix': 'temp/'}

360

for result in swift.delete('documents', options=delete_options):

361

if result['success']:

362

print(f"Deleted: {result['object']}")

363

```

364

365

### Copy Operations

366

367

```python

368

from swiftclient.service import SwiftCopyObject

369

370

copy_objects = [

371

SwiftCopyObject('file1.txt', 'documents', 'backup'),

372

SwiftCopyObject('data.csv', 'documents', 'archive', 'data-2024.csv'),

373

]

374

375

with SwiftService(options=options) as swift:

376

for result in swift.copy('documents', copy_objects):

377

if result['success']:

378

print(f"Copied: {result['object']} -> {result['destination']}")

379

else:

380

print(f"Failed to copy {result['object']}: {result['error']}")

381

```

382

383

### Metadata Updates

384

385

```python

386

from swiftclient.service import SwiftPostObject

387

388

# Update object metadata

389

post_objects = [

390

SwiftPostObject('file1.txt', options={

391

'header': ['X-Object-Meta-Author:John Doe', 'X-Object-Meta-Version:2.0']

392

}),

393

SwiftPostObject('file2.txt', options={

394

'header': ['X-Object-Meta-Department:Engineering']

395

}),

396

]

397

398

with SwiftService(options=options) as swift:

399

for result in swift.post('documents', post_objects):

400

if result['success']:

401

print(f"Updated metadata: {result['object']}")

402

else:

403

print(f"Failed to update {result['object']}: {result['error']}")

404

405

# Update container metadata

406

container_options = {

407

'header': ['X-Container-Meta-Owner:TeamA', 'X-Container-Read:.r:*']

408

}

409

for result in swift.post('documents', options=container_options):

410

if result['success']:

411

print(f"Updated container: {result['container']}")

412

```

413

414

### Listing and Statistics

415

416

```python

417

# List containers with details

418

with SwiftService(options=options) as swift:

419

for result in swift.list(options={'long': True}):

420

if result['success']:

421

if 'container' in result:

422

container = result['container']

423

print(f"Container: {container['name']}")

424

print(f" Count: {container['count']}, Bytes: {container['bytes']}")

425

426

# List objects in container

427

for result in swift.list('documents', options={'long': True, 'prefix': 'images/'}):

428

if result['success'] and 'object' in result:

429

obj = result['object']

430

print(f"Object: {obj['name']}, Size: {obj['bytes']}, ETag: {obj['hash']}")

431

432

# Get statistics

433

for result in swift.stat('documents'):

434

if result['success']:

435

stats = result['items']

436

for key, value in stats:

437

print(f"{key}: {value}")

438

```

439

440

### Advanced Upload Configuration

441

442

```python

443

# Upload with advanced options

444

upload_options = {

445

'segment_size': 1048576 * 100, # 100MB segments for large files

446

'use_slo': True, # Use Static Large Objects

447

'segment_container': 'documents_segments',

448

'leave_segments': False, # Clean up old segments

449

'changed': True, # Only upload changed files

450

'skip_identical': True, # Skip identical files

451

'fail_fast': False, # Continue on errors

452

'object_uu_threads': 10, # Upload thread count

453

}

454

455

large_files = [

456

SwiftUploadObject('large_dataset.csv', options={'content-type': 'text/csv'}),

457

SwiftUploadObject('video.mp4', options={'content-type': 'video/mp4'}),

458

]

459

460

with SwiftService(options={**options, **upload_options}) as swift:

461

for result in swift.upload('documents', large_files):

462

if result['success']:

463

print(f"Uploaded: {result['object']} ({result['bytes_uploaded']} bytes)")

464

if 'manifest' in result:

465

print(f" Created manifest with {len(result['manifest'])} segments")

466

else:

467

print(f"Failed: {result['object']} - {result['error']}")

468

```

469

470

### Progress Monitoring

471

472

```python

473

import time

474

475

def monitor_operations(swift_generator, operation_name):

476

"""Monitor and report progress of bulk operations."""

477

start_time = time.time()

478

success_count = 0

479

error_count = 0

480

total_bytes = 0

481

482

for result in swift_generator:

483

if result['success']:

484

success_count += 1

485

total_bytes += result.get('bytes_uploaded', result.get('bytes_downloaded', 0))

486

else:

487

error_count += 1

488

print(f"ERROR: {result.get('object', result.get('container', 'unknown'))}: {result['error']}")

489

490

if (success_count + error_count) % 10 == 0:

491

elapsed = time.time() - start_time

492

print(f"{operation_name}: {success_count} success, {error_count} errors, "

493

f"{total_bytes} bytes in {elapsed:.1f}s")

494

495

total_time = time.time() - start_time

496

print(f"\n{operation_name} Complete:")

497

print(f" Successful: {success_count}")

498

print(f" Failed: {error_count}")

499

print(f" Total bytes: {total_bytes}")

500

print(f" Total time: {total_time:.1f}s")

501

502

# Usage

503

with SwiftService(options=options) as swift:

504

upload_generator = swift.upload('documents', ['./large_directory'])

505

monitor_operations(upload_generator, "Upload")

506

```