3 # arv-copy [--recursive] [--no-recursive] object-uuid src dst
5 # Copies an object from Arvados instance src to instance dst.
7 # By default, arv-copy recursively copies any dependent objects
8 # necessary to make the object functional in the new instance
9 # (e.g. for a pipeline instance, arv-copy copies the pipeline
10 # template, input collection, docker images, git repositories). If
11 # --no-recursive is given, arv-copy copies only the single record
12 # identified by object-uuid.
14 # The user must have files $HOME/.config/arvados/{src}.conf and
15 # $HOME/.config/arvados/{dst}.conf with valid login credentials for
16 # instances src and dst. If either of these files is not found,
17 # arv-copy will issue an error.
31 logger = logging.getLogger('arvados.arv-copy')
33 parser = argparse.ArgumentParser(
34 description='Copy a pipeline instance from one Arvados instance to another.')
36 parser.add_argument('--recursive', dest='recursive', action='store_true')
37 parser.add_argument('--no-recursive', dest='recursive', action='store_false')
38 parser.add_argument('object_uuid')
39 parser.add_argument('source_arvados')
40 parser.add_argument('destination_arvados')
41 parser.set_defaults(recursive=True)
43 args = parser.parse_args()
45 # Create API clients for the source and destination instances
46 src_arv = api_for_instance(args.source_arvados)
47 dst_arv = api_for_instance(args.destination_arvados)
49 # And now for the copying.
50 t = uuid_type(args.object_uuid)
52 copy_collection(args.object_uuid, src=src_arv, dst=dst_arv)
53 elif t == 'pipeline_instance':
54 copy_pipeline_instance(args.object_uuid, src=src_arv, dst=dst_arv)
55 elif t == 'pipeline_template':
56 new_pt = copy_pipeline_template(args.object_uuid, src=src_arv, dst=dst_arv)
59 abort("cannot copy object {} of type {}".format(args.object_uuid, t))
63 # Creates an API client for the Arvados instance identified by
64 # instance_name. Looks in $HOME/.config/arvados/instance_name.conf
67 def api_for_instance(instance_name):
68 if '/' in instance_name:
69 abort('illegal instance name {}'.format(instance_name))
70 config_file = os.path.join(os.environ['HOME'], '.config', 'arvados', "{}.conf".format(instance_name))
71 cfg = arvados.config.load(config_file)
73 if 'ARVADOS_API_HOST' in cfg and 'ARVADOS_API_TOKEN' in cfg:
75 cfg.get('ARVADOS_API_HOST_INSECURE', '').lower() in set(
76 ['1', 't', 'true', 'y', 'yes']))
77 client = arvados.api('v1',
78 host=cfg['ARVADOS_API_HOST'],
79 token=cfg['ARVADOS_API_TOKEN'],
80 insecure=api_is_insecure,
83 abort('need ARVADOS_API_HOST and ARVADOS_API_TOKEN for {}'.format(instance_name))
86 def copy_collection(obj_uuid, src=None, dst=None):
87 raise NotImplementedError
89 def copy_pipeline_instance(obj_uuid, src=None, dst=None):
90 raise NotImplementedError
92 def copy_pipeline_template(obj_uuid, src=None, dst=None):
93 # fetch the pipeline template from the source instance
94 old_pt = src.pipeline_templates().get(uuid=obj_uuid).execute()
95 old_pt['name'] = old_pt['name'] + ' copy'
97 del old_pt['owner_uuid']
98 return dst.pipeline_templates().create(body=old_pt).execute()
101 "4zz18": "collection",
102 "d1hrv": "pipeline_instance",
103 "p5p6p": "pipeline_template",
106 def uuid_type(object_uuid):
107 type_str = object_uuid.split('-')[1]
108 return uuid_type_map.get(type_str, None)
110 def abort(msg, code=1):
111 print >>sys.stderr, "arv-copy:", msg
114 if __name__ == '__main__':