blob: 5f4d01b33ae8b448f8c517697cfbba2f45516fef [file]
#!/usr/bin/env python
# coding=utf-8
# Copyright [2020] [Apache Software Foundation]
#
# 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
import sys
import subprocess
import tarfile
import wget
import glob
import pickle
import datetime
import time
import shutil
from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
from .log import get_logger
logger = get_logger('misc')
def make_tarfile(output_filename, source_dir):
with tarfile.open(output_filename, "w:gz") as tar:
tar.add(source_dir, arcname=os.path.basename(source_dir))
def package_to_name(package):
#remove marvin_ substring
return package[len("marvin_"):]
def name_to_package(name):
return "marvin_{}".format(name)
def generate_engine_package(package, path, dest=None):
filename = package + "-" + get_version(package, path) + ".tar.gz"
output = os.path.join('/tmp/marvin', filename)
make_tarfile(output, path)
if dest is not None:
move_dest = os.path.join(dest, filename)
else:
move_dest = os.path.join(path, "docker", "develop" ,"daemon", filename)
shutil.move(output, move_dest)
def get_version(package, path):
with open(os.path.join(path, package ,"VERSION"), 'rb') as f:
version = f.read().decode('ascii').strip()
return version
def package_folder(input, output):
with tarfile.open(output, "w:gz") as tar:
tar.add(input, arcname=os.path.basename(input))
def extract_folder(input, output):
tf = tarfile.open(input)
tf.extractall(output)
def call_logs(engine):
container_name = 'marvin-cont-' + engine
p_return = subprocess.Popen(['docker', 'logs', '--follow', container_name], stdout=subprocess.PIPE)
return p_return
def create_or_return_tmp_dir():
tmp_path = '/tmp/marvin'
if not os.path.exists(tmp_path):
os.makedirs(tmp_path)
return tmp_path
def write_tmp_info(key, info):
_filepath = os.path.join(create_or_return_tmp_dir(), key)
logger.info("Creating {0}...".format(key))
with open(_filepath, 'w') as f:
f.write(info)
def retrieve_tmp_info(key):
_filepath = os.path.join(create_or_return_tmp_dir(), key)
logger.info("Retriving {0}...".format(key))
try:
with open(_filepath, 'r') as f:
info = f.read()
return info
except:
return None
def get_executor_path_or_download(executor_url):
#get filename from url
_executor_name = executor_url.split('/').pop(-1)
executor_path = os.path.join(os.environ['MARVIN_DATA_PATH'], _executor_name)
if not os.path.exists(executor_path):
logger.info("Downloading engine executor in {0}...".format(executor_path))
wget.download(executor_url, out=executor_path)
return executor_path
def generate_timestamp():
return datetime.datetime.now().timestamp()
def create_tmp_marvin_folder():
_dir = '/tmp/marvin'
if not os.path.exists(_dir):
os.makedirs(_dir)
def get_chunk_and_untar(bits, output_path):
_dir = '/tmp/marvin'
_tmp_path = os.path.join(_dir, 'tmp_data')
#save tar in tmp file
with open(_tmp_path, 'wb') as f:
for chunk in bits:
f.write(chunk)
f.close()
#extract files
with tarfile.open(_tmp_path) as tf:
tf.extractall(output_path)
tf.close()
#remove tmp_data
os.remove(_tmp_path)
def get_tar_data(source, folder, compress):
_dir = '/tmp/marvin'
tmp_path = os.path.join(_dir, 'tmp_data')
_tar_mode = "w:gz" if compress else "w"
#save tar in tmp file
with tarfile.open(tmp_path, _tar_mode) as tf:
if folder:
tf.add(source, arcname='.')
else:
tf.add(source, arcname=os.path.basename(source))
#get bytes from file
with open(tmp_path, 'rb') as bf:
temp_bytes = bf.read()
return (temp_bytes, tmp_path)
def generate_keys(engine_name):
_key_path = os.path.join(os.environ['MARVIN_DATA_PATH'],
'.keys',
engine_name)
os.makedirs(_key_path)
pvk_path = os.path.join(_key_path, 'id_rsa')
pubk_path = os.path.join(_key_path, 'id_rsa.pub')
key = rsa.generate_private_key(
backend=crypto_default_backend(),
public_exponent=65537,
key_size=2048
)
private_key = key.private_bytes(
crypto_serialization.Encoding.PEM,
crypto_serialization.PrivateFormat.PKCS8,
crypto_serialization.NoEncryption()
)
public_key = key.public_key().public_bytes(
crypto_serialization.Encoding.OpenSSH,
crypto_serialization.PublicFormat.OpenSSH
)
open(pubk_path ,"w").write(public_key.decode("utf-8"))
open(pvk_path ,"w").write(private_key.decode("utf-8"))
os.chmod(pvk_path, 0o500)
return pubk_path
def init_port_forwarding(engine_name, remote_host, ports_list, background=True):
if remote_host != 'localhost' and remote_host != '127.0.0.1':
pkey_path = os.path.join(os.environ['MARVIN_DATA_PATH'], '.keys', engine_name, 'id_rsa')
command_list = ["ssh"]
command_list.append("-o")
command_list.append("StrictHostKeyChecking=no")
command_list.append("-N")
if background:
command_list.append('-f')
for remote_port in ports_list:
command_list.append("-L")
command_list.append("localhost:{0}:localhost:{0}".format(remote_port))
command_list.append("-i")
command_list.append("{0}".format(pkey_path))
command_list.append("marvin@{0}".format(remote_host))
command_list.append("-p")
command_list.append("2022")
if not background:
logger.info("Press Ctrl+C to disable port forwarding")
os.system(" ".join(command_list))