ERROR = -3
OK = 0
+class OSType:
+ """
+ Supported flavors of Linux OS
+ """
+ FEDORA_12 = "f12"
+ FEDORA_14 = "f14"
+ FEDORA = "fedora"
+ UBUNTU = "ubuntu"
+ DEBIAN = "debian"
+
@clsinit
class LinuxNode(ResourceManager):
_rtype = "LinuxNode"
raise RuntimeError, "%s - %s - %s" %( msg, out, err )
if out.find("Fedora release 12") == 0:
- self._os = "f12"
+ self._os = OSType.FEDORA_12
elif out.find("Fedora release 14") == 0:
- self._os = "f14"
+ self._os = OSType.FEDORA_14
elif out.find("Debian") == 0:
- self._os = "debian"
+ self._os = OSType.DEBIAN
elif out.find("Ubuntu") ==0:
- self._os = "ubuntu"
+ self._os = OSType.UBUNTU
else:
msg = "Unsupported OS"
self.error(msg, out)
def deploy(self):
if self.state == ResourceState.NEW:
try:
- self.discover()
- self.provision()
+ self.discover()
+ self.provision()
except:
self._state = ResourceState.FAILED
raise
if not self.localhost:
# Build destination as <user>@<server>:<path>
dst = "%s@%s:%s" % (self.get("username"), self.get("hostname"), dst)
-
result = self.copy(src, dst)
# clean up temp file
def install_packages(self, packages, home):
command = ""
- if self.os in ["f12", "f14"]:
+ if self.os in [OSType.FEDORA_12, OSType.FEDORA_14, OSType.FEDORA]:
command = rpmfuncs.install_packages_command(self.os, packages)
- elif self.os in ["debian", "ubuntu"]:
+ elif self.os in [OSType.DEBIAN, OSType.UBUNTU]:
command = debfuncs.install_packages_command(self.os, packages)
else:
msg = "Error installing packages ( OS not known ) "
def remove_packages(self, packages, home):
command = ""
- if self.os in ["f12", "f14"]:
+ if self.os in [OSType.FEDORA_12, OSType.FEDORA_14, OSType.FEDORA]:
command = rpmfuncs.remove_packages_command(self.os, packages)
- elif self.os in ["debian", "ubuntu"]:
+ elif self.os in [OSType.DEBIAN, OSType.UBUNTU]:
command = debfuncs.remove_packages_command(self.os, packages)
else:
msg = "Error removing packages ( OS not known ) "
def run_and_wait(self, command, home,
shfile = "cmd.sh",
+ env = None,
pidfile = "pidfile",
ecodefile = "exitcode",
stdin = None,
since in the remote host the command can continue to run detached
even if network disconnections occur
"""
- self.upload_command(command, home, shfile, ecodefile)
+ self.upload_command(command, home,
+ shfile = shfile,
+ ecodefile = ecodefile,
+ env = env)
command = "bash ./%s" % shfile
# run command in background in remote host
self.error(msg, out, err)
if raise_on_error:
raise RuntimeError, msg
-
# Wait for pid file to be generated
pid, ppid = self.wait_pid(
home = home,
(out, err), proc = self.check_errors(home, ecodefile, stderr)
# Out is what was written in the stderr file
- if out or err:
+ if err:
msg = " Failed to run command '%s' " % command
self.error(msg, out, err)
shfile = "cmd.sh",
ecodefile = "exitcode",
env = None):
-
- command = "{ ( %(command)s ) ; } ; echo $? > %(ecodefile)s " % {
+ """ Saves the command as a bash script file in the remote host, and
+ forces to save the exit code of the command execution to the ecodefile
+ """
+
+ # The exit code of the command will be stored in ecodefile
+ command = " %(command)s ; echo $? > %(ecodefile)s ;" % {
'command': command,
'ecodefile': ecodefile,
}
# Export environment
- environ = ""
- if env:
- for var in env.split(" "):
- environ += 'export %s\n' % var
+ environ = self.format_environment(env)
+ # Add environ to command
command = environ + command
dst = os.path.join(home, shfile)
return self.upload(command, dst, text = True)
+ def format_environment(self, env, inline = False):
+ """Format environmental variables for command to be executed either
+ as an inline command (i.e. PYTHONPATH=src/.. python script.py) or
+ as a bash script (i.e. export PYTHONPATH=src/.. \n export LALA=.. \n)
+ """
+ sep = " " if inline else "\n"
+ export = " " if inline else "export"
+ return sep.join(map(lambda e: "%s %s" % (export, e), env.split(" "))) \
+ + sep if env else ""
+
def check_errors(self, home,
ecodefile = "exitcode",
- stderr = "stderr"):
+ stderr = "stderr",
+ stdout = "stdout"):
"""
Checks whether errors occurred while running a command.
It first checks the exit code for the command, and only if the
exit code is an error one it returns the error output.
+
"""
out = err = ""
proc = None
- # get Exit code
+ # get exit code saved in the 'exitcode' file
ecode = self.exitcode(home, ecodefile)
if ecode in [ ExitCode.CORRUPTFILE, ExitCode.ERROR ]:
elif ecode > 0 or ecode == ExitCode.FILENOTFOUND:
# The process returned an error code or didn't exist.
# Check standard error.
- (out, err), proc = self.check_output(home, stderr)
-
- # If the stderr file was not found, assume nothing happened.
- # We just ignore the error.
- if ecode == ExitCode.FILENOTFOUND and proc.poll() == 1: # cat - No such file or directory
- err = ""
+ (err, eerr), proc = self.check_output(home, stderr)
+
+ # Alsow retrive standard output for information
+ (out, oerr), oproc = self.check_output(home, stdout)
+
+ # If the stderr file was not found, assume nothing bad happened,
+ # and just ignore the error.
+ # (cat returns 1 for error "No such file or directory")
+ if ecode == ExitCode.FILENOTFOUND and proc.poll() == 1:
+ err = ""
return (out, err), proc
connect_timeout = 30,
strict_host_checking = False,
persistent = True,
+ blocking = True,
with_lock = False
):
""" Notice that this invocation will block until the
err_on_timeout = err_on_timeout,
connect_timeout = connect_timeout,
persistent = persistent,
+ blocking = blocking,
strict_host_checking = strict_host_checking
)
else:
retry = retry,
err_on_timeout = err_on_timeout,
connect_timeout = connect_timeout,
- persistent = persistent
+ persistent = persistent,
+ blocking = blocking,
+ strict_host_checking = strict_host_checking
)
return (out, err), proc