225 lines
7.0 KiB
Python
225 lines
7.0 KiB
Python
|
#!/usr/bin/python3
|
||
|
|
||
|
from __future__ import (absolute_import, division, print_function)
|
||
|
__metaclass__ = type
|
||
|
|
||
|
import os
|
||
|
import sys
|
||
|
import logging
|
||
|
from argparse import Namespace
|
||
|
import pathlib
|
||
|
import traceback
|
||
|
|
||
|
sys.path.append('/mnt/o/var/local/src/play_tox/src/ansible_gentooimgr')
|
||
|
# in the library
|
||
|
mod_path = os.path.dirname(os.path.realpath('__file__'))
|
||
|
mod_path = os.path.join(mod_path, 'src', 'ansible_gentooimgr')
|
||
|
assert os.path.isdir(mod_path), f"parent {mod_path}"
|
||
|
assert os.path.isfile(os.path.join(mod_path, '__init__.py')),f"index {mod_path}"
|
||
|
assert os.path.isdir(os.path.join(mod_path, 'gentooimgr')), f"sub {mod_path}"
|
||
|
sys.path.append(mod_path)
|
||
|
try:
|
||
|
import gentooimgr
|
||
|
except Exception as e:
|
||
|
sys.stderr.write(f"{mod_path} {sys.path} {traceback.print_exc()}")
|
||
|
raise
|
||
|
import ansible
|
||
|
|
||
|
DOCUMENTATION = rf'''
|
||
|
---
|
||
|
module: gentooimgr
|
||
|
|
||
|
short_description: Gentoo Image Builder for Cloud and Turnkey ISO installers
|
||
|
|
||
|
|
||
|
version_added: "1.0.0"
|
||
|
|
||
|
description:
|
||
|
* This project enables easy access to building ``systemd`` or ``openrc`` -based images.
|
||
|
* Performs automatic download AND verification of the linux iso, stage3 tarball and portage.
|
||
|
* Caches the iso and stage3 .txt files for at most a day before redownloading and rechecking for new files
|
||
|
* Sane and readable cli commands to build, run and test.
|
||
|
* Step system to enable user to continue off at the same place if a step fails
|
||
|
* No heavy packages like rust included ** TODO
|
||
|
|
||
|
options:
|
||
|
action:
|
||
|
description: The action to be run by the image builder
|
||
|
choices:
|
||
|
- build
|
||
|
- run
|
||
|
- status
|
||
|
- install
|
||
|
- chroot
|
||
|
- unchroot
|
||
|
- command
|
||
|
- shrink
|
||
|
- kernel
|
||
|
required: true
|
||
|
# clean test
|
||
|
config:
|
||
|
default: cloud.json
|
||
|
description: init configuration file or or base.json or cloud.json
|
||
|
required: false
|
||
|
loglevel:
|
||
|
default: {logging.INFO}
|
||
|
description: python logging level <= 50, INFO=20
|
||
|
required: false
|
||
|
threads:
|
||
|
default: 1
|
||
|
description: Number of threads to use
|
||
|
required: false
|
||
|
profile:
|
||
|
default: openrc
|
||
|
description: The init system
|
||
|
choices:
|
||
|
- openrc
|
||
|
- systemd
|
||
|
required: false
|
||
|
kernel_dir:
|
||
|
default: /usr/src/linux
|
||
|
description: Where kernel is specified. By default uses the active linux kernel
|
||
|
required: false
|
||
|
portage:
|
||
|
description: Extract the specified portage tarball onto the filesystem
|
||
|
required: false
|
||
|
stage3:
|
||
|
description: Extract the specified stage3 package onto the filesystema
|
||
|
required: false
|
||
|
action_args:
|
||
|
default: []
|
||
|
description: Arguments for some of the actions - UNUSED!
|
||
|
required: false
|
||
|
temporary_dir:
|
||
|
description: Path to temporary directory for downloading files (20G)
|
||
|
required: false
|
||
|
qcow:
|
||
|
description: Path to file to serve as the base image
|
||
|
required: false
|
||
|
|
||
|
# Specify this value according to your collection
|
||
|
# in format of namespace.collection.doc_fragment_name
|
||
|
# extends_documentation_fragment:
|
||
|
# - my_namespace.my_collection.my_doc_fragment_name
|
||
|
|
||
|
author:
|
||
|
- Your Name (@yourGitHubHandle)
|
||
|
'''
|
||
|
|
||
|
#[-y DAYS]
|
||
|
# [-d DOWNLOAD_DIR]
|
||
|
# [-f]
|
||
|
# [--format FORMAT]
|
||
|
|
||
|
EXAMPLES = r'''
|
||
|
# Pass in a message
|
||
|
- name: Test with a message
|
||
|
my_namespace.my_collection.my_test:
|
||
|
name: hello world
|
||
|
|
||
|
# pass in a message and have changed true
|
||
|
- name: Test with a message and changed output
|
||
|
my_namespace.my_collection.my_test:
|
||
|
name: hello world
|
||
|
new: true
|
||
|
|
||
|
# fail the module
|
||
|
- name: Test failure of the module
|
||
|
my_namespace.my_collection.my_test:
|
||
|
name: fail me
|
||
|
'''
|
||
|
|
||
|
RETURN = r'''
|
||
|
# These are examples of possible return values, and in general should use other names for return values.
|
||
|
message:
|
||
|
description: The output message that the test module generates.
|
||
|
type: str
|
||
|
returned: always
|
||
|
sample: 'goodbye'
|
||
|
'''
|
||
|
|
||
|
from ansible.module_utils.basic import AnsibleModule
|
||
|
|
||
|
|
||
|
def run_module():
|
||
|
# define available arguments/parameters a user can pass to the module
|
||
|
module_args = dict(
|
||
|
action=dict(type='str', required=True),
|
||
|
loglevel=dict(type='int', required=False, default=logging.INFO),
|
||
|
threads=dict(type='int', required=False, default=1),
|
||
|
config=dict(type='str', default='cloud.json', required=False),
|
||
|
profile=dict(type='str', required=False),
|
||
|
kernel_dir=dict(type='path', required=False),
|
||
|
portage=dict(type='path', required=False),
|
||
|
stage3=dict(type='path', required=False),
|
||
|
temporary_dir=dict(type='path', required=False, default=pathlib.Path(os.getcwd())),
|
||
|
download_dir=dict(type='path', required=False, default=pathlib.Path(os.getcwd())),
|
||
|
qcow=dict(type='path', required=False),
|
||
|
)
|
||
|
|
||
|
# seed the result dict in the object
|
||
|
# we primarily care about changed and state
|
||
|
# changed is if this module effectively modified the target
|
||
|
# state will include any data that you want your module to pass back
|
||
|
# for consumption, for example, in a subsequent task
|
||
|
result = dict(
|
||
|
changed=False,
|
||
|
original_message='',
|
||
|
message=''
|
||
|
)
|
||
|
|
||
|
# the AnsibleModule object will be our abstraction working with Ansible
|
||
|
# this includes instantiation, a couple of common attr would be the
|
||
|
# args/params passed to the execution, as well as if the module
|
||
|
# supports check mode
|
||
|
module = AnsibleModule(
|
||
|
argument_spec=module_args,
|
||
|
supports_check_mode=True
|
||
|
)
|
||
|
|
||
|
# if the user is working with this module in only check mode we do not
|
||
|
# want to make any changes to the environment, just return the current
|
||
|
# state with no modifications
|
||
|
if module.check_mode:
|
||
|
module.exit_json(**result)
|
||
|
|
||
|
# manipulate or modify the state as needed (this is going to be the
|
||
|
# part where your module will do what it needs to do)
|
||
|
# if module.params.get('thirsty'):
|
||
|
|
||
|
oargs = Namespace(**module.params)
|
||
|
# during the execution of the module, if there is an exception or a
|
||
|
# conditional state that effectively causes a failure, run
|
||
|
# AnsibleModule.fail_json() to pass in the message and the result
|
||
|
result['original_message'] = ""
|
||
|
try:
|
||
|
from gentooimgr.__main__ import main
|
||
|
retval = main(oargs)
|
||
|
except Exception as e:
|
||
|
result['message'] = str(e)
|
||
|
e = traceback.print_exc()
|
||
|
if e: result['original_message'] += f"{e}"
|
||
|
module.fail_json(msg='Exception', **result)
|
||
|
else:
|
||
|
result['message'] = str(retval)
|
||
|
|
||
|
# use whatever logic you need to determine whether or not this module
|
||
|
# made any modifications to your target
|
||
|
if dArgs['action'] in ['status']:
|
||
|
result['changed'] = False
|
||
|
else:
|
||
|
result['changed'] = True
|
||
|
|
||
|
# in the event of a successful module execution, you will want to
|
||
|
# simple AnsibleModule.exit_json(), passing the key/value results
|
||
|
module.exit_json(**result)
|
||
|
|
||
|
|
||
|
def main():
|
||
|
run_module()
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|
||
|
|