You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
4.2 KiB
Python
112 lines
4.2 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
PARTITION_TYPES = ('primary', 'logical', 'extended')
|
|
|
|
|
|
def construct_parted_args(device):
|
|
|
|
parted_args = [
|
|
'-s', device['device'],
|
|
]
|
|
if device['label']:
|
|
parted_args.extend(['mklabel', device['label']])
|
|
|
|
partitions = device['partitions']
|
|
if partitions:
|
|
parted_args.extend(['-a', 'optimal', '--', 'unit', 'MiB'])
|
|
start = 1
|
|
for ind, partition in enumerate(device['partitions']):
|
|
parted_args.extend([
|
|
'mkpart', partition['type']])
|
|
if partition['swap']:
|
|
parted_args.append('linux-swap')
|
|
end = start + partition['size_mib']
|
|
parted_args.extend(["%i" % start, "%i" % end])
|
|
start = end
|
|
if partition['boot']:
|
|
parted_args.extend([
|
|
'set', str(ind + 1), 'boot', 'on'])
|
|
|
|
return parted_args
|
|
|
|
|
|
def validate_partitions(module, partitions):
|
|
for ind, partition in enumerate(partitions):
|
|
# partition name might be an empty string
|
|
partition['name'] = partition.get('name') or str(ind + 1)
|
|
size = partition.get('size_mib', None)
|
|
if not size:
|
|
module.fail_json(msg="Partition size must be provided")
|
|
try:
|
|
partition['size_mib'] = int(size)
|
|
except ValueError:
|
|
module.fail_json(msg="Can not cast partition size to INT.")
|
|
partition.setdefault('type', 'primary')
|
|
if partition['type'] not in PARTITION_TYPES:
|
|
module.fail_json(msg="Partition type must be one of "
|
|
"%s." % PARTITION_TYPES)
|
|
partition['swap'] = module.boolean(partition.get('swap', False))
|
|
partition['boot'] = module.boolean(partition.get('boot', False))
|
|
if partition['boot'] and partition['swap']:
|
|
module.fail_json(msg="Can not set partition to "
|
|
"boot and swap simultaneously.")
|
|
# TODO(pas-ha) add more validation, e.g.
|
|
# - only one boot partition?
|
|
# - no more than 4 primary partitions on msdos table
|
|
# - no more that one extended partition on msdos table
|
|
# - estimate and validate available space
|
|
|
|
|
|
def main():
|
|
module = AnsibleModule(
|
|
argument_spec=dict(
|
|
device=dict(required=True, type='str'),
|
|
dryrun=dict(required=False, default=False, type='bool'),
|
|
new_label=dict(required=False, default=False, type='bool'),
|
|
label=dict(requred=False, default='msdos', choices=[
|
|
"bsd", "dvh", "gpt", "loop", "mac", "msdos", "pc98", "sun"]),
|
|
partitions=dict(
|
|
required=False, type='list')
|
|
),
|
|
supports_check_mode=True)
|
|
|
|
device = module.params['device']
|
|
dryrun = module.params['dryrun']
|
|
new_label = module.params['new_label']
|
|
label = module.params['label']
|
|
if not new_label:
|
|
label = False
|
|
partitions = module.params['partitions'] or []
|
|
try:
|
|
validate_partitions(module, partitions)
|
|
except Exception as e:
|
|
module.fail_json(msg="Malformed partitions arguments: %s" % e)
|
|
parted_args = construct_parted_args(dict(device=device, label=label,
|
|
partitions=partitions))
|
|
command = [module.get_bin_path('parted', required=True)]
|
|
if not (module.check_mode or dryrun):
|
|
command.extend(parted_args)
|
|
module.run_command(command, check_rc=True)
|
|
partitions_created = {p['name']: '%s%i' % (device, i + 1)
|
|
for i, p in enumerate(partitions)}
|
|
module.exit_json(changed=not dryrun, created=partitions_created)
|
|
|
|
|
|
from ansible.module_utils.basic import * # noqa
|
|
if __name__ == '__main__':
|
|
main()
|