diff --git a/bin/neutron-rootwrap-xen-dom0 b/bin/neutron-rootwrap-xen-dom0 new file mode 100755 index 000000000..5748f19be --- /dev/null +++ b/bin/neutron-rootwrap-xen-dom0 @@ -0,0 +1,131 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +"""Neutron root wrapper for dom0. + +Executes networking commands in dom0. The XenAPI plugin is +responsible determining whether a command is safe to execute. + +""" + +import ConfigParser +import json +import os +import sys +import traceback + +import XenAPI + + +RC_UNAUTHORIZED = 99 +RC_NOCOMMAND = 98 +RC_BADCONFIG = 97 +RC_XENAPI_ERROR = 96 + + +def parse_args(): + # Split arguments, require at least a command + exec_name = sys.argv.pop(0) + # argv[0] required; path to conf file + if len(sys.argv) < 2: + print "%s: No command specified" % exec_name + sys.exit(RC_NOCOMMAND) + + config_file = sys.argv.pop(0) + user_args = sys.argv[:] + + return exec_name, config_file, user_args + + +def _xenapi_section_name(config): + sections = [sect for sect in config.sections() if sect.lower() == "xenapi"] + if len(sections) == 1: + return sections[0] + + print "Multiple [xenapi] sections or no [xenapi] section found!" + sys.exit(RC_BADCONFIG) + + +def load_configuration(exec_name, config_file): + config = ConfigParser.RawConfigParser() + config.read(config_file) + try: + exec_dirs = config.get("DEFAULT", "exec_dirs").split(",") + filters_path = config.get("DEFAULT", "filters_path").split(",") + section = _xenapi_section_name(config) + url = config.get(section, "xenapi_connection_url") + username = config.get(section, "xenapi_connection_username") + password = config.get(section, "xenapi_connection_password") + except ConfigParser.Error: + print "%s: Incorrect configuration file: %s" % (exec_name, config_file) + sys.exit(RC_BADCONFIG) + if not url or not password: + msg = ("%s: Must specify xenapi_connection_url, " + "xenapi_connection_username (optionally), and " + "xenapi_connection_password in %s") % (exec_name, config_file) + print msg + sys.exit(RC_BADCONFIG) + return dict( + filters_path=filters_path, + url=url, + username=username, + password=password, + exec_dirs=exec_dirs, + ) + + +def filter_command(exec_name, filters_path, user_args, exec_dirs): + # Add ../ to sys.path to allow running from branch + possible_topdir = os.path.normpath(os.path.join(os.path.abspath(exec_name), + os.pardir, os.pardir)) + if os.path.exists(os.path.join(possible_topdir, "neutron", "__init__.py")): + sys.path.insert(0, possible_topdir) + + from neutron.openstack.common.rootwrap import wrapper + + # Execute command if it matches any of the loaded filters + filters = wrapper.load_filters(filters_path) + filter_match = wrapper.match_filter( + filters, user_args, exec_dirs=exec_dirs) + if not filter_match: + print "Unauthorized command: %s" % ' '.join(user_args) + sys.exit(RC_UNAUTHORIZED) + + +def run_command(url, username, password, user_args): + try: + session = XenAPI.Session(url) + session.login_with_password(username, password) + host = session.xenapi.session.get_this_host(session.handle) + result = session.xenapi.host.call_plugin( + host, 'netwrap', 'run_command', {'cmd': json.dumps(user_args)}) + return json.loads(result) + except Exception as e: + traceback.print_exc() + sys.exit(RC_XENAPI_ERROR) + + +def main(): + exec_name, config_file, user_args = parse_args() + config = load_configuration(exec_name, config_file) + filter_command(exec_name, config['filters_path'], user_args, config['exec_dirs']) + return run_command(config['url'], config['username'], config['password'], + user_args) + + +if __name__ == '__main__': + print main() diff --git a/bin/quantum-rootwrap-xen-dom0 b/bin/quantum-rootwrap-xen-dom0 index 7b5ba21e5..5748f19be 100755 --- a/bin/quantum-rootwrap-xen-dom0 +++ b/bin/quantum-rootwrap-xen-dom0 @@ -15,7 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. -"""Quantum root wrapper for dom0. +"""Neutron root wrapper for dom0. Executes networking commands in dom0. The XenAPI plugin is responsible determining whether a command is safe to execute. @@ -92,7 +92,7 @@ def filter_command(exec_name, filters_path, user_args, exec_dirs): # Add ../ to sys.path to allow running from branch possible_topdir = os.path.normpath(os.path.join(os.path.abspath(exec_name), os.pardir, os.pardir)) - if os.path.exists(os.path.join(possible_topdir, "quantum", "__init__.py")): + if os.path.exists(os.path.join(possible_topdir, "neutron", "__init__.py")): sys.path.insert(0, possible_topdir) from neutron.openstack.common.rootwrap import wrapper diff --git a/setup.cfg b/setup.cfg index 70d01d630..b73675d90 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,6 +59,8 @@ data_files = scripts = bin/quantum-rootwrap bin/neutron-rootwrap + bin/quantum-rootwrap-xen-dom0 + bin/neutron-rootwrap-xen-dom0 [global] setup-hooks =