示例#1
0
def domain_has_changed(vir_dom, domain, active=False):
    flags = libvirt.VIR_DOMAIN_XML_SECURE
    flags |= libvirt.VIR_DOMAIN_XML_INACTIVE if not active else 0
    current = util.from_xml(vir_dom.XMLDesc(flags))
    eq, path, cause = util.compare(domain, current, 'domain')
    return not eq, path, cause
示例#2
0
def run_module():
    module_args = dict(
        state=dict(type='str',
                   choices=[
                       STATE_DEFINED, STATE_CREATED, STATE_DESTROYED,
                       STATE_UNDEFINED, STATE_STOPPED
                   ],
                   default=STATE_CREATED),
        name=dict(type='str'),
        domain=dict(type='dict'),
        xml=dict(type='str'),
        update=dict(type='bool', default=False),
        persistent=dict(type='bool', default=True),
        destroy_graceful=dict(type='bool', default=True),
        undefine_destroy=dict(type='bool', default=True),
        undefine_managed_save=dict(type='bool', default=False),
        undefine_snapshots_metadata=dict(type='bool', default=False),
        undefine_keep_nvram=dict(type='bool', default=False),
        undefine_nvram=dict(type='bool', default=False),
        shutdown_acpi_power_btn=dict(type='bool', default=False),
        shutdown_guest_agent=dict(type='bool', default=False),
        shutdown_initctl=dict(type='bool', default=False),
        shutdown_signal=dict(type='bool', default=False),
        shutdown_paravirt=dict(type='bool', default=False),
        # undefine_remove_all_storage=dict(type='bool', default=False),  # TODO
        # undefine_storage=dict(type='list'),  # TODO
        # undefine_wipe_storage=dict(type='bool', default=False),  # TODO
    )
    module_args.update(util.common_args)

    result = dict(changed=False, )

    module = AnsibleModule(
        argument_spec=module_args,
        mutually_exclusive=[
            ['domain', 'xml', 'name'],
            ['undefine_keep_nvram', 'undefine_nvram'],
        ],
        required_if=[
            ['state', STATE_CREATED, ['domain', 'xml'], True],
            ['state', STATE_DEFINED, ['domain', 'xml'], True],
            ['state', STATE_DESTROYED, ['name']],
        ],
    )

    domain = module.params['domain']
    if module.params['xml'] is not None:
        domain = util.from_xml(module.params['xml'])

    state = module.params['state']
    name = module.params['name'] or domain['name']
    if not name.strip():
        module.fail_json(msg='missing domain name', **result)
    update = module.params['update']
    persistent = module.params['persistent']
    if state == STATE_DEFINED and not persistent:
        module.fail_json(
            msg='persistent cannot be false when state is defined')
    destroy_graceful = module.params['destroy_graceful']
    undefine_destroy = module.params['undefine_destroy']
    undefine_managed_save = module.params['undefine_managed_save']
    undefine_snapshots_metadata = module.params['undefine_snapshots_metadata']
    undefine_keep_nvram = module.params['undefine_keep_nvram']
    undefine_nvram = module.params['undefine_nvram']
    shutdown_acpi_power_btn = module.params['shutdown_acpi_power_btn']
    shutdown_guest_agent = module.params['shutdown_guest_agent']
    shutdown_initctl = module.params['shutdown_initctl']
    shutdown_signal = module.params['shutdown_signal']
    shutdown_paravirt = module.params['shutdown_paravirt']

    conn = util.get_conn(module.params)  # type: libvirt.virConnect
    if conn is None:
        module.fail_json(msg='cannot open connection to libvirt', **result)

    try:
        vir_dom = conn.lookupByName(name)  # type: libvirt.virDomain
        if domain:
            domain['uuid'] = vir_dom.UUIDString()
    except libvirt.libvirtError:
        vir_dom = None

    if state == STATE_DEFINED:
        if vir_dom is None:
            result['changed'] = True
            vir_dom = define_domain(conn, domain)
            result.update(util.describe_domain(vir_dom))
        elif update:
            changed, path, cause = domain_has_changed(vir_dom, domain)
            if changed:
                result['changed'] = True
                result['changed_path'] = path
                result['changed_cause'] = cause
                vir_dom = define_domain(conn, domain)
                changed, path, cause = domain_has_changed(vir_dom, domain)
                if changed:
                    module.warn(
                        'the provided domain definition was modified by the virtualization platform, '
                        'check the current definition to avoid unnecessary updates'
                    )
                    result['domain'] = domain
                    result['changed_path'] = path
                    result['changed_cause'] = cause
                result.update(util.describe_domain(vir_dom))
    elif state == STATE_CREATED:
        if vir_dom is None:
            result['changed'] = True
            if persistent:
                vir_dom = define_domain(conn, domain)
                vir_dom.create()
            else:
                vir_dom = create_domain(conn, domain)
            result.update(util.describe_domain(vir_dom))
        elif update:
            if vir_dom.isActive():
                # TODO: detect changes
                changed, path, cause = domain_has_changed(vir_dom,
                                                          domain,
                                                          active=True)
                if changed:
                    module.warn(
                        'some configurations cannot be applied to running domain'
                    )
                    module.warn('{}: {}'.format(path, cause))
            if persistent:
                result['changed'] = True
                vir_dom = define_domain(conn, domain)
                if not vir_dom.isActive():
                    vir_dom.create()
                result.update(util.describe_domain(vir_dom))
            elif vir_dom.isPersistent():
                result['changed'] = True
                undefine_domain(vir_dom, undefine_managed_save,
                                undefine_snapshots_metadata,
                                undefine_keep_nvram, undefine_nvram)
    elif state == STATE_UNDEFINED:
        if vir_dom is not None:
            destroy = vir_dom.isActive() and undefine_destroy
            if vir_dom.isPersistent():
                result['changed'] = True
                undefine_domain(vir_dom, undefine_managed_save,
                                undefine_snapshots_metadata,
                                undefine_keep_nvram, undefine_nvram)
            if destroy:
                result['changed'] = True
                destroy_domain(vir_dom, destroy_graceful)
    elif state == STATE_DESTROYED:
        if vir_dom is not None:
            result['changed'] = True
            destroy_domain(vir_dom, destroy_graceful)
    elif state == STATE_STOPPED:
        if vir_dom is None:
            module.warn('domain does not exists so cannot shutdown')
        else:
            result['changed'] = True
            domain_shutdown(vir_dom, shutdown_acpi_power_btn,
                            shutdown_guest_agent, shutdown_initctl,
                            shutdown_paravirt, shutdown_signal)

    module.exit_json(**result)
示例#3
0
def run_module():
    module_args = dict(
        state=dict(type='str',
                   choices=[STATE_DEFINED, STATE_STARTED, STATE_UNDEFINED, STATE_DESTROYED],
                   default=STATE_STARTED),
        name=dict(type='str'),
        network=dict(type='dict'),
        xml=dict(type='str'),
        autostart=dict(type='bool', default=True),
        persistent=dict(type='bool', default=True),
        undefine_destroy=dict(type='bool', default=True),
    )
    module_args.update(util.common_args)

    result = dict(
        changed=False,
    )

    module = AnsibleModule(
        argument_spec=module_args,
        mutually_exclusive=[
            ['domain', 'xml', 'name'],
        ],
        required_if=[
            ['state', STATE_STARTED, ['network', 'xml'], True],
            ['state', STATE_DEFINED, ['network', 'xml'], True],
            ['state', STATE_UNDEFINED, ['name']],
            ['state', STATE_DESTROYED, ['name']],
        ],
    )

    network = module.params['network']
    if module.params['xml'] is not None:
        network = util.from_xml(module.params['xml'])

    state = module.params['state']
    name = module.params['name'] or network['name']
    if not name.strip():
        module.fail_json(msg='missing network name', **result)
    autostart = module.params['autostart']
    persistent = module.params['persistent']
    if state == STATE_DEFINED and not persistent:
        module.fail_json(msg='persistent cannot be false when state is defined')
    undefine_destroy = module.params['undefine_destroy']

    conn = util.get_conn(module.params)  # type: libvirt.virConnect
    if conn is None:
        module.fail_json(msg='cannot open connection to libvirt', **result)

    try:
        vir_net = conn.networkLookupByName(name)  # type: libvirt.virNetwork
        if network:
            network['uuid'] = vir_net.UUIDString()
    except libvirt.libvirtError as e:
        vir_net = None

    if state == STATE_DEFINED:
        if vir_net is None:
            result['changed'] = True
            vir_net = define_network(conn, network, autostart)
            result.update(util.describe_network(vir_net))
        else:
            changed, path, cause = network_has_changed(vir_net, network)
            if changed:
                result['changed'] = True
                result['changed_path'] = path
                result['changed_cause'] = cause
                vir_net = define_network(conn, network, autostart)
                changed, path, cause = network_has_changed(vir_net, network)
                if changed:
                    module.warn('the provided network definition was modified by the virtualization platform, '
                                'check the current definition to avoid unnecessary updates')
                    result['network'] = network
                    result['changed_path'] = path
                    result['changed_cause'] = cause
                result.update(util.describe_network(vir_net))
    elif state == STATE_STARTED:
        if vir_net is None:
            result['changed'] = True
            if persistent:
                vir_net = define_network(conn, network, autostart)
                vir_net.create()
            else:
                vir_net = create_network(conn, network)
            result.update(util.describe_network(vir_net))
        else:
            if vir_net.isActive():
                # TODO: detect changes
                changed, path, cause = network_has_changed(vir_net, network, active=True)
                if changed:
                    module.warn('some configurations cannot be applied to running network')
                    module.warn('{}: {}'.format(path, cause))
            if persistent:
                result['changed'] = True
                vir_net = define_network(conn, network, autostart)
                if not vir_net.isActive():
                    vir_net.create()
                result.update(util.describe_network(vir_net))
            elif vir_net.isPersistent():
                result['changed'] = True
                undefine_network(vir_net)
    elif state == STATE_UNDEFINED:
        if vir_net is not None:
            destroy = vir_net.isActive() and undefine_destroy
            if vir_net.isPersistent():
                result['changed'] = True
                undefine_network(vir_net)
            if destroy:
                result['changed'] = True
                destroy_network(vir_net)
    elif state == STATE_DESTROYED:
        if vir_net is not None:
            result['changed'] = True
            destroy_network(vir_net)

    module.exit_json(**result)
示例#4
0
def network_has_changed(vir_net, network, active=False):
    # type: (libvirt.virNetwork, dict, bool) -> tuple
    flags = libvirt.VIR_NETWORK_XML_INACTIVE if not active else 0
    current = util.from_xml(vir_net.XMLDesc(flags))
    eq, path, cause = util.compare(network, current, 'network')
    return not eq, path, cause
示例#5
0
def run_module():
    module_args = dict(
        state=dict(type='str',
                   choices=[STATE_PRESENT, STATE_ABSENT],
                   default=STATE_PRESENT),
        domain=dict(type='str', required=True),
        alias=dict(type='str'),
        type=dict(type='str',
                  choices=['emulator', 'disk', 'filesystem', 'controller', 'lease', 'hostdev', 'source', 'redirdev',
                           'smartcard', 'interface', 'input', 'hub', 'graphics', 'video', 'parallel', 'serial',
                           'console', 'channel', 'sound', 'watchdog', 'memballoon', 'rng', 'tpm', 'nvram', 'panic',
                           'shmem', 'memory', 'iommu', 'vsock']),
        device=dict(type='dict'),
        xml=dict(type='str'),
        update=dict(type='bool', default=False),
    )
    module_args.update(util.common_args)

    result = dict(
        changed=False,
    )

    module = AnsibleModule(
        argument_spec=module_args,
        mutually_exclusive=[
            ['device', 'xml'],
            ['alias', 'type'],
        ],
        required_if=[
            ['state', STATE_PRESENT, ['domain', 'xml'], True],
            ['state', STATE_ABSENT, ['alias', 'domain', 'xml'], True],
        ],
    )

    state = module.params['state']
    domain = module.params['domain']

    device_type = module.params['type']
    device = module.params['device']
    if module.params['xml'] is not None:
        device = util.from_xml(module.params['xml'])

    alias = module.params['alias'] or device.get('alias', {}).get('_name')
    if alias and not alias.startswith('ua-'):
        module.fail_json(msg='alias must have "ua-" prefix', **result)

    update = module.params['update']

    conn = util.get_conn(module.params)  # type: libvirt.virConnect
    if conn is None:
        module.fail_json(msg='cannot open connection to libvirt', **result)

    try:
        vir_dom = conn.lookupByName(domain)  # type: libvirt.virDomain
    except libvirt.libvirtError:
        module.fail_json(msg='domain not found', **result)

    # TODO: Check if device already exists. The rules are complex.
    # search disk by <target dev='name'/> then by <source file='name'/>
    if state == STATE_PRESENT:
        xml = encode_device(device_type, device)
        if alias:
            if not alias_exists(vir_dom, device_type, alias):
                vir_dom.attachDeviceFlags(xml, libvirt.VIR_DOMAIN_AFFECT_CURRENT)
                result['changed'] = True
        else:
            vir_dom.attachDeviceFlags(xml, libvirt.VIR_DOMAIN_AFFECT_CURRENT)
            result['changed'] = True
    elif state == STATE_ABSENT:
        if alias:
            if alias_exists(vir_dom, device_type, alias):
                vir_dom.detachDeviceAlias(alias, libvirt.VIR_DOMAIN_AFFECT_CURRENT)
                result['changed'] = True
        else:
            xml = encode_device(device_type, device)
            vir_dom.detachDeviceFlags(xml, libvirt.VIR_DOMAIN_AFFECT_CURRENT)
            result['changed'] = True  # TODO: Check if has changed

    module.exit_json(**result)
示例#6
0
def run_module():
    module_args = dict(
        state=dict(type='str', choices=['absent', 'present'], default='present'),
        name=dict(type='str'),
        pool=dict(type='str', required=True),
        volume=dict(type='dict'),
        xml=dict(type='str'),
        upload=dict(type='path'),
        resize=dict(type='int'),
    )
    module_args.update(util.common_args)

    result = dict(
        changed=False,
    )

    module = AnsibleModule(
        argument_spec=module_args,
        mutually_exclusive=[
            ['volume', 'xml']
        ],
        required_if=[
            ['state', 'present', ['volume', 'xml'], True],
            ['state', 'absent', ['name']]
        ]
    )

    state = module.params['state']
    pool = module.params['pool']
    upload = module.params['upload']
    resize = module.params['resize']

    volume = module.params['volume']
    if module.params['xml'] is not None:
        volume = util.from_xml(module.params['xml'])

    name = module.params['name'] or volume['name']
    if not name.strip():
        module.fail_json(msg='Missing volume name', **result)

    conn = util.get_conn(module.params)  # type: libvirt.virConnect
    if conn is None:
        module.fail_json(msg='Cannot open connection to libvirt', **result)

    vir_pool = None
    try:
        vir_pool = conn.storagePoolLookupByName(pool)
    except libvirt.libvirtError:
        pass

    vir_vol = None
    if vir_pool is not None:
        try:
            vir_vol = vir_pool.storageVolLookupByName(name)
        except libvirt.libvirtError:
            pass

    if state == 'absent':
        if vir_vol is not None:
            vir_vol.delete()
            result['name'] = vir_vol.name()
            result['changed'] = True
    elif state == 'present':
        if vir_vol is None:
            xml = encode_volume(volume)
            vir_vol = vir_pool.createXML(xml)
            result['changed'] = True
            result.update(util.describe_volume(vir_vol))

            if upload is not None:
                size = os.path.getsize(upload)
                if not module.check_mode:
                    stream = conn.newStream()
                    vir_vol.upload(stream, 0, size)
                    with open(upload, 'rb') as f:
                        stream.sendAll(lambda _, data, file_: file_.read(data), f)
                    stream.finish()
                result['uploaded'] = upload
                result['uploaded_bytes'] = size

            if resize is not None:
                vir_vol.resize(resize)
                result['resized'] = resize
        else:
            # TODO
            result.update(util.describe_volume(vir_vol))

    module.exit_json(**result)