/usr/share/pyshared/juju/control/scp.py is in juju-0.7 0.7-0ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | from argparse import RawDescriptionHelpFormatter
import os
from twisted.internet.defer import inlineCallbacks, returnValue
from juju.control.utils import (
get_environment, get_ip_address_for_machine, get_ip_address_for_unit,
parse_passthrough_args, ParseError)
def configure_subparser(subparsers):
sub_parser = subparsers.add_parser(
"scp",
help=command.__doc__,
usage=("%(prog)s [-h] [-e ENV] "
"[remote_host:]file1 ... [remote_host:]file2"),
formatter_class=RawDescriptionHelpFormatter,
description=(
"positional arguments:\n"
" [remote_host:]file The remote host can the name of either\n"
" a Juju unit/machine or a remote system"))
sub_parser.add_argument(
"--environment", "-e",
help="Environment to operate on.", metavar="ENV")
return sub_parser
def passthrough(options, extra):
"""Second parsing phase to parse `extra` to passthrough to scp itself.
Partitions into flags and file specifications.
"""
flags, positional = parse_passthrough_args(extra, "cFiloPS")
if not positional:
raise ParseError("too few arguments")
options.scp_flags = flags
options.paths = positional
def open_scp(flags, paths):
# XXX - TODO - Might be nice if we had the ability to get the user's
# private key path and utilize it here, ie the symmetric end to
# get user public key.
args = ["scp"]
# Unlike ssh, choose not to share connections by default, given
# that the target usage may be for large files. The user's ssh
# config would probably be the best place to get this anyway.
args.extend(flags)
args.extend(paths)
os.execvp("scp", args)
@inlineCallbacks
def _expand_unit_or_machine(client, provider, path):
"""Expands service unit or machine ID into DNS name"""
parts = path.split(":")
if len(parts) > 1:
remote_system = parts[0]
ip_address = None
if remote_system.isdigit():
# machine id, will not pick up dotted IP addresses
ip_address, _ = yield get_ip_address_for_machine(
client, provider, remote_system)
elif "/" in remote_system:
# service unit
ip_address, _ = yield get_ip_address_for_unit(
client, provider, remote_system)
if ip_address:
returnValue("ubuntu@%s:%s" % (ip_address, ":".join(parts[1:])))
returnValue(path) # no need to expand
@inlineCallbacks
def command(options):
"""Use scp to copy files to/from given unit or machine.
"""
# Unlike juju ssh, no attempt to verify liveness of the agent,
# instead it's just a matter of whether the underlying scp will work
# or not.
environment = get_environment(options)
provider = environment.get_machine_provider()
client = yield provider.connect()
try:
paths = [(yield _expand_unit_or_machine(client, provider, path))
for path in options.paths]
open_scp(options.scp_flags, paths)
finally:
yield client.close()
|