summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorAnne Gentle <anne@openstack.org>2011-01-03 16:58:45 -0600
committerAnne Gentle <anne@openstack.org>2011-01-03 16:58:45 -0600
commit4ced09acb75ec0ebc431b98a84763f5f6530ba66 (patch)
tree322a50150dab9d17c087d0f2ed2d34cc47c85e11 /plugins
parentdc2c64b7d7a8ebab8a8ddb69474fdce0086a7ec8 (diff)
parentbed422cb2677f9e7505b5e7dc9ac46edb9a90dea (diff)
downloadnova-4ced09acb75ec0ebc431b98a84763f5f6530ba66.tar.gz
nova-4ced09acb75ec0ebc431b98a84763f5f6530ba66.tar.xz
nova-4ced09acb75ec0ebc431b98a84763f5f6530ba66.zip
Fixing merge conflicts with new branch
Diffstat (limited to 'plugins')
-rw-r--r--plugins/xenserver/doc/networking.rst144
-rwxr-xr-xplugins/xenserver/networking/etc/init.d/host-rules106
-rw-r--r--plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch22
-rwxr-xr-xplugins/xenserver/networking/etc/xensource/scripts/vif_rules.py119
-rw-r--r--plugins/xenserver/xenapi/README (renamed from plugins/xenapi/README)0
-rw-r--r--plugins/xenserver/xenapi/etc/xapi.d/plugins/glance132
-rw-r--r--plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore (renamed from plugins/xenapi/etc/xapi.d/plugins/objectstore)41
-rwxr-xr-xplugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py (renamed from plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py)0
8 files changed, 554 insertions, 10 deletions
diff --git a/plugins/xenserver/doc/networking.rst b/plugins/xenserver/doc/networking.rst
new file mode 100644
index 000000000..67f2d9af3
--- /dev/null
+++ b/plugins/xenserver/doc/networking.rst
@@ -0,0 +1,144 @@
+Multi Tenancy Networking Protections in XenServer
+=================================================
+
+The purpose of the vif_rules script is to allow multi-tenancy on a XenServer
+host. In a multi-tenant cloud environment a host machine needs to be able to
+enforce network isolation amongst guest instances, at both layer two and layer
+three. The rules prevent guests from taking and using unauthorized IP addresses,
+sniffing other guests traffic, and prevents ARP poisoning attacks. This current
+revision only supports IPv4, but will support IPv6 in the future.
+
+Kernel Requirements
+===================
+
+- physdev module
+- arptables support
+- ebtables support
+- iptables support
+
+If the kernel doesn't support these, you will need to obtain the Source RPMS for
+the proper version of XenServer to recompile the dom0 kernel.
+
+XenServer Requirements (32-bit dom0)
+====================================
+
+- arptables 32-bit rpm
+- ebtables 32-bit rpm
+- python-simplejson
+
+XenServer Environment Specific Notes
+====================================
+
+- XenServer 5.5 U1 based on the 2.6.18 kernel didn't include physdev module
+ support. Support for this had to be recompiled into the kernel.
+- XenServer 5.6 based on the 2.6.27 kernel didn't include physdev, ebtables, or
+ arptables.
+- XenServer 5.6 FP1 didn't include physdev, ebtables, or arptables but they do
+ have a Cloud Supplemental pack available to partners which swaps out the
+ kernels for kernels that support the networking rules.
+
+How it works - tl;dr
+====================
+
+iptables, ebtables, and arptables drop rules are applied to all forward chains
+on the host. These are applied at boot time with an init script. They ensure
+all forwarded packets are dropped by default. Allow rules are then applied to
+the instances to ensure they have permission to talk on the internet.
+
+How it works - Long
+===================
+
+Any time an underprivileged domain or domU is started or stopped, it gets a
+unique domain id (dom_id). This dom_id is utilized in a number of places, one
+of which is it's assigned to the virtual interface (vif). The vifs are attached
+to the bridge that is attached to the physical network. For instance, if you
+had a public bridge attached to eth0 and your domain id was 5, your vif would be
+vif5.0.
+
+The networking rules are applied to the VIF directly so they apply at the lowest
+level of the networking stack. Because the VIF changes along with the domain id
+on any start, stop, or reboot of the instance, the rules need to be removed and
+re-added any time that occurs.
+
+Because the dom_id can change often, the vif_rules script is hooked into the
+/etc/xensource/scripts/vif script that gets called anytime an instance is
+started, or stopped, which includes pauses and resumes.
+
+Examples of the rules ran for the host on boot:
+
+iptables -P FORWARD DROP
+iptables -A FORWARD -m physdev --physdev-in eth0 -j ACCEPT
+ebtables -P FORWARD DROP
+ebtables -A FORWARD -o eth0 -j ACCEPT
+arptables -P FORWARD DROP
+arptables -A FORWARD --opcode Request --in-interface eth0 -j ACCEPT
+arptables -A FORWARD --opcode Reply --in-interface eth0 -j ACCEPT
+
+Examples of the rules that are ran per instance state change:
+
+iptables -A FORWARD -m physdev --physdev-in vif1.0 -s 10.1.135.22/32 -j ACCEPT
+arptables -A FORWARD --opcode Request --in-interface "vif1.0" \
+ --source-ip 10.1.135.22 -j ACCEPT
+arptables -A FORWARD --opcode Reply --in-interface "vif1.0" \
+ --source-ip 10.1.135.22 --source-mac 9e:6e:cc:19:7f:fe -j ACCEPT
+ebtables -A FORWARD -p 0806 -o vif1.0 --arp-ip-dst 10.1.135.22 -j ACCEPT
+ebtables -A FORWARD -p 0800 -o vif1.0 --ip-dst 10.1.135.22 -j ACCEPT
+ebtables -I FORWARD 1 -s ! 9e:6e:cc:19:7f:fe -i vif1.0 -j DROP
+
+Typically when you see a vif, it'll look like vif<domain id>.<network bridge>.
+vif2.1 for example would be domain 2 on the second interface.
+
+The vif_rules.py script needs to pull information about the IPs and MAC
+addresses assigned to the instance. The current implementation assumes that
+information is put into the VM Record into the xenstore-data key in a JSON
+string. The vif_rules.py script reads out of the JSON string to determine the
+IPs, and MAC addresses to protect.
+
+An example format is given below:
+
+# xe vm-param-get uuid=<uuid> param-name=xenstore-data
+xenstore-data (MRW):
+vm-data/networking/4040fa7292e4:
+{"label": "public",
+ "ips": [{"netmask":"255.255.255.0",
+ "enabled":"1",
+ "ip":"173.200.100.10"}],
+ "mac":"40:40:fa:72:92:e4",
+ "gateway":"173.200.100.1",
+ "vm_id":"123456",
+ "dns":["72.3.128.240","72.3.128.241"]};
+
+vm-data/networking/40402321c9b8:
+{"label":"private",
+ "ips":[{"netmask":"255.255.224.0",
+ "enabled":"1",
+ "ip":"10.177.10.10"}],
+ "routes":[{"route":"10.176.0.0",
+ "netmask":"255.248.0.0",
+ "gateway":"10.177.10.1"},
+ {"route":"10.191.192.0",
+ "netmask":"255.255.192.0",
+ "gateway":"10.177.10.1"}],
+ "mac":"40:40:23:21:c9:b8"}
+
+The key is used for two purposes. One, the vif_rules.py script will read from
+it to apply the rules needed after parsing the JSON. The second is that because
+it's put into the xenstore-data field, the xenstore will be populated with this
+data on boot. This allows a guest agent the ability to read out data about the
+instance and apply configurations as needed.
+
+Installation
+============
+
+- Copy host-rules into /etc/init.d/ and make sure to chmod +x host-rules.
+- Run 'chkconfig host-rules on' to add the init script to start up.
+- Copy vif_rules.py into /etc/xensource/scripts
+- Patch /etc/xensource/scripts/vif using the supplied patch file. It may vary
+ for different versions of XenServer but it should be pretty self explanatory.
+ It calls the vif_rules.py script on domain creation and tear down.
+- Run '/etc/init.d/host-rules start' to start up the host based rules.
+- The instance rules will then fire on creation of the VM as long as the correct
+ JSON is in place.
+- You can check to see if the rules are in place with: iptables --list,
+ arptables --list, or ebtables --list
+
diff --git a/plugins/xenserver/networking/etc/init.d/host-rules b/plugins/xenserver/networking/etc/init.d/host-rules
new file mode 100755
index 000000000..798da9552
--- /dev/null
+++ b/plugins/xenserver/networking/etc/init.d/host-rules
@@ -0,0 +1,106 @@
+#!/bin/bash
+#
+# host-rules Start/Stop the networking host rules
+#
+# chkconfig: 2345 85 15
+# description: Networking Host Rules for Multi Tenancy Protections
+
+# Copyright 2010 OpenStack LLC.
+# All Rights Reserved.
+#
+# 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.
+
+IPTABLES=/sbin/iptables
+EBTABLES=/sbin/ebtables
+ARPTABLES=/sbin/arptables
+
+iptables-up()
+{
+ $IPTABLES -P FORWARD DROP
+ $IPTABLES -A FORWARD -m physdev --physdev-in eth0 -j ACCEPT
+ $IPTABLES -A FORWARD -m physdev --physdev-in eth1 -j ACCEPT
+}
+
+ebtables-up()
+{
+ $EBTABLES -P FORWARD DROP
+ $EBTABLES -A FORWARD -o eth0 -j ACCEPT
+ $EBTABLES -A FORWARD -o eth1 -j ACCEPT
+}
+
+arptables-up()
+{
+ $ARPTABLES -P FORWARD DROP
+ $ARPTABLES -A FORWARD --opcode Request --in-interface eth0 -j ACCEPT
+ $ARPTABLES -A FORWARD --opcode Reply --in-interface eth0 -j ACCEPT
+ $ARPTABLES -A FORWARD --opcode Request --in-interface eth1 -j ACCEPT
+ $ARPTABLES -A FORWARD --opcode Reply --in-interface eth1 -j ACCEPT
+}
+
+iptables-down()
+{
+ $IPTABLES -P FORWARD ACCEPT
+ $IPTABLES -D FORWARD -m physdev --physdev-in eth0 -j ACCEPT
+ $IPTABLES -D FORWARD -m physdev --physdev-in eth1 -j ACCEPT
+}
+
+ebtables-down()
+{
+ $EBTABLES -P FORWARD ACCEPT
+ $EBTABLES -D FORWARD -o eth0 -j ACCEPT
+ $EBTABLES -D FORWARD -o eth1 -j ACCEPT
+}
+
+arptables-down()
+{
+ $ARPTABLES -P FORWARD ACCEPT
+ $ARPTABLES -D FORWARD --opcode Request --in-interface eth0 -j ACCEPT
+ $ARPTABLES -D FORWARD --opcode Reply --in-interface eth0 -j ACCEPT
+ $ARPTABLES -D FORWARD --opcode Request --in-interface eth1 -j ACCEPT
+ $ARPTABLES -D FORWARD --opcode Reply --in-interface eth1 -j ACCEPT
+}
+
+start()
+{
+ iptables-up
+ ebtables-up
+ arptables-up
+}
+
+stop()
+{
+ iptables-down
+ ebtables-down
+ arptables-down
+}
+
+case "$1" in
+ start)
+ start
+ RETVAL=$?
+ ;;
+ stop)
+ stop
+ RETVAL=$?
+ ;;
+ restart)
+ stop
+ start
+ RETVAL=$?
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart}"
+ exit 1
+ ;;
+esac
+exit $RETVAL
diff --git a/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch b/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch
new file mode 100644
index 000000000..feaf1312d
--- /dev/null
+++ b/plugins/xenserver/networking/etc/xensource/scripts/vif_5.6-fp1.patch
@@ -0,0 +1,22 @@
+--- vif 2010-12-20 16:39:46.000000000 +0000
++++ vif_modified 2010-11-19 23:24:37.000000000 +0000
+@@ -213,6 +213,7 @@
+
+ # xs-xen.pq.hq:91e986b8e49f netback-wait-for-hotplug
+ xenstore-write "/local/domain/0/backend/vif/${DOMID}/${DEVID}/hotplug-status" "connected"
++ python /etc/xensource/scripts/vif_rules.py ${DOMID} online 2>&1 > /dev/null
+ fi
+ ;;
+
+@@ -224,9 +225,11 @@
+
+ remove)
+ if [ "${TYPE}" = "vif" ] ;then
++ python /etc/xensource/scripts/vif_rules.py ${DOMID} offline 2>&1 > /dev/null
+ xenstore-rm "${HOTPLUG}/hotplug"
+ fi
+ logger -t scripts-vif "${dev} has been removed"
+ remove_from_bridge
+ ;;
+ esac
++
diff --git a/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py
new file mode 100755
index 000000000..d60816ce7
--- /dev/null
+++ b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2010 OpenStack LLC.
+# All Rights Reserved.
+#
+# 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.
+
+"""
+This script is used to configure iptables, ebtables, and arptables rules on
+XenServer hosts.
+"""
+
+import os
+import subprocess
+import sys
+
+# This is written to Python 2.4, since that is what is available on XenServer
+import simplejson as json
+
+
+def main(dom_id, command, only_this_vif=None):
+ xsls = execute("/usr/bin/xenstore-ls /local/domain/%s/vm-data/networking" \
+ % dom_id, True)
+ macs = [line.split("=")[0].strip() for line in xsls.splitlines()]
+
+ for mac in macs:
+ xsr = "/usr/bin/xenstore-read /local/domain/%s/vm-data/networking/%s"
+ xsread = execute(xsr % (dom_id, mac), True)
+ data = json.loads(xsread)
+ for ip in data['ips']:
+ if data["label"] == "public":
+ vif = "vif%s.0" % dom_id
+ else:
+ vif = "vif%s.1" % dom_id
+
+ if (only_this_vif is None) or (vif == only_this_vif):
+ params = dict(IP=ip['ip'], VIF=vif, MAC=data['mac'])
+ apply_ebtables_rules(command, params)
+ apply_arptables_rules(command, params)
+ apply_iptables_rules(command, params)
+
+
+def execute(command, return_stdout=False):
+ devnull = open(os.devnull, 'w')
+ proc = subprocess.Popen(command, shell=True, close_fds=True,
+ stdout=subprocess.PIPE, stderr=devnull)
+ devnull.close()
+ if return_stdout:
+ return proc.stdout.read()
+ else:
+ return None
+
+# A note about adding rules:
+# Whenever we add any rule to iptables, arptables or ebtables we first
+# delete the same rule to ensure the rule only exists once.
+
+
+def apply_iptables_rules(command, params):
+ iptables = lambda rule: execute("/sbin/iptables %s" % rule)
+
+ iptables("-D FORWARD -m physdev --physdev-in %(VIF)s -s %(IP)s \
+ -j ACCEPT" % params)
+ if command == 'online':
+ iptables("-A FORWARD -m physdev --physdev-in %(VIF)s -s %(IP)s \
+ -j ACCEPT" % params)
+
+
+def apply_arptables_rules(command, params):
+ arptables = lambda rule: execute("/sbin/arptables %s" % rule)
+
+ arptables("-D FORWARD --opcode Request --in-interface %(VIF)s \
+ --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params)
+ arptables("-D FORWARD --opcode Reply --in-interface %(VIF)s \
+ --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params)
+ if command == 'online':
+ arptables("-A FORWARD --opcode Request --in-interface %(VIF)s \
+ --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params)
+ arptables("-A FORWARD --opcode Reply --in-interface %(VIF)s \
+ --source-ip %(IP)s --source-mac %(MAC)s -j ACCEPT" % params)
+
+
+def apply_ebtables_rules(command, params):
+ ebtables = lambda rule: execute("/sbin/ebtables %s" % rule)
+
+ ebtables("-D FORWARD -p 0806 -o %(VIF)s --arp-ip-dst %(IP)s -j ACCEPT" %
+ params)
+ ebtables("-D FORWARD -p 0800 -o %(VIF)s --ip-dst %(IP)s -j ACCEPT" %
+ params)
+ if command == 'online':
+ ebtables("-A FORWARD -p 0806 -o %(VIF)s --arp-ip-dst %(IP)s \
+ -j ACCEPT" % params)
+ ebtables("-A FORWARD -p 0800 -o %(VIF)s --ip-dst %(IP)s \
+ -j ACCEPT" % params)
+
+ ebtables("-D FORWARD -s ! %(MAC)s -i %(VIF)s -j DROP" % params)
+ if command == 'online':
+ ebtables("-I FORWARD 1 -s ! %(MAC)s -i %(VIF)s -j DROP" % params)
+
+
+if __name__ == "__main__":
+ if len(sys.argv) < 3:
+ print "usage: %s dom_id online|offline [vif]" % \
+ os.path.basename(sys.argv[0])
+ sys.exit(1)
+ else:
+ dom_id, command = sys.argv[1:3]
+ vif = len(sys.argv) == 4 and sys.argv[3] or None
+ main(dom_id, command, vif)
diff --git a/plugins/xenapi/README b/plugins/xenserver/xenapi/README
index fbd471035..fbd471035 100644
--- a/plugins/xenapi/README
+++ b/plugins/xenserver/xenapi/README
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance
new file mode 100644
index 000000000..5e648b970
--- /dev/null
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2010 Citrix Systems, Inc.
+# Copyright 2010 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# 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.
+
+#
+# XenAPI plugin for putting images into glance
+#
+
+import base64
+import errno
+import hmac
+import httplib
+import os
+import os.path
+import pickle
+import sha
+import subprocess
+import time
+import urlparse
+
+import XenAPIPlugin
+
+#FIXME(sirp): should this use pluginlib from 5.6?
+from pluginlib_nova import *
+configure_logging('glance')
+
+CHUNK_SIZE = 8192
+FILE_SR_PATH = '/var/run/sr-mount'
+
+def put_vdis(session, args):
+ params = pickle.loads(exists(args, 'params'))
+ vdi_uuids = params["vdi_uuids"]
+ image_name = params["image_name"]
+ glance_host = params["glance_host"]
+ glance_port = params["glance_port"]
+
+ sr_path = get_sr_path(session)
+ #FIXME(sirp): writing to a temp file until Glance supports chunked-PUTs
+ tmp_file = "%s.tar.gz" % os.path.join('/tmp', image_name)
+ tar_cmd = ['tar', '-zcf', tmp_file, '--directory=%s' % sr_path]
+ paths = [ "%s.vhd" % vdi_uuid for vdi_uuid in vdi_uuids ]
+ tar_cmd.extend(paths)
+ logging.debug("Bundling image with cmd: %s", tar_cmd)
+ subprocess.call(tar_cmd)
+ logging.debug("Writing to test file %s", tmp_file)
+ put_bundle_in_glance(tmp_file, image_name, glance_host, glance_port)
+ return "" # FIXME(sirp): return anything useful here?
+
+
+def put_bundle_in_glance(tmp_file, image_name, glance_host, glance_port):
+ size = os.path.getsize(tmp_file)
+ basename = os.path.basename(tmp_file)
+
+ bundle = open(tmp_file, 'r')
+ try:
+ headers = {
+ 'x-image-meta-store': 'file',
+ 'x-image-meta-is_public': 'True',
+ 'x-image-meta-type': 'raw',
+ 'x-image-meta-name': image_name,
+ 'x-image-meta-size': size,
+ 'content-length': size,
+ 'content-type': 'application/octet-stream',
+ }
+ conn = httplib.HTTPConnection(glance_host, glance_port)
+ #NOTE(sirp): httplib under python2.4 won't accept a file-like object
+ # to request
+ conn.putrequest('POST', '/images')
+
+ for header, value in headers.iteritems():
+ conn.putheader(header, value)
+ conn.endheaders()
+
+ chunk = bundle.read(CHUNK_SIZE)
+ while chunk:
+ conn.send(chunk)
+ chunk = bundle.read(CHUNK_SIZE)
+
+
+ res = conn.getresponse()
+ #FIXME(sirp): should this be 201 Created?
+ if res.status != httplib.OK:
+ raise Exception("Unexpected response from Glance %i" % res.status)
+ finally:
+ bundle.close()
+
+def get_sr_path(session):
+ sr_ref = find_sr(session)
+
+ if sr_ref is None:
+ raise Exception('Cannot find SR to read VDI from')
+
+ sr_rec = session.xenapi.SR.get_record(sr_ref)
+ sr_uuid = sr_rec["uuid"]
+ sr_path = os.path.join(FILE_SR_PATH, sr_uuid)
+ return sr_path
+
+
+#TODO(sirp): both objectstore and glance need this, should this be refactored
+#into common lib
+def find_sr(session):
+ host = get_this_host(session)
+ srs = session.xenapi.SR.get_all()
+ for sr in srs:
+ sr_rec = session.xenapi.SR.get_record(sr)
+ if not ('i18n-key' in sr_rec['other_config'] and
+ sr_rec['other_config']['i18n-key'] == 'local-storage'):
+ continue
+ for pbd in sr_rec['PBDs']:
+ pbd_rec = session.xenapi.PBD.get_record(pbd)
+ if pbd_rec['host'] == host:
+ return sr
+ return None
+
+
+if __name__ == '__main__':
+ XenAPIPlugin.dispatch({'put_vdis': put_vdis})
diff --git a/plugins/xenapi/etc/xapi.d/plugins/objectstore b/plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore
index 271e7337f..8ee2f748d 100644
--- a/plugins/xenapi/etc/xapi.d/plugins/objectstore
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/objectstore
@@ -43,24 +43,43 @@ SECTOR_SIZE = 512
MBR_SIZE_SECTORS = 63
MBR_SIZE_BYTES = MBR_SIZE_SECTORS * SECTOR_SIZE
-
+def is_vdi_pv(session,args):
+ logging.debug("Checking wheter VDI has PV kernel")
+ vdi = exists(args, 'vdi-ref')
+ pv=with_vdi_in_dom0(session, vdi, False,
+ lambda dev: _is_vdi_pv('/dev/%s' % dev))
+ if pv:
+ return 'true'
+ else:
+ return 'false'
+
+def _is_vdi_pv(dest):
+ logging.debug("Running pygrub against %s",dest)
+ output=os.popen('pygrub -qn %s' % dest)
+ pv=False
+ for line in output.readlines():
+ #try to find kernel string
+ m=re.search('(?<=kernel:)/.*(?:>)',line)
+ if m:
+ if m.group(0).find('xen')!=-1:
+ pv=True
+ logging.debug("PV:%d",pv)
+ return pv
+
def get_vdi(session, args):
src_url = exists(args, 'src_url')
username = exists(args, 'username')
password = exists(args, 'password')
+ raw_image=validate_bool(args, 'raw', 'false')
add_partition = validate_bool(args, 'add_partition', 'false')
-
(proto, netloc, url_path, _, _, _) = urlparse.urlparse(src_url)
-
sr = find_sr(session)
if sr is None:
raise Exception('Cannot find SR to write VDI to')
-
virtual_size = \
get_content_length(proto, netloc, url_path, username, password)
if virtual_size < 0:
raise Exception('Cannot get VDI size')
-
vdi_size = virtual_size
if add_partition:
# Make room for MBR.
@@ -69,18 +88,19 @@ def get_vdi(session, args):
vdi = create_vdi(session, sr, src_url, vdi_size, False)
with_vdi_in_dom0(session, vdi, False,
lambda dev: get_vdi_(proto, netloc, url_path,
- username, password, add_partition,
+ username, password, add_partition,raw_image,
virtual_size, '/dev/%s' % dev))
return session.xenapi.VDI.get_uuid(vdi)
-def get_vdi_(proto, netloc, url_path, username, password, add_partition,
+def get_vdi_(proto, netloc, url_path, username, password, add_partition,raw_image,
virtual_size, dest):
- if add_partition:
+ #Salvatore: vdi should not be partitioned for raw images
+ if (add_partition and not raw_image):
write_partition(virtual_size, dest)
- offset = add_partition and MBR_SIZE_BYTES or 0
+ offset = (add_partition and not raw_image and MBR_SIZE_BYTES) or 0
get(proto, netloc, url_path, username, password, dest, offset)
@@ -228,4 +248,5 @@ def download_all(response, length, dest_file, offset):
if __name__ == '__main__':
XenAPIPlugin.dispatch({'get_vdi': get_vdi,
- 'get_kernel': get_kernel})
+ 'get_kernel': get_kernel,
+ 'is_vdi_pv': is_vdi_pv})
diff --git a/plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py b/plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
index 2d323a016..2d323a016 100755
--- a/plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/pluginlib_nova.py