Adding utils to install XAPI plugins to dom0

When deploy OpenStack on XenServer, we need install some XAPI
plugins to dom0. This commit is to add utils for this purpose.
If the os-xenapi version is different from the os-xenapi which
contains the utils. Users can specify the version to the utils.
So that the utils will download the right version of os-xenapi
and copy plugins from there. Otherwise the utils will by default
copy plugins from current installed packages.

Change-Id: I269a444b952f63fd73b3825b23dc95d6e825ce8f
This commit is contained in:
Jianghua Wang 2017-12-26 10:13:12 +00:00
parent 4cafb55ce0
commit aa48f8223a
2 changed files with 183 additions and 0 deletions

View File

@ -0,0 +1,100 @@
# 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.
import mock
import os
import shutil
import tempfile
from os_xenapi.tests import base
from os_xenapi.utils import common_function
from os_xenapi.utils import xapi_plugin
class XenapiPluginTestCase(base.TestCase):
@mock.patch.object(tempfile, 'mkdtemp',
return_value='/tmp/tmp1VyeJn')
@mock.patch.object(common_function, 'execute')
def test_get_os_xenapi_dir_with_version(self, mock_exec, mock_tmp):
VERSION = '0.3.1'
is_tmp, dir = xapi_plugin.get_os_xenapi_dir(VERSION)
self.assertEqual(2, mock_exec.call_count)
self.assertEqual(dir, '/tmp/tmp1VyeJn')
self.assertEqual(is_tmp, True)
@mock.patch.object(tempfile, 'mkdtemp')
@mock.patch.object(common_function, 'execute')
def test_get_os_xenapi_dir_no_version(self, mock_exec, mock_tmp):
fake_loc = '/fake/install/loc'
mock_exec.return_value = 'Location: %s\n' % fake_loc
is_tmp, dir = xapi_plugin.get_os_xenapi_dir()
self.assertEqual(dir, fake_loc)
self.assertEqual(is_tmp, False)
mock_exec.assert_called_with('pip', 'show',
xapi_plugin.OS_XENAPI_PKG)
mock_tmp.assert_not_called()
@mock.patch.object(xapi_plugin, 'get_os_xenapi_dir')
@mock.patch.object(os, 'listdir')
@mock.patch.object(shutil, 'rmtree')
def test_install_plugins_to_dom0_no_version(self, mock_rm, mock_dir,
mock_get):
FAKE_PKG_PATH = '/fake/pkg/path'
ssh_client = mock.Mock()
mock_get.return_value = (False, FAKE_PKG_PATH)
mock_dir.return_value = ['file1', 'file2']
xapi_plugin.install_plugins_to_dom0(ssh_client)
dom0_path = xapi_plugin.DOM0_PLUGIN_PATH
local_path = '%s/%s' % (FAKE_PKG_PATH,
xapi_plugin.PKG_PLUGIN_PATH)
scp_expect = [mock.call('%s/file1' % local_path,
'%s/file1' % dom0_path),
mock.call('%s/file2' % local_path,
'%s/file2' % dom0_path)]
ssh_expect = [mock.call('chmod +x %s/file1' % dom0_path),
mock.call('chmod +x %s/file2' % dom0_path)]
self.assertEqual(scp_expect, ssh_client.scp.call_args_list)
self.assertEqual(ssh_expect, ssh_client.ssh.call_args_list)
# Shouldn't invoke mock_rm to remove the package dir.
mock_rm.assert_not_called()
@mock.patch.object(xapi_plugin, 'get_os_xenapi_dir')
@mock.patch.object(os, 'listdir')
@mock.patch.object(shutil, 'rmtree')
def test_install_plugins_to_dom0_with_version(self, mock_rm, mock_dir,
mock_get):
VERSION = '0.3.1'
FAKE_PKG_PATH = '/tmp/tmp1VyeJn'
ssh_client = mock.Mock()
mock_get.return_value = (True, FAKE_PKG_PATH)
mock_dir.return_value = ['file1', 'file2']
xapi_plugin.install_plugins_to_dom0(ssh_client, VERSION)
dom0_path = xapi_plugin.DOM0_PLUGIN_PATH
local_path = '%s/%s' % (FAKE_PKG_PATH,
xapi_plugin.PKG_PLUGIN_PATH)
scp_expect = [mock.call('%s/file1' % local_path,
'%s/file1' % dom0_path),
mock.call('%s/file2' % local_path,
'%s/file2' % dom0_path)]
ssh_expect = [mock.call('chmod +x %s/file1' % dom0_path),
mock.call('chmod +x %s/file2' % dom0_path)]
self.assertEqual(scp_expect, ssh_client.scp.call_args_list)
self.assertEqual(ssh_expect, ssh_client.ssh.call_args_list)
# Should invoke mock_rm to remove the package dir.
mock_rm.assert_called_with(FAKE_PKG_PATH)

View File

@ -0,0 +1,83 @@
#!/usr/bin/env python
# Copyright 2017 Citrix Systems
#
# 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.
"""XAPI plugin utils
It contains the utilities relative to XAPI plugins."""
import os
import shutil
import sys
import tempfile
from os_xenapi.utils import common_function as fun
from os_xenapi.utils.sshclient import SSHClient
DOM0_PLUGIN_PATH = '/etc/xapi.d/plugins'
PKG_PLUGIN_PATH = 'os_xenapi/dom0/etc/xapi.d/plugins'
OS_XENAPI_PKG = 'os-xenapi'
def get_os_xenapi_dir(version=None):
# Get os-xenapi's directory.
# return (is_tmp_dir, os_xenapi_dir), where is_tmp_dir indicates
# if the os_xenapi_dir is a temporary directory.
is_tmp_dir = False
os_xenapi_dir = None
if version:
# If version is specified, then download the specified package.
# And unpack the package.
temp_dir = tempfile.mkdtemp()
fun.execute('pip', 'download', '--no-deps', '-d', temp_dir,
'%s==%s' % (OS_XENAPI_PKG, version))
fun.execute('unzip', '-d', temp_dir, '%s/*.whl' % temp_dir)
is_tmp_dir = True
os_xenapi_dir = temp_dir
else:
# Check current installed os-xenapi package's location
LOCATION_KEY = 'Location: '
pkg_info = fun.execute('pip', 'show', OS_XENAPI_PKG).split('\n')
for line in pkg_info:
if line.startswith(LOCATION_KEY):
os_xenapi_dir = line[len(LOCATION_KEY):]
break
return (is_tmp_dir, os_xenapi_dir)
def install_plugins_to_dom0(ssh_client, version=None):
is_tmp_dir, dir = get_os_xenapi_dir(version)
plugin_location = '%s/%s' % (dir, PKG_PLUGIN_PATH)
try:
for file in os.listdir(plugin_location):
src_file = '%s/%s' % (plugin_location, file)
dst_file = '%s/%s' % (DOM0_PLUGIN_PATH, file)
ssh_client.scp(src_file, dst_file)
ssh_client.ssh('chmod +x %s' % dst_file)
finally:
if is_tmp_dir:
# delete the temp directory.
shutil.rmtree(dir)
if __name__ == '__main__':
# argv[1]: dom0's IP address
# argv[2]: user name
# argv[3]: user passwd
# argv[4]: os-xenapi version (default None)
ssh_client = SSHClient(sys.argv[1], sys.argv[2], sys.argv[3])
version = None
if len(sys.argv) > 4:
version = sys.argv[4]
install_plugins_to_dom0(ssh_client, version)