263 lines
9.6 KiB
Python
263 lines
9.6 KiB
Python
"""
|
|
Copyright (c) 2018-2022 Intel Corporation
|
|
|
|
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.
|
|
"""
|
|
|
|
__version__ = "0.6"
|
|
|
|
import os
|
|
import argparse
|
|
import tempfile
|
|
from pathlib import Path
|
|
from typing import List
|
|
|
|
from deployman.logger import init_logger
|
|
from deployman.config import ConfigReader, ComponentFactory, Component
|
|
from deployman.ui import UserInterface
|
|
|
|
logger = init_logger("WARNING")
|
|
|
|
|
|
# main class
|
|
class DeploymentManager:
|
|
def __init__(self, args, selected_targets: List[Component], components: List[Component]):
|
|
self.args = args
|
|
self.selected_targets = selected_targets
|
|
self.components = components
|
|
self.dependencies = []
|
|
self.mandatory_components = []
|
|
|
|
def get_dependencies(self):
|
|
dependencies_names = []
|
|
logger.debug("Updating dependencies...")
|
|
for target in self.selected_targets:
|
|
if hasattr(target, "dependencies"):
|
|
dependencies_names.extend(target.dependencies)
|
|
# remove duplications
|
|
dependencies_names = list(dict.fromkeys(dependencies_names))
|
|
for dependency in dependencies_names:
|
|
_target: Component
|
|
for _target in self.components:
|
|
if _target.name != dependency:
|
|
continue
|
|
if not _target.is_exist():
|
|
FileNotFoundError("Dependency {} not available.".format(_target.name))
|
|
self.dependencies.append(_target)
|
|
|
|
def get_mandatory_component(self):
|
|
for _target in self.components:
|
|
_target: Component
|
|
if hasattr(_target, "mandatory"):
|
|
if not _target.is_exist():
|
|
FileNotFoundError("Mandatory component {} not available.".format(_target.name))
|
|
self.mandatory_components.append(_target)
|
|
|
|
@staticmethod
|
|
def packing_binaries(archive_name: str, target_dir: str, source_dir: str):
|
|
logger.info("Archiving deploy package")
|
|
if os.name == "posix":
|
|
archive_path = DeploymentManager.packing_binaries_posix(
|
|
archive_name, target_dir, source_dir
|
|
)
|
|
else:
|
|
archive_path = DeploymentManager.packing_binaries_windows(
|
|
archive_name, target_dir, source_dir
|
|
)
|
|
logger.setLevel("INFO")
|
|
logger.info(
|
|
"Deployment archive is ready. "
|
|
"You can find it here:\n\t{}".format(os.path.join(target_dir, archive_path))
|
|
)
|
|
|
|
@staticmethod
|
|
def packing_binaries_posix(archive_name: str, target_dir: str, source_dir: str) -> str:
|
|
extension = "tar.gz"
|
|
archive_file_name = "{}.{}".format(archive_name, extension)
|
|
archive_path = os.path.join(target_dir, archive_file_name)
|
|
|
|
import tarfile
|
|
|
|
with tarfile.open(archive_path, "w:gz") as tar_pac:
|
|
total_files_number = DeploymentManager.count_files_number(source_dir)
|
|
count = 0
|
|
logger.info(
|
|
"Total number of files to add to the package: {}".format(total_files_number)
|
|
)
|
|
for root, dirs, files in os.walk(source_dir):
|
|
for file in files:
|
|
count += 1
|
|
full_path = os.path.join(root, file)
|
|
if not os.path.isfile(full_path):
|
|
continue
|
|
relative_path = str(Path(full_path).relative_to(source_dir))
|
|
logger.info(
|
|
"Add {} {}/{} file to the package".format(
|
|
relative_path, count, total_files_number
|
|
)
|
|
)
|
|
tar_pac.add(full_path, arcname=relative_path)
|
|
return archive_path
|
|
|
|
@staticmethod
|
|
def packing_binaries_windows(archive_name: str, target_dir: str, source_dir: str) -> str:
|
|
extension = "zip"
|
|
archive_file_name = "{}.{}".format(archive_name, extension)
|
|
archive_path = os.path.join(target_dir, archive_file_name)
|
|
|
|
from zipfile import ZipFile, ZIP_DEFLATED
|
|
|
|
compression = ZIP_DEFLATED
|
|
with ZipFile(archive_path, "w") as zip_pac:
|
|
total_files_number = DeploymentManager.count_files_number(source_dir)
|
|
count = 0
|
|
logger.info(
|
|
"Total number of files to add to the package: {}".format(total_files_number)
|
|
)
|
|
for root, dirs, files in os.walk(source_dir):
|
|
for file in files:
|
|
count += 1
|
|
full_path = os.path.join(root, file)
|
|
if not os.path.isfile(full_path):
|
|
continue
|
|
relative_path = str(Path(full_path).relative_to(source_dir))
|
|
logger.info(
|
|
"Add {} {}/{} file to the package".format(
|
|
relative_path, count, total_files_number
|
|
)
|
|
)
|
|
zip_pac.write(
|
|
os.path.join(root, file), arcname=relative_path, compress_type=compression
|
|
)
|
|
return archive_path
|
|
|
|
@staticmethod
|
|
def count_files_number(source_dir: str) -> int:
|
|
total_files_number = 0
|
|
for root, dirs, files in os.walk(source_dir):
|
|
total_files_number += len(files)
|
|
return total_files_number
|
|
|
|
def process(self):
|
|
# get dependencies if have
|
|
self.get_dependencies()
|
|
# get mandatory components
|
|
self.get_mandatory_component()
|
|
|
|
logger.info("Collection information for components")
|
|
with tempfile.TemporaryDirectory() as tmpdirname:
|
|
for target in self.selected_targets:
|
|
target: Component
|
|
target.copy_files(tmpdirname)
|
|
if self.dependencies:
|
|
for dependency in self.dependencies:
|
|
dependency: Component
|
|
dependency.copy_files(tmpdirname)
|
|
if self.mandatory_components:
|
|
for target in self.mandatory_components:
|
|
target: Component
|
|
target.copy_files(tmpdirname)
|
|
if self.args.user_data and os.path.exists(self.args.user_data):
|
|
from shutil import copytree
|
|
|
|
logger.info("Storing user data for deploy package ")
|
|
copytree(
|
|
self.args.user_data,
|
|
os.path.join(
|
|
tmpdirname, os.path.basename(self.args.user_data.rstrip(os.path.sep))
|
|
),
|
|
symlinks=True,
|
|
)
|
|
self.packing_binaries(self.args.archive_name, self.args.output_dir, tmpdirname)
|
|
|
|
|
|
def main():
|
|
# read main config
|
|
cfg = ConfigReader(logger)
|
|
|
|
# here we store all components
|
|
components = []
|
|
|
|
for component in cfg.components:
|
|
components.append(
|
|
ComponentFactory.create_component(component, cfg.components[component], logger)
|
|
)
|
|
|
|
# list for only available components
|
|
available_targets = []
|
|
help_msg = ""
|
|
|
|
for component in components:
|
|
if component.is_exist() and not component.invisible:
|
|
available_targets.append(component)
|
|
help_msg += "{} - {}\n".format(component.name, component.ui_name)
|
|
|
|
parser = argparse.ArgumentParser(description="", formatter_class=argparse.RawTextHelpFormatter)
|
|
|
|
parser.add_argument(
|
|
"--targets",
|
|
"-t",
|
|
nargs="+",
|
|
help="List of targets. " "Possible values: \n{}".format(help_msg),
|
|
)
|
|
parser.add_argument(
|
|
"--user_data",
|
|
"-u",
|
|
type=str,
|
|
help="Path to user data that will be added to " "the deployment package",
|
|
default=None,
|
|
)
|
|
parser.add_argument(
|
|
"--output_dir",
|
|
"-o",
|
|
type=str,
|
|
help="Output directory for deployment archive",
|
|
default=os.getenv("HOME", os.path.join(os.path.join(os.path.dirname(__file__), os.pardir))),
|
|
)
|
|
parser.add_argument(
|
|
"--archive_name",
|
|
"-name",
|
|
type=str,
|
|
help="Name for deployment archive",
|
|
default="openvino_deploy_package",
|
|
)
|
|
parser.add_argument("--version", action="version", version="%(prog)s " + __version__)
|
|
|
|
logger.info("Parsing command line arguments")
|
|
args = parser.parse_args()
|
|
|
|
selected_targets = []
|
|
if not available_targets:
|
|
exit(
|
|
"No available targets to packaging detected.\n"
|
|
"Please check your OpenVINO installation."
|
|
)
|
|
|
|
ui = UserInterface(__version__, args, available_targets, logger)
|
|
if not args.targets:
|
|
ui.run()
|
|
selected_targets = ui.get_selected_targets()
|
|
args = ui.args
|
|
else:
|
|
for target in args.targets:
|
|
target_name = target.lower()
|
|
if not any(target_name == _target.name.lower() for _target in available_targets):
|
|
raise ValueError(
|
|
"You input incorrect target. {} is not available.".format(target_name)
|
|
)
|
|
for _target in available_targets:
|
|
if _target.name.lower() == target_name:
|
|
selected_targets.append(_target)
|
|
_manager = DeploymentManager(args, selected_targets, components)
|
|
_manager.process()
|