def get_containers(): with open(MODIFIED_YML_PATH) as f: y = yaml.load(f) # Manually insert the Loader container as it's been removed from the modified yaml. ret = {my_container_name(): my_full_image_name()} for key, c in y['containers'].iteritems(): ret[key] = c['image'] return json.dumps(ret)
def switch(repo, tag, target): kill_other_containers() print 'Computing data volumes to be copied from the old containers...' # List old containers # old: map of original-name => (old modified-name, image) old = {} with open(MODIFIED_YML_PATH) as f: for k, v in yaml.load(f)['containers'].iteritems(): old[v['original-name']] = (k, v['image']) # List the new containers that haven't been created and have shared volumes with their old counterparts. # new: map of new modified-name => (old modified-name, volumes shared by both old and new containers) new = {} new_loader_image = '{}/{}:{}'.format(repo, my_image_name(), tag) cmd = ['docker', 'run', '--rm', '-v', '/var/run/docker.sock:/var/run/docker.sock', new_loader_image, 'modified-yml', repo, tag] for new_container, new_container_props in yaml.load(subprocess.check_output(print_args(cmd)))['containers'].iteritems(): counterpart = old.get(new_container_props['original-name']) if not counterpart: print '{} has no counterpart'.format(new_container) continue volumes = volume_set_of(new_container_props['image']) if not volumes: print '{} has no data volumes'.format(new_container) continue counterpart_volumes = volume_set_of(counterpart[1]) if not counterpart_volumes: print '{}\'s counterpart has no data volumes'.format(new_container) continue intersected_volumes = volumes & counterpart_volumes if not counterpart_volumes: print '{} has no intersecting data volumes'.format(new_container) continue if has_container(new_container): print '{} already exists'.format(new_container) continue if not has_container(counterpart[0]): print '{} doesn\'t exist'.format(counterpart[0]) continue new[new_container] = (counterpart[0], intersected_volumes) print 'Containers for data copying, in the format of "target-container: (source-container, volumes)":' print new # Create the loader container first. Otherwise when launching the containers that we create below, the system would # fail if one of them links to the new loader -- the `create-containers` command doesn't create the loader. new_loader = create_loader_container(new_loader_image, tag) if new: # Create containers cmd = ['docker', 'run', '--rm', '-v', '/var/run/docker.sock:/var/run/docker.sock', new_loader_image, 'create-containers', repo, tag, new_loader] cmd.extend(new.keys()) subprocess.check_call(print_args(cmd)) # Copy data loader_image = my_full_image_name() for container, new_container_props in new.iteritems(): cmd = ['/copy-container-data.sh', loader_image, new_container_props[0], container] cmd.extend(list(new_container_props[1])) subprocess.check_call(print_args(cmd)) with open(_repo_file, 'w') as f: f.write(repo) with open(_tag_file, 'w') as f: f.write(tag) return restart_to(target)