Remove unsupported commands

Delete commands that are not required for upgrade from version 7 to version 8
and above.

Change-Id: Ibd30603b60eb8ca3b68eefb70be39937c5f9d584
This commit is contained in:
Oleg Gelbukh 2016-03-24 15:52:44 +03:00
parent a4ed2778ab
commit fb061f4ef6
12 changed files with 0 additions and 914 deletions

View File

@ -1,70 +0,0 @@
# 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 logging
import os
from cliff import command as cmd
from fuelclient import objects
from octane import magic_consts
from octane.util import env as env_util
from octane.util import node as node_util
from octane.util import ssh
LOG = logging.getLogger(__name__)
def cleanup_environment(env_id):
env = objects.Environment(env_id)
nodes = env.get_all_nodes()
for node in nodes:
node_util.remove_compute_upgrade_levels(node)
controller = env_util.get_one_controller(env)
sftp = ssh.sftp(controller)
admin_pass = env_util.get_admin_password(env, controller)
script_filename = 'clean_env.py'
with ssh.tempdir(controller) as tempdir:
script_src_filename = os.path.join(
magic_consts.CWD, "helpers", script_filename)
script_dst_filename = os.path.join(tempdir, script_filename)
sftp.put(script_src_filename, script_dst_filename)
command = [
'sh', '-c', '. /root/openrc; export OS_PASSWORD={0}; python {1}'
.format(admin_pass, script_dst_filename),
]
with ssh.popen(command, node=controller, stdin=ssh.PIPE) as proc:
roles = ["controller", "compute"]
for node in env_util.get_nodes(env, roles):
data = "{0}\n{1}\n".format(node.data['fqdn'].split('.')[0],
node.data['fqdn'])
proc.stdin.write(data)
class CleanupCommand(cmd.Command):
"""Cleanup upgraded environment"""
def get_parser(self, prog_name):
parser = super(CleanupCommand, self).get_parser(prog_name)
parser.add_argument(
'env', type=int, metavar='ENV_ID',
help="ID of environment to cleanup")
return parser
def take_action(self, parsed_args):
cleanup_environment(parsed_args.env)

View File

@ -1,74 +0,0 @@
# 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 os.path
from cliff import command as cmd
from octane import magic_consts
from octane.util import archivate
from octane.util import docker
from octane.util import subprocess
def apply_patches(revert=False):
for container, prefix, patch in magic_consts.PATCHES:
docker.apply_patches(container, prefix,
os.path.join(magic_consts.CWD, patch),
revert=revert)
def revert_initramfs():
backup = magic_consts.BOOTSTRAP_INITRAMFS + '.bkup'
os.rename(backup, magic_consts.BOOTSTRAP_INITRAMFS)
def patch_initramfs():
with archivate.update_cpio(magic_consts.BOOTSTRAP_INITRAMFS) as chroot:
patch_fuel_agent(chroot)
docker.run_in_container("cobbler", ["cobbler", "sync"])
def patch_fuel_agent(chroot):
patch_dir = os.path.join(magic_consts.CWD, "patches", "fuel_agent")
with open(os.path.join(patch_dir, "patch")) as patch:
subprocess.call(["patch", "-N", "-p0"], stdin=patch, cwd=chroot)
def prepare():
if not os.path.isdir(magic_consts.FUEL_CACHE):
os.makedirs(magic_consts.FUEL_CACHE)
subprocess.call(["yum", "-y", "install"] + magic_consts.PACKAGES)
# From patch_all_containers
apply_patches()
docker.run_in_container("nailgun", ["pkill", "-f", "wsgi"])
patch_initramfs()
def revert_prepare():
apply_patches(revert=True)
docker.run_in_container("nailgun", ["pkill", "-f", "wsgi"])
revert_initramfs()
class PrepareCommand(cmd.Command):
"""Prepare the Fuel master node to upgrade an environment"""
def take_action(self, parsed_args):
prepare()
class RevertCommand(cmd.Command):
"""Revert all patches applied by 'prepare' command"""
def take_action(self, parsed_args):
revert_prepare()

View File

@ -1,74 +0,0 @@
# 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 tempfile
from cliff import command as cmd
from fuelclient.objects import environment as environment_obj
from octane.helpers.sync_glance_images import sync_glance_images
from octane.util import db
from octane.util import env as env_util
from octane.util import ssh
def prepare(orig_id, seed_id):
orig_env = environment_obj.Environment(orig_id)
seed_env = environment_obj.Environment(seed_id)
controller = env_util.get_one_controller(seed_env)
with tempfile.NamedTemporaryFile() as temp:
db.mysqldump_from_env(orig_env, ['keystone'], temp.name)
db.mysqldump_restore_to_env(seed_env, temp.name)
ssh.call(['keystone-manage', 'db_sync'],
node=controller, parse_levels=True)
for controller in env_util.get_controllers(seed_env):
ssh.call(['service', 'memcached', 'restart'], node=controller)
class SyncImagesCommand(cmd.Command):
"""Sync glance images between ORIG and SEED environments"""
def get_parser(self, prog_name):
parser = super(SyncImagesCommand, self).get_parser(prog_name)
parser.add_argument(
'orig_id', type=int, metavar='ORIG_ID',
help="ID of original environment")
parser.add_argument(
'seed_id', type=int, metavar='SEED_ID',
help="ID of seed environment")
parser.add_argument(
'swift_ep', type=str,
help="Endpoint's name where swift-proxy service is listening on")
return parser
def take_action(self, parsed_args):
sync_glance_images(parsed_args.orig_id, parsed_args.seed_id,
parsed_args.swift_ep)
class SyncImagesPrepareCommand(cmd.Command):
"""Sync glance images between ORIG and SEED environments"""
def get_parser(self, prog_name):
parser = super(SyncImagesPrepareCommand, self).get_parser(prog_name)
parser.add_argument(
'orig_id', type=int, metavar='ORIG_ID',
help="ID of original environment")
parser.add_argument(
'seed_id', type=int, metavar='SEED_ID',
help="ID of seed environment")
return parser
def take_action(self, parsed_args):
prepare(parsed_args.orig_id, parsed_args.seed_id)

View File

@ -1,92 +0,0 @@
# 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 logging
from cliff import command as cmd
from fuelclient import objects
from requests import HTTPError
from octane.util import env as env_util
LOG = logging.getLogger(__name__)
KEEP_NETWORK_NAMES = ['fuelweb_admin', 'management', 'public']
def update_env_networks(env_id, networks):
fields_to_update = ['meta', 'ip_ranges']
env = objects.Environment(env_id)
release_id = env.get_fresh_data()['release_id']
network_data = env.get_network_data()
node_group_id = None
for ng in network_data['networks']:
if ng['name'] in KEEP_NETWORK_NAMES:
continue
if node_group_id is None:
# for now we'll have only one node group
# so just take it id from any network
node_group_id = ng['group_id']
objects.NetworkGroup(ng['id']).delete()
data_to_update = {}
for ng in networks:
if ng['name'] in KEEP_NETWORK_NAMES:
continue
try:
objects.NetworkGroup.create(
ng['name'],
release_id,
ng['vlan_start'],
ng['cidr'],
ng['gateway'],
node_group_id,
ng['meta']
)
except HTTPError:
LOG.error("Cannot sync network '{0}'".format(ng['name']))
continue
data = {}
for key in fields_to_update:
data[key] = ng[key]
data_to_update[ng['name']] = data
# now we need to update new networks with
# correct ip_ranges and meta
network_data = env.get_network_data()
network_data['networks'] = [ng for ng in network_data['networks']
if ng['name'] not in KEEP_NETWORK_NAMES]
for ng in network_data['networks']:
if ng['name'] in data_to_update:
for k in fields_to_update:
ng[k] = data_to_update[ng['name']][k]
env.set_network_data(network_data)
class SyncNetworksCommand(cmd.Command):
"""Synchronize network groups in original and seed environments"""
def get_parser(self, prog_name):
parser = super(SyncNetworksCommand, self).get_parser(prog_name)
parser.add_argument(
'original_env', type=int, metavar='ORIGINAL_ENV_ID',
help="ID of original environment")
parser.add_argument(
'seed_env', type=int, metavar='SEED_ENV_ID',
help="ID of seed environment")
return parser
def take_action(self, parsed_args):
orig_env = objects.Environment(parsed_args.original_env)
networks = env_util.get_env_networks(orig_env)
update_env_networks(parsed_args.seed_env, networks)

View File

@ -1,204 +0,0 @@
# 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 argparse
import logging
import re
import requests
from cliff import command as cmd
from fuelclient.objects import environment
from fuelclient.objects import node as node_obj
from octane.util import env as env_util
from octane.util import ssh
LOG = logging.getLogger(__name__)
def get_template_hosts_by_name(client, plugin_name):
return client.template.get(filter={'name': plugin_name},
selectHosts=['name'])[0]['hosts']
def get_host_snmp_ip(client, host_id):
# second type is SNMP type
return client.hostinterface.get(hosids=host_id,
output=['ip'],
filter={'type': 2})[0]['ip']
def get_zabbix_url(astute):
return 'http://{0}/zabbix'.format(astute['public_vip'])
def get_zabbix_credentials(astute):
return astute['zabbix']['username'], astute['zabbix']['password']
def zabbix_monitoring_settings(astute, attrs):
attrs['username']['value'] = astute['zabbix']['username']
attrs['password']['value'] = astute['zabbix']['password']
attrs['db_password']['value'] = astute['zabbix']['db_password']
attrs['metadata']['enabled'] = astute['zabbix']['enabled']
def emc_vnx_settings(astute, attrs):
attrs['emc_sp_a_ip']['value'] = astute['storage']['emc_sp_a_ip']
attrs['emc_sp_b_ip']['value'] = astute['storage']['emc_sp_b_ip']
attrs['emc_password']['value'] = astute['storage']['emc_password']
attrs['emc_username']['value'] = astute['storage']['emc_username']
attrs['emc_pool_name']['value'] = astute['storage']['emc_pool_name']
attrs['metadata']['enabled'] = astute['storage']['volumes_emc']
def zabbix_snmptrapd_settings(astute, attrs):
node = node_obj.Node(astute['uid'])
with ssh.sftp(node).open('/etc/snmp/snmptrapd.conf') as f:
data = f.read()
template = re.compile(r"authCommunity\s[a-z-,]+\s([a-z-]+)")
match = template.search(data)
attrs['community']['value'] = match.group(1)
attrs['metadata']['enabled'] = True
def get_zabbix_client(astute):
url = get_zabbix_url(astute)
user, password = get_zabbix_credentials(astute)
session = requests.Session()
node_cidr = astute['network_scheme']['endpoints']['br-fw-admin']['IP'][0]
node_ip = node_cidr.split('/')[0]
session.proxies = {
'http': 'http://{0}:8888'.format(node_ip)
}
import pyzabbix
client = pyzabbix.ZabbixAPI(server=url, session=session)
client.login(user=user, password=password)
return client
def zabbix_monitoring_emc_settings(astute, attrs):
client = get_zabbix_client(astute)
hosts = get_template_hosts_by_name(client, 'Template EMC VNX')
for host in hosts:
host['ip'] = get_host_snmp_ip(client, host['hostid'])
settings = ','.join('{0}:{1}'.format(host['name'], host['ip'])
for host in hosts)
attrs['hosts']['value'] = settings
attrs['metadata']['enabled'] = True
def zabbix_monitoring_extreme_networks_settings(astute, attrs):
client = get_zabbix_client(astute)
hosts = get_template_hosts_by_name(client, 'Template Extreme Networks')
for host in hosts:
host['ip'] = get_host_snmp_ip(client, host['hostid'])
settings = ','.join('{0}:{1}'.format(host['name'], host['ip'])
for host in hosts)
attrs['hosts']['value'] = settings
attrs['metadata']['enabled'] = True
class UnknownPlugin(Exception):
message = "Unknown plugin '{0}'"
def __init__(self, plugin):
super(UnknownPlugin, self).__init__(self.message.format(plugin))
class PluginNotConfigured(Exception):
message = "No settings for plugin '{0}' in environment #{1}. " \
"Was it installed before environment #{1} has been created?"
def __init__(self, plugin, env_id):
super(PluginNotConfigured, self).__init__(self.message.format(
plugin, env_id))
def transfer_plugins_settings(orig_env_id, seed_env_id, plugins):
orig_env = environment.Environment(orig_env_id)
seed_env = environment.Environment(seed_env_id)
astute = env_util.get_astute_yaml(orig_env)
attrs = seed_env.get_settings_data()
editable_attrs = attrs['editable']
plugin_fns = {}
plugin_attrs = {}
for plugin in plugins:
try:
plugin_fns[plugin] = PLUGINS[plugin]
except KeyError:
raise UnknownPlugin(plugin)
try:
plugin_attrs[plugin] = editable_attrs[plugin]
except KeyError:
raise PluginNotConfigured(plugin, seed_env_id)
for plugin in plugins:
LOG.info("Fetching settings for plugin '%s'", plugin)
plugin_fn = plugin_fns[plugin]
plugin_attr = plugin_attrs[plugin]
plugin_fn(astute, plugin_attr)
seed_env.set_settings_data(attrs)
PLUGINS = {
'zabbix_monitoring': zabbix_monitoring_settings,
'emc_vnx': emc_vnx_settings,
'zabbix_snmptrapd': zabbix_snmptrapd_settings,
'zabbix_monitoring_emc': zabbix_monitoring_emc_settings,
'zabbix_monitoring_extreme_networks':
zabbix_monitoring_extreme_networks_settings,
}
def plugin_names(s):
plugins = s.split(',')
for plugin in plugins:
if plugin not in PLUGINS:
raise argparse.ArgumentTypeError("Unknown plugin '{0}'"
.format(plugin))
return plugins
class UpdatePluginSettingsCommand(cmd.Command):
"""Transfer settings for specified plugin from ORIG_ENV to SEED_ENV"""
def get_parser(self, prog_name):
parser = super(UpdatePluginSettingsCommand, self).get_parser(prog_name)
parser.add_argument(
'orig_env',
type=int,
metavar='ORIG_ID',
help="ID of original environment")
parser.add_argument(
'seed_env',
type=int,
metavar='SEED_ID',
help="ID of seed environment")
parser.add_argument(
'--plugins',
type=plugin_names,
required=True,
help="Comma separated values: {0}".format(', '.join(PLUGINS)))
return parser
def take_action(self, parsed_args):
transfer_plugins_settings(parsed_args.orig_env,
parsed_args.seed_env,
parsed_args.plugins)

View File

@ -1,223 +0,0 @@
# 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 logging
from fuelclient.objects import environment as environment_obj
from octane.util import env as env_util
from octane.util import ssh
LOG = logging.getLogger(__name__)
def get_endpoint_ip(ep_name, yaml_data):
endpoint = yaml_data['network_scheme']['endpoints'].get(ep_name)
if not endpoint:
return None
net_data = endpoint["IP"][0]
if net_data:
return net_data.split('/')[0]
def get_glance_password(yaml_data):
return yaml_data['glance']['user_password']
def parse_swift_out(output, field):
for line in output.splitlines()[1:-1]:
parts = line.split(': ')
if parts[0].strip() == field:
return parts[1]
raise Exception(
"Field {0} not found in output:\n{1}".format(field, output))
def get_swift_objects(node, tenant, user, password, token, container):
cmd = ". /root/openrc; swift --os-project-name {0} --os-username {1}"\
" --os-password {2} --os-auth-token {3} list {4}".format(tenant,
user,
password,
token,
container)
objects_list = ssh.call_output(["sh", "-c", cmd], node=node)
return objects_list.split('\n')[:-1]
def get_object_property(node, tenant, user, password, token, container,
object_id, prop):
cmd = ". /root/openrc; swift --os-project-name {0} --os-username {1}"\
" --os-password {2} --os-auth-token {3} stat {4} {5}"\
.format(tenant,
user,
password,
token,
container,
object_id)
object_data = ssh.call_output(["sh", "-c", cmd], node=node)
return parse_swift_out(object_data, prop)
def get_auth_token(node, tenant, user, password):
cmd = ". /root/openrc; keystone --os-tenant-name {0}"\
" --os-username {1} --os-password {2} token-get".format(tenant,
user,
password)
token_info = ssh.call_output(["sh", "-c", cmd], node=node)
return env_util.parse_tenant_get(token_info, 'id')
def download_image(node, tenant, user, password, token, container, object_id):
cmd = ". /root/openrc; swift --os-project-name {0} --os-username {1}"\
" --os-password {2} --os-auth-token {3} download {4} {5}"\
.format(tenant,
user,
password,
token,
container,
object_id)
ssh.call(["sh", "-c", cmd], node=node)
LOG.info("Swift %s image has been downloaded", object_id)
def delete_image(node, tenant, user, password, token, container, object_id):
cmd = ". /root/openrc; swift --os-project-name {0}"\
" --os-username {1} --os-password {2} --os-auth-token {3}"\
" delete {4} {5}".format(tenant, user, password, token,
container, object_id)
ssh.call(["sh", "-c", cmd], node=node)
LOG.info("Swift %s image has been deleted", object_id)
def transfer_image(node, tenant, user, password, token, container, object_id,
storage_ip, tenant_id):
storage_url = "http://{0}:8080/v1/AUTH_{1}".format(storage_ip, tenant_id)
cmd = ['swift', '--os-project-name', tenant, '--os-username', user,
'--os-password', password, '--os-auth-token', token,
'--os-storage-url', storage_url, 'upload', container,
object_id]
ssh.call(cmd, node=node)
LOG.info("Swift %s image has been transferred", object_id)
def create_container(node, tenant, user, password, token, container):
cmd = ". /root/openrc; swift --os-project-name {0}"\
" --os-username {1} --os-password {2} --os-auth-token {3}"\
" post {4}".format(tenant, user, password, token, container)
ssh.call(["sh", "-c", cmd], node=node)
def sync_glance_images(source_env_id, seed_env_id, seed_swift_ep):
"""Sync glance images from original ENV to seed ENV
Args:
source_env_id (int): ID of original ENV.
seed_env_id (int): ID of seed ENV.
seed_swift_ep (str): endpoint's name where swift-proxy service is
listening on.
Examples:
sync_glance_images(2, 3, 'br-mgmt')
"""
# set glance username
glance_user = "glance"
# set swift container value
container = "glance"
# choose tenant
tenant = "services"
# get clusters by id
source_env = environment_obj.Environment(source_env_id)
seed_env = environment_obj.Environment(seed_env_id)
# gather cics admin IPs
source_node = next(env_util.get_controllers(source_env))
seed_node = next(env_util.get_controllers(seed_env))
# get cics yaml files
source_yaml = env_util.get_astute_yaml(source_env, source_node)
seed_yaml = env_util.get_astute_yaml(seed_env, seed_node)
# get glance passwords
source_glance_pass = get_glance_password(source_yaml)
seed_glance_pass = get_glance_password(seed_yaml)
# get seed node swift ip
seed_swift_ip = get_endpoint_ip(seed_swift_ep, seed_yaml)
# get service tenant id & lists of objects for source env
source_token = get_auth_token(source_node, tenant, glance_user,
source_glance_pass)
source_swift_list = set(get_swift_objects(source_node,
tenant,
glance_user,
source_glance_pass,
source_token,
container))
# get service tenant id & lists of objects for seed env
seed_token = get_auth_token(seed_node, tenant, glance_user,
seed_glance_pass)
# to be sure that glance container is present for seed env
create_container(seed_node, tenant, glance_user, seed_glance_pass,
seed_token, container)
seed_swift_list = set(get_swift_objects(seed_node,
tenant,
glance_user,
seed_glance_pass,
seed_token,
container))
# get service tenant for seed env
seed_tenant = env_util.get_service_tenant_id(seed_env)
# check consistency of matched images
source_token = get_auth_token(source_node, tenant, glance_user,
source_glance_pass)
seed_token = get_auth_token(seed_node, tenant, glance_user,
seed_glance_pass)
for image in source_swift_list & seed_swift_list:
source_obj_etag = get_object_property(source_node,
tenant,
glance_user,
source_glance_pass,
source_token,
container,
image,
'ETag')
seed_obj_etag = get_object_property(seed_node, tenant,
glance_user, seed_glance_pass,
seed_token, container, image,
'ETag')
if source_obj_etag != seed_obj_etag:
# image should be resynced
delete_image(seed_node, tenant, glance_user, seed_glance_pass,
seed_token, container, image)
LOG.info("Swift %s image should be resynced", image)
seed_swift_list.remove(image)
# migrate new images
for image in source_swift_list - seed_swift_list:
# download image on source's node local drive
source_token = get_auth_token(source_node, tenant, glance_user,
source_glance_pass)
download_image(source_node, tenant, glance_user, source_glance_pass,
source_token, container, image)
# transfer image
source_token = get_auth_token(source_node, tenant,
glance_user, source_glance_pass)
seed_token = get_auth_token(seed_node, tenant, glance_user,
seed_glance_pass)
transfer_image(source_node, tenant, glance_user, seed_glance_pass,
seed_token, container, image, seed_swift_ip,
seed_tenant)
# remove transferred image
ssh.sftp(source_node).remove(image)
# delete outdated images
for image in seed_swift_list - source_swift_list:
token = get_auth_token(seed_node, tenant, glance_user,
seed_glance_pass)
delete_image(seed_node, tenant, glance_user, seed_glance_pass,
token, container, image)

View File

@ -12,7 +12,6 @@
import os.path
PACKAGES = ["postgresql.x86_64", "pssh", "patch", "python-pip"]
PATCHES = []
# TODO: use pkg_resources for patches
CWD = os.path.dirname(__file__) # FIXME

View File

@ -1,27 +0,0 @@
# 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.
def test_prepare_parser(mocker, octane_app):
m = mocker.patch('octane.commands.prepare.prepare')
octane_app.run(["prepare"])
assert not octane_app.stdout.getvalue()
assert not octane_app.stderr.getvalue()
m.assert_called_once_with()
def test_revert_parser(mocker, octane_app):
mock_apply = mocker.patch('octane.commands.prepare.revert_prepare')
octane_app.run(["revert-prepare"])
assert not octane_app.stdout.getvalue()
assert not octane_app.stderr.getvalue()
mock_apply.assert_called_once_with()

View File

@ -1,62 +0,0 @@
# 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 pytest
from octane.helpers import sync_glance_images
def test_parser(mocker, octane_app):
m = mocker.patch('octane.commands.sync_images.sync_glance_images')
octane_app.run(['sync-images', '1', '2', 'br-mgmt'])
assert not octane_app.stdout.getvalue()
assert not octane_app.stderr.getvalue()
m.assert_called_once_with(1, 2, 'br-mgmt')
def test_prepare_parser(mocker, octane_app):
m = mocker.patch('octane.commands.sync_images.prepare')
octane_app.run(['sync-images-prepare', '1', '2'])
assert not octane_app.stdout.getvalue()
assert not octane_app.stderr.getvalue()
m.assert_called_once_with(1, 2)
@pytest.mark.parametrize("yaml,expected", [
({'network_scheme': {'endpoints': {'MY_EP': {'IP': ['1.2.3.4/24']}}}},
'1.2.3.4'),
({'network_scheme': {'endpoints': {'MY_EP1': {'IP': ['1.2.3.4/24']}}}},
None),
])
def test_get_endpoint_ip(yaml, expected):
result = sync_glance_images.get_endpoint_ip('MY_EP', yaml)
assert result == expected
def test_get_swift_object(mock_subprocess, mock_ssh_call_output, node):
mock_ssh_call_output.return_value = 'id1\nid2\n'
res = sync_glance_images.get_swift_objects(
node, 'tenant', 'user', 'password', 'token', 'container')
assert not mock_subprocess.called
assert mock_ssh_call_output.call_args_list == [
mock.call(["sh", "-c", mock.ANY], node=node)]
assert res == ['id1', 'id2']
def test_download_image(mock_subprocess, mock_ssh_call, node):
mock_ssh_call.return_value = 'id1\nid2\n'
sync_glance_images.download_image(
node, 'tenant', 'user', 'password', 'token', 'container', 'id')
assert not mock_subprocess.called
assert mock_ssh_call.call_args_list == [
mock.call(["sh", "-c", mock.ANY], node=node)]

View File

@ -1,27 +0,0 @@
# 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.
def test_parser(mocker, octane_app):
networks = [{'key': 'value'}]
env_cls = mocker.patch('fuelclient.objects.Environment')
m1 = mocker.patch('octane.util.env.get_env_networks')
m1.return_value = networks
m2 = mocker.patch('octane.commands.sync_networks.update_env_networks')
octane_app.run(["sync-networks", "1", "2"])
assert not octane_app.stdout.getvalue()
assert not octane_app.stderr.getvalue()
m1.assert_called_once_with(env_cls.return_value)
m2.assert_called_once_with(2, networks)

View File

@ -1,49 +0,0 @@
# 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 pytest
from octane.commands import update_plugin_settings
def test_parser(mocker, octane_app):
m = mocker.patch('octane.commands.update_plugin_settings'
'.transfer_plugins_settings')
plugins_str = ','.join(update_plugin_settings.PLUGINS)
octane_app.run(["update-plugin-settings", "--plugins", plugins_str,
"1", "2"])
assert not octane_app.stdout.getvalue()
assert not octane_app.stderr.getvalue()
m.assert_called_once_with(1, 2, update_plugin_settings.PLUGINS.keys())
def test_transfer_plugin_settings(mocker):
plugin = mock.Mock()
mocker.patch.object(update_plugin_settings, 'PLUGINS', {'plugin': plugin})
env_cls = mocker.patch('fuelclient.objects.environment.Environment')
get_astute_yaml = mocker.patch('octane.util.env.get_astute_yaml')
attrs = {'editable': {'plugin': {}}}
env_cls.return_value.get_settings_data.return_value = attrs
update_plugin_settings.transfer_plugins_settings(1, 2, ['plugin'])
plugin.assert_called_once_with(get_astute_yaml.return_value, {})
def test_transfer_plugin_settings_fail(mocker):
plugin = mock.Mock()
mocker.patch.object(update_plugin_settings, 'PLUGINS', {'plugin': plugin})
env_cls = mocker.patch('fuelclient.objects.environment.Environment')
mocker.patch('octane.util.env.get_astute_yaml')
attrs = {'editable': {'plugin1': {}}}
env_cls.return_value.get_settings_data.return_value = attrs
with pytest.raises(update_plugin_settings.PluginNotConfigured):
update_plugin_settings.transfer_plugins_settings(1, 2, ['plugin'])

View File

@ -23,16 +23,10 @@ classifier =
packages =
octane
[extras]
zabbix =
pyzabbix==0.7.3
[entry_points]
console_scripts =
octane = octane.app:main
octane =
prepare = octane.commands.prepare:PrepareCommand
revert-prepare = octane.commands.prepare:RevertCommand
upgrade-env = octane.commands.upgrade_env:UpgradeEnvCommand
upgrade-node = octane.commands.upgrade_node:UpgradeNodeCommand
upgrade-db = octane.commands.upgrade_db:UpgradeDBCommand
@ -40,11 +34,6 @@ octane =
install-node = octane.commands.install_node:InstallNodeCommand
upgrade-control = octane.commands.upgrade_controlplane:UpgradeControlPlaneCommand
rollback-control = octane.commands.rollback_controlplane:RollbackControlPlaneCommand
sync-networks = octane.commands.sync_networks:SyncNetworksCommand
cleanup = octane.commands.cleanup:CleanupCommand
sync-images = octane.commands.sync_images:SyncImagesCommand
sync-images-prepare = octane.commands.sync_images:SyncImagesPrepareCommand
update-plugin-settings = octane.commands.update_plugin_settings:UpdatePluginSettingsCommand [zabbix]
fuel-backup = octane.commands.backup:BackupCommand
fuel-restore = octane.commands.restore:RestoreCommand
fuel-repo-backup = octane.commands.backup:BackupRepoCommand