Skip to content

Commit 35bcd8b

Browse files
authored
Merge pull request #169 from lae/feature/pbs-storage
Add Proxmox Backup Server storage type
2 parents 85abc3d + bdadfdb commit 35bcd8b

File tree

3 files changed

+84
-11
lines changed

3 files changed

+84
-11
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,8 @@ Refer to `library/proxmox_role.py` [link][user-module] and
545545

546546
You can use this role to manage storage within Proxmox VE (both in
547547
single server deployments and cluster deployments). For now, the only supported
548-
types are `dir`, `rbd`, `nfs`, `cephfs`, `lvm`,`lvmthin`, `zfspool` and `btrfs`.
549-
Here are some examples.
548+
types are `dir`, `rbd`, `nfs`, `cephfs`, `lvm`,`lvmthin`, `zfspool`, `btrfs`,
549+
and `pbs`. Here are some examples.
550550

551551
```
552552
pve_storages:
@@ -589,6 +589,13 @@ pve_storages:
589589
- 10.0.0.1
590590
- 10.0.0.2
591591
- 10.0.0.3
592+
- name: pbs1
593+
type: pbs
594+
content: [ "backup" ]
595+
server: 192.168.122.2
596+
username: user@pbs
597+
password: PBSPassword1
598+
datastore: main
592599
- name: zfs1
593600
type: zfspool
594601
content: [ "images", "rootdir" ]

library/proxmox_storage.py

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,17 @@
159159
- 10.0.0.1
160160
- 10.0.0.2
161161
- 10.0.0.3
162+
- name: Create a Proxmox Backup Server storage type
163+
proxmox_storage:
164+
name: pbs1
165+
type: pbs
166+
content: [ "backup" ]
167+
server: 192.168.122.2
168+
username: user@pbs
169+
password: PBSPassword1
170+
datastore: main
171+
fingerprint: f2:fb:85:76:d2:2a:c4:96:5c:6e:d8:71:37:36:06:17:09:55:f7:04:e3:74:bb:aa:9e:26:85:92:63:c8:b9:23
172+
encryption_key: autogen
162173
- name: Create a ZFS storage type
163174
proxmox_storage:
164175
name: zfs1
@@ -175,16 +186,26 @@
175186
from ansible.module_utils._text import to_text
176187
from ansible.module_utils.pvesh import ProxmoxShellError
177188
import ansible.module_utils.pvesh as pvesh
189+
import re
190+
import json
191+
from json import JSONDecodeError, loads as parse_json
192+
178193

179194
class ProxmoxStorage(object):
180195
def __init__(self, module):
181196
self.module = module
182197
self.name = module.params['name']
183198
self.state = module.params['state']
184-
self.type = module.params['type']
199+
# Globally applicable PVE API arguments
185200
self.disable = module.params['disable']
186201
self.content = module.params['content']
187202
self.nodes = module.params['nodes']
203+
self.type = module.params['type']
204+
# Remaining PVE API arguments (depending on type) past this point
205+
self.datastore = module.params['datastore']
206+
self.encryption_key = module.params['encryption_key']
207+
self.fingerprint = module.params['fingerprint']
208+
self.password = module.params['password']
188209
self.path = module.params['path']
189210
self.pool = module.params['pool']
190211
self.monhost = module.params['monhost']
@@ -199,6 +220,24 @@ def __init__(self, module):
199220
self.sparse = module.params['sparse']
200221
self.is_mountpoint = module.params['is_mountpoint']
201222

223+
# Validate the parameters given to us
224+
fingerprint_re = re.compile('^([A-Fa-f0-9]{2}:){31}[A-Fa-f0-9]{2}$')
225+
if self.fingerprint is not None and not fingerprint_re.match(self.fingerprint):
226+
self.module.fail_json(msg=(f"fingerprint must be of the format, "
227+
f"{fingerprint_re.pattern}."))
228+
229+
if self.type == 'pbs':
230+
if self.content != ['backup']:
231+
self.module.fail_json(msg="PBS storage type only supports the "
232+
"'backup' content type.")
233+
try:
234+
if self.encryption_key not in ["autogen", None]:
235+
parse_json(self.encryption_key)
236+
except JSONDecodeError:
237+
self.module.fail_json(msg=("encryption_key needs to be valid "
238+
"JSON or set to 'autogen'."))
239+
240+
# Attempt to retrieve current/live storage definitions
202241
try:
203242
self.existing_storages = pvesh.get("storage")
204243
except ProxmoxShellError as e:
@@ -233,6 +272,16 @@ def prepare_storage_args(self):
233272
args['nodes'] = ','.join(self.nodes)
234273
if self.disable is not None:
235274
args['disable'] = 1 if self.disable else 0
275+
if self.datastore is not None:
276+
args['datastore'] = self.datastore
277+
if self.encryption_key is not None:
278+
args['encryption-key'] = self.encryption_key
279+
if self.fingerprint is not None:
280+
args['fingerprint'] = self.fingerprint
281+
if self.master_pubkey is not None:
282+
args['master-pubkey'] = self.master_pubkey
283+
if self.password is not None:
284+
args['password'] = self.password
236285
if self.path is not None:
237286
args['path'] = self.path
238287
if self.pool is not None:
@@ -329,13 +378,20 @@ def main():
329378
# Refer to https://pve.proxmox.com/pve-docs/api-viewer/index.html
330379
module_args = dict(
331380
name=dict(type='str', required=True, aliases=['storage', 'storageid']),
381+
state=dict(default='present', choices=['present', 'absent'], type='str'),
382+
# Globally applicable PVE API arguments
332383
content=dict(type='list', required=True, aliases=['storagetype']),
384+
disable=dict(required=False, type='bool', default=False),
333385
nodes=dict(type='list', required=False, default=None),
334386
type=dict(default=None, type='str', required=True,
335387
choices=["dir", "nfs", "rbd", "lvm", "lvmthin", "cephfs",
336-
"zfspool", "btrfs"]),
337-
disable=dict(required=False, type='bool', default=False),
338-
state=dict(default='present', choices=['present', 'absent'], type='str'),
388+
"zfspool", "btrfs", "pbs"]),
389+
# Remaining PVE API arguments (depending on type) past this point
390+
datastore=dict(default=None, type='str', required=False),
391+
encryption_key=dict(default=None, type='str', required=False),
392+
fingerprint=dict(default=None, type='str', required=False),
393+
master_pubkey=dict(default=None, type='str', required=False),
394+
password=dict(default=None, type='str', required=False),
339395
path=dict(default=None, required=False, type='str'),
340396
pool=dict(default=None, type='str', required=False),
341397
monhost=dict(default=None, type='list', required=False),
@@ -363,7 +419,11 @@ def main():
363419
["type", "lvmthin", ["vgname", "thinpool", "content"]],
364420
["type", "zfspool", ["pool", "content"]],
365421
["type", "btrfs", ["path", "content"]],
366-
]
422+
["type", "pbs", ["server", "username", "password", "datastore"]]
423+
],
424+
required_by={
425+
"master_pubkey": "encryption_key"
426+
}
367427
)
368428
storage = ProxmoxStorage(module)
369429

tasks/main.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,17 +269,23 @@
269269
- name: Configure Proxmox Storage
270270
proxmox_storage:
271271
name: "{{ item.name }}"
272-
type: "{{ item.type }}"
273-
disable: "{{ item.disable | default(False) }}"
274-
path: "{{ item.path | default(omit) }}"
272+
state: "{{ item.state | default('present') }}"
273+
# Globally applicable PVE API arguments
275274
content: "{{ item.content | default([]) }}"
275+
disable: "{{ item.disable | default(False) }}"
276276
nodes: "{{ item.nodes | default(omit) }}"
277+
type: "{{ item.type }}"
278+
# Remaining PVE API arguments (depending on type) past this point
279+
datastore: "{{ item.datastore | default(omit) }}"
280+
encryption_key: "{{ item.encryption_key | default(omit) }}"
281+
fingerprint: "{{ item.fingerprint | default(omit) }}"
282+
password: "{{ item.password | default(omit) }}"
283+
path: "{{ item.path | default(omit) }}"
277284
username: "{{ item.username | default(omit) }}"
278285
pool: "{{ item.pool | default(omit) }}"
279286
monhost: "{{ item.monhost | default(omit) }}"
280287
maxfiles: "{{ item.maxfiles | default(omit) }}"
281288
krbd: "{{ item.krbd | default(omit) }}"
282-
state: "{{ item.state | default('present') }}"
283289
server: "{{ item.server | default(omit) }}"
284290
export: "{{ item.export | default(omit) }}"
285291
options: "{{ item.options | default(omit) }}"

0 commit comments

Comments
 (0)