deb-sahara/sahara/plugins/mapr/util/general.py
Artem Osadchyi ca5294a801 Removed redundant metaclass declarations in MapR plugin
Change-Id: Ifad8f7521be49c5564f43e6df78f2d49fb753ba0
Implements: blueprint mapr-refactor-singleton
2015-09-30 17:33:25 +03:00

204 lines
6.5 KiB
Python

# Copyright (c) 2015, MapR Technologies
#
# 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 uuid
from sahara.conductor import objects
from sahara import context
import sahara.utils.files as files
def unique_list(iterable, mapper=lambda i: i):
result = []
for item in iterable:
value = mapper(item)
if value not in result:
result.append(value)
return result
def _run_as(user, command):
if not user:
return command
return 'sudo -u %(user)s %(command)s' % {'user': user, 'command': command}
def unique_file_name(base='/tmp'):
return '%(base)s/%(uuid)s' % {'base': base, 'uuid': uuid.uuid4()}
def remove(instance, path, recursive=True, run_as=None):
with instance.remote() as r:
args = {'recursive': '-r' if recursive else '', 'path': path}
r.execute_command(_run_as(run_as, 'rm %(recursive)s %(path)s' % args))
def create_archive(instance, path, archive=None, run_as=None):
if not archive:
archive = unique_file_name('/tmp')
args = {'archive': archive, 'path': path}
tar = 'tar cf %(archive)s -C %(path)s .' % args
with instance.remote() as r:
r.execute_command(_run_as(run_as, tar))
return archive
def unpack_archive(instance, src, dest, cleanup=False, run_as=None):
with instance.remote() as r:
r.execute_command(_run_as(run_as, 'mkdir -p %s' % dest))
untar = 'tar xf %(src)s -C %(dest)s' % {'src': src, 'dest': dest}
r.execute_command(_run_as(run_as, untar))
if cleanup:
r.execute_command(_run_as(run_as, 'rm -r %s' % src))
def copy_file(s_path, s_instance, d_path, d_instance, run_as=None):
with s_instance.remote() as sr:
data = sr.read_file_from(s_path, run_as_root=(run_as == 'root'))
with d_instance.remote() as dr:
dr.write_file_to(d_path, data, run_as_root=(run_as == 'root'))
def copy_dir(s_path, s_instance, d_path, d_instance, run_as=None):
s_path = create_archive(s_instance, s_path, run_as=run_as)
tmp_path = unique_file_name('/tmp')
copy_file(s_path, s_instance, tmp_path, d_instance, run_as)
unpack_archive(d_instance, tmp_path, d_path, True, run_as)
remove(s_instance, s_path, True, run_as)
def copy(s_path, s_instance, d_path, d_instance, run_as=None):
if is_directory(s_instance, s_path):
copy_dir(s_path, s_instance, d_path, d_instance, run_as)
else:
copy_file(s_path, s_instance, d_path, d_instance, run_as)
def run_script(instance, script, run_as=None, *args, **kwargs):
with instance.remote() as r:
path = '/tmp/%s.sh' % uuid.uuid4()
script = files.get_file_text(script) % kwargs
r.write_file_to(path, script, run_as_root=(run_as == 'root'))
r.execute_command(_run_as(run_as, 'chmod +x %s' % path))
r.execute_command(_run_as(run_as, '%s %s' % (path, ' '.join(args))),
timeout=3600)
# FIXME(aosadchyi): reuse existing remote
remove(instance, path, run_as=run_as)
def execute_on_instances(instances, function, *args, **kwargs):
with context.ThreadGroup() as tg:
for instance in instances:
t_name = '%s-execution' % function.__name__
tg.spawn(t_name, function, instance, *args, **kwargs)
def _replace(args, position, value):
return args[:position] + (value,) + args[position + 1:]
def remote_command(position):
def wrap(func):
def wrapped(*args, **kwargs):
target = args[position]
if isinstance(target, objects.Instance):
with target.remote() as remote:
return func(*_replace(args, position, remote), **kwargs)
return func(*args, **kwargs)
return wrapped
return wrap
def execute_command(instances, command, run_as=None):
def _execute_command(instance):
with instance.remote() as remote:
remote.execute_command(_run_as(run_as, command), timeout=1800)
execute_on_instances(instances, _execute_command)
@remote_command(0)
def is_directory(remote, path):
command = '[ -d %s ]' % path
ec = remote.execute_command(command, True, raise_when_error=False)[0]
return not ec
@remote_command(0)
def chown(remote, owner, path):
args = {'owner': owner, 'path': path}
remote.execute_command('chown -R %(owner)s %(path)s' % args, True)
@remote_command(0)
def chmod(remote, mode, path):
args = {'mode': mode, 'path': path}
remote.execute_command('chmod -R %(mode)s %(path)s' % args, True)
@remote_command(0)
def mkdir(remote, path, mode=None, owner=''):
args = {'mode': '-m %s' % mode if mode else '', 'path': path}
remote.execute_command('mkdir -p %(mode)s %(path)s' % args, bool(owner))
if owner:
chown(remote, owner, path)
@remote_command(0)
def write_file(remote, path, data, mode=None, owner=''):
remote.write_file_to(path, data, run_as_root=bool(owner))
if mode:
chmod(remote, mode, path)
if owner:
chown(remote, owner, path)
@remote_command(0)
def install_ssh_key(remote, user, private_key, public_key):
ssh_dir = '/home/%s/.ssh' % user
owner = '%s:%s' % (user, user)
if not is_directory(remote, ssh_dir):
mkdir(remote, ssh_dir, 700, owner)
write_file(remote, '%s/id_rsa.pub' % ssh_dir, public_key, 644, owner)
write_file(remote, '%s/id_rsa' % ssh_dir, private_key, 600, owner)
@remote_command(0)
def authorize_key(remote, user, public_key):
authorized_keys = '/home/%s/.ssh/authorized_keys' % user
remote.append_to_file(authorized_keys, public_key, run_as_root=True)
@remote_command(0)
def download(remote, url, output=None, run_as=None):
args = {'url': url, 'output': '-O %s' % output if output else ''}
command = _run_as(run_as, 'wget -q %(output)s %(url)s' % args)
remote.execute_command(command, timeout=600)
class Singleton(type):
instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls.instances:
new_instance = super(Singleton, cls).__call__(*args, **kwargs)
cls.instances[cls] = new_instance
return cls.instances[cls]