blob: a58b16749fc2934585c9492433e8dbb804c09dfc [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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 fnmatch
import pickle
import shutil
import errno
from gppylib.commands.base import Command, REMOTE
from gppylib.operations import Operation
from gppylib.operations.utils import RemoteOperation
# TODO: Improve RawRemoteOperation
"""
Requirements:
1. Clean Code: Remove python -c "lots of inline stuff".
2. Eliminate redundancy: Remove having to create a FooRemote operation to accompany Foo.
Proposal:
1. Create module gppylib.operations.raw
2. Put RawRemoteOperation in gppylib.operations.raw.__init__
3. Put each core operation here in its own file, i.e. gppylib.operations.raw.list_files.ListFiles
4. Require each such file to only import built-in modules
5. Reimplement RawRemoteOperation to do the following:
a. Determine file of nested operation via inspect.getsourcefile(operation.__class__)
b. Scp this file to remote:/tmp/<random>
c. Scp gppylib/operations/__init__.py to remote:/tmp/<random>
d. Scp rawoperation.py to remote:/tmp/<random> (to behave like gpoperation.py)
e. Invoke rawoperation.py with pickled IO, much like RemoteOperation
"""
class RawRemoteOperation(Operation):
"""
As general purpose helpers, the Operations herein may not necessarily be invoked on remote hosts that use gppylib.
Therefore, the internal pickling mechanism of RemoteOperation will not work. A more raw mechanism is needed.
"""
def __init__(self, cmd_str, host):
self.cmd_str = cmd_str
self.host = host
def execute(self):
cmd = Command(name = self.__class__.__name__,
cmdStr = self.cmd_str,
ctxt = REMOTE,
remoteHost = self.host)
cmd.run(validateAfter=True)
# TODO! If exception is raised remotely, there's no stdout, thereby causing a pickling error.
return pickle.loads(cmd.get_results().stdout)
def __str__(self):
return "Raw(%s, %s)" % (self.cmd_str, self.host)
class ListRemoteFiles(RawRemoteOperation):
def __init__(self, path, host):
self.path, self.host = path, host
super(ListRemoteFiles, self).__init__(""" python -c "import os, pickle; print pickle.dumps(os.listdir('%s'))" """ % path, host)
def __str__(self):
return "ListRemoteFiles(%s, %s)" % (self.path, self.host)
class ListFiles(Operation):
def __init__(self, path):
self.path = path
def execute(self):
return os.listdir(self.path)
def __str__(self):
return "ListFiles(%s)" % self.path
class ListRemoteFilesByPattern(RawRemoteOperation):
def __init__(self, path, pattern, host):
self.path, self.pattern, self.host = path, pattern, host
super(ListRemoteFilesByPattern, self).__init__(""" python -c "import os, fnmatch, pickle; print pickle.dumps(fnmatch.filter(os.listdir('%s'), '%s'))" """ % (path, pattern), host)
def __str__(self):
return "ListRemoteFilesByPattern(%s, %s, %s)" % (self.path, self.pattern, self.host)
class ListFilesByPattern(Operation):
def __init__(self, path, pattern):
self.path, self.pattern = path, pattern
def execute(self):
return fnmatch.filter(os.listdir(self.path), self.pattern)
def __str__(self):
return "ListFilesByPattern(%s, %s)" % (self.path, self.pattern)
class CheckRemoteDir(RawRemoteOperation):
def __init__(self, path, host):
self.path, self.host = path, host
super(CheckRemoteDir, self).__init__(""" python -c "import os, pickle; print pickle.dumps(os.path.isdir('%s'))" """ % path, host)
def __str__(self):
return "CheckRemoteDir(%s, %s)" % (self.path, self.host)
class CheckDir(Operation):
def __init__(self, path):
self.path = path
def execute(self):
return os.path.isdir(self.path)
def __str__(self):
return "CheckDir(%s)" % self.path
class MakeRemoteDir(RawRemoteOperation):
def __init__(self, path, host):
self.path, self.host = path, host
super(MakeRemoteDir, self).__init__(""" python -c "import os, pickle; print pickle.dumps(os.makedirs('%s'))" """ % path, host)
def __str__(self):
return "MakeRemoteDir(%s, %s)" % (self.path, self.host)
class MakeDir(Operation):
def __init__(self, path):
self.path = path
def execute(self):
try:
return os.makedirs(self.path)
except OSError, e:
if e.errno != errno.EEXIST:
raise
def __str__(self):
return "MakeDir(%s)" % self.path
class CheckRemoteFile(RawRemoteOperation):
def __init__(self, path, host):
self.path, self.host = path, host
super(CheckRemoteFile, self).__init__(""" python -c "import os, pickle; print pickle.dumps(os.path.isfile('%s'))" """ % path, host)
def __str__(self):
return "CheckRemoteFile(%s, %s)" % (self.path, self.host)
class CheckFile(Operation):
def __init__(self, path):
self.path = path
def execute(self):
return os.path.isfile(self.path)
def __str__(self):
return "CheckFile(%s)" % self.path
class RemoveRemoteFile(RawRemoteOperation):
def __init__(self, path, host):
self.path, self.host = path, host
super(RemoveRemoteFile, self).__init__(""" python -c "import os, pickle; print pickle.dumps(os.remove('%s'))" """ % path, host)
def __str__(self):
return "RemoveRemoteFile(%s, %s)" % (self.path, self.host)
class RemoveFile(Operation):
def __init__(self, path):
self.path = path
def execute(self):
return os.remove(self.path)
def __str__(self):
return "RemoveFile(%s)" % self.path
class RemoveRemoteTree(RawRemoteOperation):
def __init__(self, path, host):
self.path, self.host = path, host
super(RemoveRemoteTree, self).__init__(""" python -c "import shutil, pickle; print pickle.dumps(shutil.rmtree('%s'))" """ % path, host)
def __str__(self):
return "RemoveRemoteTree(%s, %s)" % (self.path, self.host)
class RemoveTree(Operation):
def __init__(self, path):
self.path = path
def execute(self):
return shutil.rmtree(self.path)