Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor IBEX_upgrade Script #123

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
245 changes: 187 additions & 58 deletions installation_and_upgrade/IBEX_upgrade.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
"""
Script to install IBEX to various machines
"""

# pylint: disable=import-error
import argparse
import os
import re
import sys
from typing import Tuple
import semantic_version

from ibex_install_utils.Arguments_config import ARGUMENT_PARSER, ARGUMENTS
from ibex_install_utils.install_tasks import UpgradeInstrument, UPGRADE_TYPES
from ibex_install_utils.exceptions import UserStop, ErrorInTask
from ibex_install_utils.user_prompt import UserPrompt
from ibex_install_utils.file_utils import get_latest_directory_path


def _get_latest_release_path(release_dir):
def _get_latest_release_path(release_dir) -> str:
"""
Get the latest release path
Args:
release_dir: directory to search for releases
Returns:
latest_release_path
"""
regex = re.compile(r'^\d+\.\d+\.\d+$')

releases = [name for name in os.listdir(release_dir) if os.path.isdir(os.path.join(release_dir, name))]
release_path = os.listdir(release_dir)
releases = [name for name in release_path if os.path.isdir(os.path.join(release_dir, name))]
releases = list(filter(regex.match, releases))
releases = sorted(list(filter(regex.match, releases)), key=semantic_version.Version)

Expand All @@ -27,83 +37,202 @@ def _get_latest_release_path(release_dir):
current_release = releases[-1]
return os.path.join(release_dir, f"{current_release}")


if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Upgrade the instrument.',
formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument("--release_dir", dest="release_dir", default=None,
help="directory from which the client and server should be installed")
parser.add_argument("--release_suffix", dest="release_suffix", default="",
help="Suffix for specifying non-standard releases "
"(such as those including hot fixes)")
parser.add_argument("--server_build_prefix", default="EPICS", help="Prefix for build directory name")
parser.add_argument("--server_dir", default=None, help="Directory from which IBEX server should be installed")
parser.add_argument("--client_dir", default=None, help="Directory from which IBEX client should be installed")
parser.add_argument("--client_e4_dir", default=None, help="Directory from which IBEX E4 client should be installed")
parser.add_argument("--genie_python3_dir", default=None,
help="Directory from which genie_python_3 should be installed")
parser.add_argument("--confirm_step", default=False, action="store_true",
help="Confirm each major action before performing it")
parser.add_argument("--quiet", default=False, action="store_true",
help="Do not ask any questions just to the default.")
parser.add_argument("--kits_icp_dir", default=None, help="Directory of kits/ICP")

def add_deployment_type_to_parser(argument_parser: argparse.ArgumentParser) -> argparse.ArgumentParser: # pylint: disable=line-too-long
"""
Add deployment type to the argument parser
Args:
argument_parser: argument parser to add arguments to
Returns:
argument_parser
"""
deployment_types = [f"{choice}: {deployment_types}"
for choice, (_, deployment_types) in UPGRADE_TYPES.items()]
parser.add_argument('deployment_type', choices=UPGRADE_TYPES.keys(),
help="What upgrade should be performed. ( {})"
.format(", \n".join(deployment_types)))
argument_parser.add_argument('deployment_type',
choices=UPGRADE_TYPES.keys(),
help="What upgrade should be performed. ( {})".format(", \n".join(deployment_types)))

return argument_parser

def add_arguments_to_parser_from_arguments(argument_parser: argparse.ArgumentParser) -> argparse.ArgumentParser: # pylint: disable=line-too-long
"""
Add arguments to the argument parser
Args:
argument_parser: argument parser to add arguments to
Returns:
argument_parser
"""
for argument in ARGUMENTS:
flag_argument = argument.pop("name_or_flags")
argument_parser.add_argument(flag_argument, **argument)

return argument_parser

def check_directory_selected(args_server_dir: str, args_client_dir: str, args_genie_python3_dir: str, args_client_e4_dir: str) -> bool: # pylint: disable=line-too-long
"""
Check if all directories are selected
Args:
args_server_dir: server directory
args_client_dir: client directory
args_genie_python3_dir: genie python 3 directory
args_client_e4_dir: client e4 directory
Returns:
True if all directories are selected
"""
argument_checklist = [args_server_dir,
args_client_dir,
args_genie_python3_dir,
args_client_e4_dir]

all_directories_populated = all(argument_checklist)
return all_directories_populated

def set_args_to_latest(current_release_directory: str) -> Tuple[str, str, str, str, str, str]:
"""
Set the arguments to the latest release
Args:
current_release_directory: current release directory
Returns:
server_directory, client_directory, client_e4_directory, genie_python3_directory
"""
server_directory = os.path.join(current_release_directory, "EPICS")
client_directory = os.path.join(current_release_directory, "Client")
client_e4_directory = client_directory
genie_python3_directory = os.path.join(current_release_directory, "genie_python_3")

return server_directory, client_directory, client_e4_directory, genie_python3_directory

def set_release_directory_to_latest(argument_dirs: argparse.Namespace) -> Tuple[str, str, str, str, str]: # pylint: disable=line-too-long
"""
Set the release directory to the latest release
Args:
argument_dirs: directory to search for releases
Returns:
(release_directory, client_version, server_directory, client_directory,
client_e4_directory, genie_python3_directory)
"""
release_directory = os.path.join(argument_dirs.release_dir,
_get_latest_release_path(args.release_dir))
client_version = _get_latest_release_path(argument_dirs.release_dir).split("\\")[-1]

if argument_dirs.release_suffix != "":
release_directory += f"-{argument_dirs.release_suffix}"

arg_dirs = set_args_to_latest(release_directory)
server_directory, client_directory, client_e4_directory, genie_python3_directory = arg_dirs

return (client_version,
server_directory,
client_directory,
client_e4_directory,
genie_python3_directory)

def set_epics_build_dir_using_kits_icp(namespace_arguments: argparse.Namespace) -> str:
"""
Set the epics build directory to the kits ICP directory
Args:
namespace_arguments: arguments
Returns:
epics_build_directory
"""
if namespace_arguments.deployment_type == 'install_latest_incr':
epics_build_directory = os.path.join(namespace_arguments.kits_icp_dir,
"EPICS", namespace_arguments.server_build_prefix+"_win7_x64")
else:
epics_build_directory = os.path.join(namespace_arguments.kits_icp_dir,
"EPICS",
namespace_arguments.server_build_prefix+"_CLEAN_win7_x64")
return epics_build_directory

def set_directory_using_kits_icp(namespace_arguments: argparse.Namespace, directory_name: str, directory_type: str, icp: bool, build_directory=None) -> str: # pylint: disable=line-too-long
"""
Set the directory to the kits ICP directory to latest release
Args:
namespace_arguments: arguments
directory_name: directory name
directory_type: directory type
icp: kits ICP directory
build_directory: build directory
Returns:
directory
"""
if icp:
build_directory = os.path.join(namespace_arguments.kits_icp_dir, f"{directory_name}")
lastest_directory_path = get_latest_directory_path(build_directory, f"{directory_type}")
return build_directory, lastest_directory_path

if build_directory:
lastest_directory_path = get_latest_directory_path(epics_build_dir,
f"{directory_name}",
f"{directory_type}")
return lastest_directory_path
return None

if __name__ == "__main__":
# A parser to parse the command line arguments
parser = argparse.ArgumentParser(**ARGUMENT_PARSER)
parser = add_arguments_to_parser_from_arguments(parser) # Add Arguments
parser = add_deployment_type_to_parser(parser) # Add deployment type from UPGRADE_TYPES

args = parser.parse_args()
client_e4_dir = args.client_e4_dir
current_client_version = None
current_client_version = None # pylint: disable=invalid-name
# If the release directory is not specified, use the latest release
if args.release_dir is not None:
current_release_dir = os.path.join(args.release_dir, _get_latest_release_path(args.release_dir))
current_client_version = _get_latest_release_path(args.release_dir).split("\\")[-1]
if args.release_suffix != "":
current_release_dir += f"-{args.release_suffix}"
server_dir = os.path.join(current_release_dir, "EPICS")
client_dir = os.path.join(current_release_dir, "Client")
client_e4_dir = client_dir
genie_python3_dir = os.path.join(current_release_dir, "genie_python_3")
rel_dir = set_release_directory_to_latest(args) # Set release directories to latest release
current_client_version, server_dir, client_dir, client_e4_dir, genie_python3_dir = rel_dir

elif args.kits_icp_dir is not None:
if args.deployment_type == 'install_latest_incr':
epics_build_dir = os.path.join(args.kits_icp_dir, "EPICS", args.server_build_prefix+"_win7_x64")
else:
epics_build_dir = os.path.join(args.kits_icp_dir, "EPICS", args.server_build_prefix+"_CLEAN_win7_x64")

# If kits_icp_dir is specified, epics_build_dir is set
epics_build_dir = set_epics_build_dir_using_kits_icp(args)
# Try initialising the server and client directories to latest release using kits_icp_dir
try:
server_dir = get_latest_directory_path(epics_build_dir, "BUILD-", "EPICS")

client_build_dir = os.path.join(args.kits_icp_dir, "Client")
client_dir = get_latest_directory_path(client_build_dir, "BUILD")
server_dir = set_directory_using_kits_icp(args,
"BUILD-",
"EPICS",
True,
epics_build_dir)

client_build_dir, client_dir = set_directory_using_kits_icp(args,
"Client",
"BUILD",
False)

client_e4_build_dir, client_e4_dir = set_directory_using_kits_icp(args,
"Client_E4",
"BUILD",
False)

genie_python3_build_dir, genie_python3_dir = set_directory_using_kits_icp(args,
"genie_python_3",
"BUILD-",
False)

except IOError as error:
print(error)
sys.exit(3)

client_e4_build_dir = os.path.join(args.kits_icp_dir, "Client_E4")
client_e4_dir = get_latest_directory_path(client_e4_build_dir, "BUILD")
# Instantiate All server, client and genie_python3 directory paths if present

genie_python3_build_dir = os.path.join(args.kits_icp_dir, "genie_python_3")
genie_python3_dir = get_latest_directory_path(genie_python3_build_dir, "BUILD-")
except IOError as e:
print(e)
sys.exit(3)
elif check_directory_selected(args.server_dir, args.client_dir, args.genie_python3_dir,\
args.client_e4_dir) is True:

elif args.server_dir is not None and args.client_dir is not None and args.genie_python3_dir is not None and \
args.client_e4_dir is not None:
server_dir = args.server_dir
client_dir = args.client_dir
client_e4_dir = args.client_e4_dir
genie_python3_dir = args.genie_python3_dir

else:
print("You must specify either the release directory or kits_icp_dir or "
"ALL of the server, client, client e4 and genie python 3 directories.")
sys.exit(2)

try:
prompt = UserPrompt(args.quiet, args.confirm_step)
upgrade_instrument = UpgradeInstrument(prompt, server_dir, client_dir, client_e4_dir, genie_python3_dir,
current_client_version)
upgrade_instrument = UpgradeInstrument(prompt,
server_dir,
client_dir,
client_e4_dir,
genie_python3_dir,
current_client_version)
upgrade_function = UPGRADE_TYPES[args.deployment_type][0]
upgrade_function(upgrade_instrument)

Expand Down
67 changes: 67 additions & 0 deletions installation_and_upgrade/ibex_install_utils/Arguments_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
Arguments for IBEX_upgrade.py
"""

import argparse

ARGUMENT_PARSER = {
"description": "Upgrade the instrument.",
"formatter_class": argparse.RawTextHelpFormatter
}

ARGUMENTS = [
{
"name_or_flags": "--release_dir",
"dest": "release_dir",
"default": None,
"help": "directory from which the client and server should be installed"
},
{
"name_or_flags": "--release_suffix",
"dest": "release_suffix",
"default": "",
"help": "Suffix for specifying non-standard releases (such as those including hot fixes)"
},
{
"name_or_flags": "--server_build_prefix",
"default": "EPICS",
"help": "Prefix for build directory name"
},
{
"name_or_flags": "--server_dir",
"default": None,
"help": "Directory from which IBEX server should be installed"
},
{
"name_or_flags": "--client_dir",
"default": None,
"help": "Directory from which IBEX client should be installed"
},
{
"name_or_flags": "--client_e4_dir",
"default": None,
"help": "Directory from which IBEX E4 client should be installed"
},
{
"name_or_flags": "--genie_python3_dir",
"default": None,
"help": "Directory from which genie_python_3 should be installed"
},
{
"name_or_flags": "--confirm_step",
"default": False,
"action": "store_true",
"help": "Confirm each major action before performing it"
},
{
"name_or_flags": "--quiet",
"default": False,
"action": "store_true",
"help": "Do not ask any questions just to the default."
},
{
"name_or_flags": "--kits_icp_dir",
"default": None,
"help": "Directory of kits/ICP"
}
]