XenAPI: add support for conntrack with XenServer

With XenServer as hypervisor, the commands neutron-ovs-agent in
compute node run are actually executed in Dom0. But current Dom0
plugin doesn't allow conntrack command, this patch is to add such
support.
Also, the exitcode the commands returned in Dom0 will pass through
Dom0 to neutron to make sure the plugin is only aimed executing
commands, it doesn't deal with business scenario.

Closes-Bug: #1603400

Change-Id: I304788240bcd590ec211bca052fe64594a4e6eca
(cherry picked from commit 0d8483391d)
This commit is contained in:
Huan Xie 2016-07-12 22:48:01 -07:00 committed by Ihar Hrachyshka
parent 8a89cce6fc
commit 02c621e2b9
2 changed files with 27 additions and 14 deletions

View File

@ -29,7 +29,6 @@ from oslo_serialization import jsonutils as json
import os
import select
import sys
import traceback
import XenAPI
@ -45,7 +44,7 @@ def parse_args():
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.stderr.write("%s: No command specified" % exec_name)
sys.exit(RC_NOCOMMAND)
config_file = sys.argv.pop(0)
@ -59,7 +58,7 @@ def _xenapi_section_name(config):
if len(sections) == 1:
return sections[0]
print("Multiple [xenapi] sections or no [xenapi] section found!")
sys.stderr.write("Multiple [xenapi] sections or no [xenapi] section found!")
sys.exit(RC_BADCONFIG)
@ -74,13 +73,14 @@ def load_configuration(exec_name, config_file):
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.stderr.write("%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.stderr.write(msg)
sys.exit(RC_BADCONFIG)
return dict(
filters_path=filters_path,
@ -105,7 +105,7 @@ def filter_command(exec_name, filters_path, user_args, exec_dirs):
filter_match = wrapper.match_filter(
filters, user_args, exec_dirs=exec_dirs)
if not filter_match:
print("Unauthorized command: %s" % ' '.join(user_args))
sys.stderr.write("Unauthorized command: %s" % ' '.join(user_args))
sys.exit(RC_UNAUTHORIZED)
@ -118,11 +118,17 @@ def run_command(url, username, password, user_args, cmd_input):
result = session.xenapi.host.call_plugin(
host, 'netwrap', 'run_command',
{'cmd': json.dumps(user_args), 'cmd_input': json.dumps(cmd_input)})
return json.loads(result)
result_dict = json.loads(result)
returncode = result_dict.get('returncode')
captured_stdout = result_dict.get('out')
captured_stderr = result_dict.get('err')
sys.stdout.write(captured_stdout)
sys.stderr.write(captured_stderr)
sys.exit(returncode)
finally:
session.xenapi.session.logout()
except Exception as e:
traceback.print_exc()
sys.stderr.write("Failed to execute command in Dom0, %s" % e)
sys.exit(RC_XENAPI_ERROR)
@ -142,4 +148,4 @@ def main():
if __name__ == '__main__':
print(main())
main()

View File

@ -44,6 +44,7 @@ ALLOWED_CMDS = [
'ovs-ofctl',
'ovs-vsctl',
'ovsdb-client',
'conntrack',
]
@ -61,10 +62,7 @@ def _run_command(cmd, cmd_input):
proc = subprocess.Popen(cmd, shell=False, stdin=pipe, stdout=pipe,
stderr=pipe, close_fds=True)
(out, err) = proc.communicate(cmd_input)
if proc.returncode != 0:
raise PluginError(err)
return out
return proc.returncode, out, err
def run_command(session, args):
@ -72,7 +70,16 @@ def run_command(session, args):
if cmd and cmd[0] not in ALLOWED_CMDS:
msg = _("Dom0 execution of '%s' is not permitted") % cmd[0]
raise PluginError(msg)
result = _run_command(cmd, json.loads(args.get('cmd_input', 'null')))
returncode, out, err = _run_command(
cmd, json.loads(args.get('cmd_input', 'null')))
if not err:
err = ""
if not out:
out = ""
# This runs in Dom0, will return to neutron-ovs-agent in compute node
result = {'returncode': returncode,
'out': out,
'err': err}
return json.dumps(result)