diff --git a/lib/ansible/modules/extras/cloud/xenserver_facts.py b/lib/ansible/modules/extras/cloud/xenserver_facts.py
new file mode 100644
index 0000000000..1977f9fe2b
--- /dev/null
+++ b/lib/ansible/modules/extras/cloud/xenserver_facts.py
@@ -0,0 +1,196 @@
+#!/usr/bin/python -tt
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+
+DOCUMENTATION = '''
+---
+module: xenserver_facts
+version_added: 1.7
+short_description: get facts reported on xenserver
+description:
+ - Reads data out of XenAPI, can be used instead of multiple xe commands.
+author: Andy Hill, Tim Rupp
+'''
+
+import platform
+import sys
+import XenAPI
+
+EXAMPLES = '''
+- name: Gather facts from xenserver
+ xenserver:
+
+- name: Print running VMs
+ debug: msg="{{ item }}"
+ with_items: xs_vms.keys()
+ when: xs_vms[item]['power_state'] == "Running"
+
+TASK: [Print running VMs] ***********************************************************
+skipping: [10.13.0.22] => (item=CentOS 4.7 (32-bit))
+ok: [10.13.0.22] => (item=Control domain on host: 10.0.13.22) => {
+ "item": "Control domain on host: 10.0.13.22",
+ "msg": "Control domain on host: 10.0.13.22"
+}
+'''
+
+class XenServerFacts:
+ def __init__(self):
+ self.codes = {
+ '5.5.0': 'george',
+ '5.6.100': 'oxford',
+ '6.0.0': 'boston',
+ '6.1.0': 'tampa',
+ '6.2.0': 'clearwater'
+ }
+
+ @property
+ def version(self):
+ # Be aware! Deprecated in Python 2.6!
+ result = platform.dist()[1]
+ return result
+
+ @property
+ def codename(self):
+ if self.version in self.codes:
+ result = self.codes[self.version]
+ else:
+ result = None
+
+ return result
+
+
+def get_xenapi_session():
+ try:
+ session = XenAPI.xapi_local()
+ session.xenapi.login_with_password('', '')
+ return session
+ except XenAPI.Failure:
+ sys.exit(1)
+
+
+def get_networks(session):
+ recs = session.xenapi.network.get_all_records()
+ xs_networks = {}
+ networks = change_keys(recs, key='uuid')
+ for network in networks.itervalues():
+ xs_networks[network['name_label']] = network
+ return xs_networks
+
+
+def get_pifs(session):
+ recs = session.xenapi.PIF.get_all_records()
+ pifs = change_keys(recs, key='uuid')
+ xs_pifs = {}
+ devicenums = range(0, 7)
+ for pif in pifs.itervalues():
+ for eth in devicenums:
+ interface_name = "eth%s" % (eth)
+ bond_name = interface_name.replace('eth', 'bond')
+ if pif['device'] == interface_name:
+ xs_pifs[interface_name] = pif
+ elif pif['device'] == bond_name:
+ xs_pifs[bond_name] = pif
+ return xs_pifs
+
+
+def get_vlans(session):
+ recs = session.xenapi.VLAN.get_all_records()
+ return change_keys(recs, key='tag')
+
+
+def change_keys(recs, key='uuid', filter_func=None):
+ """
+ Take a xapi dict, and make the keys the value of recs[ref][key].
+
+ Preserves the ref in rec['ref']
+
+ """
+ new_recs = {}
+
+ for ref, rec in recs.iteritems():
+ if filter_func is not None and not filter_func(rec):
+ continue
+
+ new_recs[rec[key]] = rec
+ new_recs[rec[key]]['ref'] = ref
+
+ return new_recs
+
+def get_host(session):
+ """Get the host"""
+ host_recs = session.xenapi.host.get_all()
+ # We only have one host, so just return its entry
+ return session.xenapi.host.get_record(host_recs[0])
+
+def get_vms(session):
+ xs_vms = {}
+ recs = session.xenapi.VM.get_all()
+ if not recs:
+ return None
+
+ vms = change_keys(recs, key='uuid')
+ for vm in vms.itervalues():
+ xs_vms[vm['name_label']] = vm
+ return xs_vms
+
+
+def get_srs(session):
+ xs_srs = {}
+ recs = session.xenapi.SR.get_all()
+ if not recs:
+ return None
+ srs = change_keys(recs, key='uuid')
+ for sr in srs.itervalues():
+ xs_srs[sr['name_label']] = sr
+ return xs_srs
+
+def main():
+ module = AnsibleModule({})
+
+ obj = XenServerFacts()
+ session = get_xenapi_session()
+
+
+ data = {
+ 'xenserver_version': obj.version,
+ 'xenserver_codename': obj.codename
+ }
+
+ xs_networks = get_networks(session)
+ xs_pifs = get_pifs(session)
+ xs_vlans = get_vlans(session)
+ xs_vms = get_vms(session)
+ xs_srs = get_srs(session)
+
+ if xs_vlans:
+ data['xs_vlans'] = xs_vlans
+ if xs_pifs:
+ data['xs_pifs'] = xs_pifs
+ if xs_networks:
+ data['xs_networks'] = xs_networks
+
+ if xs_vms:
+ data['xs_vms'] = xs_vms
+
+ if xs_srs:
+ data['xs_srs'] = xs_srs
+
+ module.exit_json(ansible=data)
+
+# this is magic, see lib/ansible/module_common.py
+#<>
+
+main()