|
|
6e61fb |
#!/usr/bin/python
|
|
|
6e61fb |
from ansible.module_utils.basic import AnsibleModule
|
|
|
6e61fb |
from ansible.module_utils import common_koji
|
|
|
6e61fb |
|
|
|
6e61fb |
|
|
|
6e61fb |
ANSIBLE_METADATA = {
|
|
|
6e61fb |
'metadata_version': '1.0',
|
|
|
6e61fb |
'status': ['preview'],
|
|
|
6e61fb |
'supported_by': 'community'
|
|
|
6e61fb |
}
|
|
|
6e61fb |
|
|
|
6e61fb |
|
|
|
6e61fb |
DOCUMENTATION = '''
|
|
|
6e61fb |
---
|
|
|
6e61fb |
module: koji_host
|
|
|
6e61fb |
|
|
|
6e61fb |
short_description: Create and manage Koji build hosts
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- This module can add new hosts and manage existing hosts.
|
|
|
6e61fb |
- 'Koji only supports adding new hosts, not deleting them. Once they are
|
|
|
6e61fb |
defined, you can enable or disable the hosts with "state: enabled" or
|
|
|
6e61fb |
"state: disabled".'
|
|
|
6e61fb |
|
|
|
6e61fb |
options:
|
|
|
6e61fb |
name:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- The name of the Koji builder.
|
|
|
6e61fb |
- 'Example: "builder1.example.com".'
|
|
|
6e61fb |
required: true
|
|
|
6e61fb |
arches:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- The list of arches this host supports.
|
|
|
6e61fb |
- 'Example: [x86_64]'
|
|
|
6e61fb |
required: true
|
|
|
6e61fb |
channels:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- The list of channels this host should belong to.
|
|
|
6e61fb |
- If you specify a completely new channel here, Ansible will create the
|
|
|
6e61fb |
channel on the hub. For example, when you set up OSBS with Koji, you
|
|
|
6e61fb |
must add a builder host to a new "container" channel. You can simply
|
|
|
6e61fb |
specify "container" in the list here, and Ansible will create the new
|
|
|
6e61fb |
"container" channel when it adds your host to that channel.
|
|
|
6e61fb |
- 'Example: [default, createrepo]'
|
|
|
6e61fb |
required: false
|
|
|
6e61fb |
state:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- Whether to set this host as "enabled" or "disabled". If unset, this
|
|
|
6e61fb |
defaults to "enabled".
|
|
|
6e61fb |
krb_principal:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- Set a non-default krb principal for this host. If unset, Koji will
|
|
|
6e61fb |
use the standard krb principal scheme for builder accounts.
|
|
|
6e61fb |
capacity:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- Total task weight for this host. This is a float value. If unset,
|
|
|
6e61fb |
Koji will use the standard capacity for a host (2.0).
|
|
|
6e61fb |
- 'Example: 10.0'
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- Human-readable description for this host.
|
|
|
6e61fb |
comment:
|
|
|
6e61fb |
description:
|
|
|
6e61fb |
- Human-readable comment explaining the current state of the host. You
|
|
|
6e61fb |
may write a description here explaining how this host was set up, or
|
|
|
6e61fb |
why this host is currently offline.
|
|
|
6e61fb |
requirements:
|
|
|
6e61fb |
- "python >= 2.7"
|
|
|
6e61fb |
- "koji"
|
|
|
6e61fb |
'''
|
|
|
6e61fb |
|
|
|
6e61fb |
EXAMPLES = '''
|
|
|
6e61fb |
- name: create a koji host
|
|
|
6e61fb |
hosts: localhost
|
|
|
6e61fb |
tasks:
|
|
|
6e61fb |
- name: Add new builder1 host
|
|
|
6e61fb |
koji_host:
|
|
|
6e61fb |
name: builder1.example.com
|
|
|
6e61fb |
arches: [x86_64]
|
|
|
6e61fb |
state: enabled
|
|
|
6e61fb |
channels:
|
|
|
6e61fb |
- createrepo
|
|
|
6e61fb |
- default
|
|
|
6e61fb |
|
|
|
6e61fb |
- name: Add new builder host for OSBS
|
|
|
6e61fb |
koji_host:
|
|
|
6e61fb |
name: containerbuild1.example.com
|
|
|
6e61fb |
arches: [x86_64]
|
|
|
6e61fb |
state: enabled
|
|
|
6e61fb |
channels:
|
|
|
6e61fb |
# This will automatically create the "container" channel
|
|
|
6e61fb |
# if it does not already exist:
|
|
|
6e61fb |
- container
|
|
|
6e61fb |
'''
|
|
|
6e61fb |
|
|
|
6e61fb |
|
|
|
6e61fb |
def ensure_channels(session, host_id, host_name, check_mode, desired_channels):
|
|
|
6e61fb |
"""
|
|
|
6e61fb |
Ensure that given host belongs to given channels (and only them).
|
|
|
6e61fb |
|
|
|
6e61fb |
:param session: Koji client session
|
|
|
6e61fb |
:param int host_id: Koji host ID
|
|
|
6e61fb |
:param int host_name: Koji host name
|
|
|
6e61fb |
:param bool check_mode: don't make any changes
|
|
|
6e61fb |
:param list desired_channels: channels that the host should belong to
|
|
|
6e61fb |
"""
|
|
|
6e61fb |
result = {'changed': False, 'stdout_lines': []}
|
|
|
6e61fb |
common_koji.ensure_logged_in(session)
|
|
|
6e61fb |
current_channels = session.listChannels(host_id)
|
|
|
6e61fb |
current_channels = [channel['name'] for channel in current_channels]
|
|
|
6e61fb |
for channel in current_channels:
|
|
|
6e61fb |
if channel not in desired_channels:
|
|
|
6e61fb |
if not check_mode:
|
|
|
6e61fb |
session.removeHostFromChannel(host_name, channel)
|
|
|
6e61fb |
result['stdout_lines'].append('removed host from channel %s' % channel)
|
|
|
6e61fb |
result['changed'] = True
|
|
|
6e61fb |
for channel in desired_channels:
|
|
|
6e61fb |
if channel not in current_channels:
|
|
|
6e61fb |
if not check_mode:
|
|
|
6e61fb |
session.addHostToChannel(host_name, channel, create=True)
|
|
|
6e61fb |
result['stdout_lines'].append('added host to channel %s' % channel)
|
|
|
6e61fb |
result['changed'] = True
|
|
|
6e61fb |
return result
|
|
|
6e61fb |
|
|
|
6e61fb |
|
|
|
6e61fb |
def ensure_host(session, name, check_mode, state, arches, krb_principal,
|
|
|
6e61fb |
channels, **kwargs):
|
|
|
6e61fb |
"""
|
|
|
6e61fb |
Ensure that this host is configured in Koji.
|
|
|
6e61fb |
|
|
|
6e61fb |
:param session: Koji client session
|
|
|
6e61fb |
:param str name: Koji builder host name
|
|
|
6e61fb |
:param bool check_mode: don't make any changes
|
|
|
6e61fb |
:param str state: "enabled" or "disabled"
|
|
|
6e61fb |
:param list arches: list of arches for this builder.
|
|
|
6e61fb |
:param str krb_principal: custom kerberos principal, or None
|
|
|
6e61fb |
:param list chanels: list of channels this host should belong to.
|
|
|
6e61fb |
:param **kwargs: Pass remaining kwargs directly into Koji's editHost RPC.
|
|
|
6e61fb |
"""
|
|
|
6e61fb |
result = {'changed': False, 'stdout_lines': []}
|
|
|
6e61fb |
host = session.getHost(name)
|
|
|
6e61fb |
if not host:
|
|
|
6e61fb |
result['changed'] = True
|
|
|
6e61fb |
result['stdout_lines'].append('created host')
|
|
|
6e61fb |
if check_mode:
|
|
|
6e61fb |
return result
|
|
|
6e61fb |
common_koji.ensure_logged_in(session)
|
|
|
6e61fb |
id_ = session.addHost(name, arches, krb_principal)
|
|
|
6e61fb |
host = session.getHost(id_)
|
|
|
6e61fb |
if state == 'enabled':
|
|
|
6e61fb |
if not host['enabled']:
|
|
|
6e61fb |
result['changed'] = True
|
|
|
6e61fb |
result['stdout_lines'].append('enabled host')
|
|
|
6e61fb |
if not check_mode:
|
|
|
6e61fb |
common_koji.ensure_logged_in(session)
|
|
|
6e61fb |
session.enableHost(name)
|
|
|
6e61fb |
elif state == 'disabled':
|
|
|
6e61fb |
if host['enabled']:
|
|
|
6e61fb |
result['changed'] = True
|
|
|
6e61fb |
result['stdout_lines'].append('disabled host')
|
|
|
6e61fb |
if not check_mode:
|
|
|
6e61fb |
common_koji.ensure_logged_in(session)
|
|
|
6e61fb |
session.disableHost(name)
|
|
|
6e61fb |
edits = {}
|
|
|
6e61fb |
if ' '.join(arches) != host['arches']:
|
|
|
6e61fb |
edits['arches'] = ' '.join(arches)
|
|
|
6e61fb |
for key, value in kwargs.items():
|
|
|
6e61fb |
if value is None:
|
|
|
6e61fb |
continue # Ansible did not set this parameter.
|
|
|
6e61fb |
if key in host and kwargs[key] != host[key]:
|
|
|
6e61fb |
edits[key] = value
|
|
|
6e61fb |
if edits:
|
|
|
6e61fb |
result['changed'] = True
|
|
|
6e61fb |
for edit in edits.keys():
|
|
|
6e61fb |
result['stdout_lines'].append('edited host %s' % edit)
|
|
|
6e61fb |
if not check_mode:
|
|
|
6e61fb |
common_koji.ensure_logged_in(session)
|
|
|
6e61fb |
session.editHost(name, **edits)
|
|
|
6e61fb |
|
|
|
6e61fb |
# Ensure host is member of desired channels.
|
|
|
6e61fb |
if channels not in (None, ''):
|
|
|
6e61fb |
channels_result = ensure_channels(session, host['id'],
|
|
|
6e61fb |
name, check_mode, channels)
|
|
|
6e61fb |
if channels_result['changed']:
|
|
|
6e61fb |
result['changed'] = True
|
|
|
6e61fb |
result['stdout_lines'].extend(channels_result['stdout_lines'])
|
|
|
6e61fb |
|
|
|
6e61fb |
return result
|
|
|
6e61fb |
|
|
|
6e61fb |
|
|
|
6e61fb |
def run_module():
|
|
|
6e61fb |
module_args = dict(
|
|
|
6e61fb |
koji=dict(type='str', required=False),
|
|
|
6e61fb |
name=dict(type='str', required=True),
|
|
|
6e61fb |
arches=dict(type='list', required=True),
|
|
|
6e61fb |
channels=dict(type='list', required=False, default=None),
|
|
|
6e61fb |
krb_principal=dict(type='str', required=False, default=None),
|
|
|
6e61fb |
capacity=dict(type='float', required=False, default=None),
|
|
|
6e61fb |
description=dict(type='str', required=False, default=None),
|
|
|
6e61fb |
comment=dict(type='str', required=False, default=None),
|
|
|
6e61fb |
state=dict(type='str', choices=[
|
|
|
6e61fb |
'enabled', 'disabled'], required=False, default='enabled'),
|
|
|
6e61fb |
)
|
|
|
6e61fb |
module = AnsibleModule(
|
|
|
6e61fb |
argument_spec=module_args,
|
|
|
6e61fb |
supports_check_mode=True
|
|
|
6e61fb |
)
|
|
|
6e61fb |
|
|
|
6e61fb |
if not common_koji.HAS_KOJI:
|
|
|
6e61fb |
module.fail_json(msg='koji is required for this module')
|
|
|
6e61fb |
|
|
|
6e61fb |
check_mode = module.check_mode
|
|
|
6e61fb |
params = module.params
|
|
|
6e61fb |
profile = params['koji']
|
|
|
6e61fb |
name = params['name']
|
|
|
6e61fb |
state = params['state']
|
|
|
6e61fb |
|
|
|
6e61fb |
session = common_koji.get_session(profile)
|
|
|
6e61fb |
|
|
|
6e61fb |
result = ensure_host(session, name, check_mode, state,
|
|
|
6e61fb |
arches=params['arches'],
|
|
|
6e61fb |
channels=params['channels'],
|
|
|
6e61fb |
krb_principal=params['krb_principal'],
|
|
|
6e61fb |
capacity=params['capacity'],
|
|
|
6e61fb |
description=params['description'],
|
|
|
6e61fb |
comment=params['comment'])
|
|
|
6e61fb |
module.exit_json(**result)
|
|
|
6e61fb |
|
|
|
6e61fb |
|
|
|
6e61fb |
def main():
|
|
|
6e61fb |
run_module()
|
|
|
6e61fb |
|
|
|
6e61fb |
|
|
|
6e61fb |
if __name__ == '__main__':
|
|
|
6e61fb |
main()
|