def save(self, requester, new_image_name, name_confirmed): username = requester.get_username() if not username: return 'GIVE_UP' # client already disconnected, give up # 1st step: validate new name existing_image = self.images.get_user_image_from_name( requester, new_image_name, expected=None) if self.image.name == new_image_name: if name_confirmed: pass else: # same name for the modified image. # this would overwrite the existing one. # we will let the user confirm this. self.images.warn_overwrite_image(requester, self.image.name) return 'NAME_NEEDS_CONFIRM' else: # save as a different name if existing_image: requester.stderr.write('Bad name: Image already exists.\n') return 'NAME_NOT_OK' # verify name syntax if not validate_image_name(requester, new_image_name): return 'NAME_NOT_OK' # ok, all is fine # 2nd step: save the image image_fullname = format_image_fullname(username, new_image_name) # with the walt image cp command, the client sends a request to start a # container for receiving, then immediately starts to send a tar archive, # and then tries to commit the container through rpc commands. # we have to ensure here that the container was run and completed its job. while True: event = next(self.docker_events) if 'Status' not in event or 'Name' not in event: continue if event['Status'] in ('cleanup', 'died') and event['Name'] == self.container_name: break # if we modified an image in use, umount/mount it in order to make changes # available to nodes need_remount = (self.image.fullname == image_fullname) and self.image.in_use if need_remount: self.images.umount_used_image(self.image) print('committing %s...' % self.container_name) self.docker.local.commit(self.container_name, image_fullname) if need_remount: self.images.update_image_mounts() if self.image.fullname == image_fullname: # same name, we are modifying the image requester.stdout.write('Image %s updated.\n' % new_image_name) self.image.task_label = None return 'OK_BUT_REBOOT_NODES' else: # we are saving changes to a new image, leaving the initial one # unchanged self.images.register_image(image_fullname, True) requester.stdout.write('New image %s saved.\n' % new_image_name) self.image.task_label = None return 'OK_SAVED'
def get_user_image_from_name(self, requester, image_name, expected=True, ready_only=True): username = requester.get_username() if not username: return None # client already disconnected, give up found = None fullname = format_image_fullname(username, image_name) for image in self.images.values(): if image.fullname == fullname: found = image if expected == True and found is None: requester.stderr.write( "Error: No such image '%s'. (tip: walt image show)\n" % image_name) if expected == False and found is not None: requester.stderr.write("Error: Image '%s' already exists.\n" % image_name) if expected == True and found is not None: if ready_only and found.ready == False: requester.stderr.write("Error: Image '%s' is not ready.\n" % image_name) found = None return found
def do_rename(images, docker, image, new_name): new_fullname = format_image_fullname(image.user, new_name) # rename the docker image docker.local.tag(image.fullname, new_fullname) docker.local.rmi(image.fullname) # update the store images.rename(image.fullname, new_fullname)
def do_rename(images, docker, image, new_name): new_fullname = format_image_fullname(image.user, new_name) # rename the docker image docker.local.tag(image.fullname, new_fullname) docker.local.rmi(image.fullname) # update the store images.rename(image.fullname, new_fullname)
def image_shell_session_save(self, requester, session, new_name, name_confirmed): status = session.save(requester, new_name, name_confirmed) if status == 'OK_BUT_REBOOT_NODES': image_fullname = format_image_fullname(requester.get_username(), new_name) self.nodes.reboot_nodes_for_image(requester, image_fullname) status = 'OK_SAVED' return status
def warn_overwrite_image(self, requester, image_name): image_fullname = format_image_fullname(requester.get_username(), image_name) num_nodes = self.num_nodes_using_image(image_fullname) if num_nodes == 0: reboot_message = '' else: reboot_message = MSG_WOULD_OVERWRITE_IMAGE_REBOOTED_NODES % num_nodes requester.stderr.write(MSG_WOULD_OVERWRITE_IMAGE % reboot_message)
def warn_overwrite_image(self, requester, image_name): image_fullname = format_image_fullname(requester.get_username(), image_name) num_nodes = self.num_nodes_using_image(image_fullname) if num_nodes == 0: reboot_message = '' else: reboot_message = MSG_WOULD_OVERWRITE_IMAGE_REBOOTED_NODES % num_nodes requester.stderr.write(MSG_WOULD_OVERWRITE_IMAGE % reboot_message)
def image_shell_session_save(self, requester, session, new_name, name_confirmed): status = session.save(requester, new_name, name_confirmed) if status == 'OK_BUT_REBOOT_NODES': image_fullname = format_image_fullname(requester.get_username(), new_name) self.nodes.reboot_nodes_for_image(requester, image_fullname) status = 'OK_SAVED' return status
def task_callback(status): if status == 'OK_BUT_REBOOT_NODES': image_fullname = format_image_fullname( requester.get_username(), image_name) task_callback_2 = lambda res: task.return_result('OK') self.reboot_nodes_after_image_change(requester, task_callback_2, image_fullname) else: task.return_result(status)
def image_shell_session_save(self, requester, cb_return, session, new_name, name_confirmed): image_fullname = format_image_fullname(requester.get_username(), new_name) status = session.save(requester, new_name, name_confirmed) if status == 'OK_BUT_REBOOT_NODES': cb_reboot = lambda res: cb_return('OK_SAVED') self.reboot_nodes_after_image_change(requester, cb_reboot, image_fullname) else: cb_return(status)
def warn_if_would_reboot_nodes(self, requester, image_name): if '/' in image_name: image_fullname = image_name else: image_fullname = format_image_fullname(requester.get_username(), image_name) num_nodes = self.num_nodes_using_image(image_fullname) if num_nodes == 0: return False # no node would reboot requester.stderr.write(MSG_WOULD_REBOOT_NODES % num_nodes) return True # yes it would reboot some nodes
def get_user_image_from_name(self, requester, image_name, expected = True, ready_only = True): username = requester.get_username() if not username: return None # client already disconnected, give up found = None fullname = format_image_fullname(username, image_name) for image in self.images.values(): if image.fullname == fullname: found = image if expected == True and found is None: requester.stderr.write( "Error: No such image '%s'. (tip: walt image show)\n" % image_name) if expected == False and found is not None: requester.stderr.write( "Error: Image '%s' already exists.\n" % image_name) if expected == True and found is not None: if ready_only and found.ready == False: requester.stderr.write( "Error: Image '%s' is not ready.\n" % image_name) found = None return found
def do_duplicate(images, docker, image, new_name): new_fullname = format_image_fullname(image.user, new_name) # add a tag to the docker image docker.local.tag(image.fullname, new_fullname) # update the store images.register_image(new_fullname, True)
def save(self, requester, new_image_name, name_confirmed): username = requester.get_username() if not username: return 'GIVE_UP' # client already disconnected, give up # 1st step: validate new name existing_image = self.images.get_user_image_from_name( requester, new_image_name, expected=None) if self.image.name == new_image_name: if name_confirmed: pass else: # same name for the modified image. # this would overwrite the existing one. # we will let the user confirm this. self.images.warn_overwrite_image(requester, self.image.name) return 'NAME_NEEDS_CONFIRM' else: # save as a different name if existing_image: requester.stderr.write('Bad name: Image already exists.\n') return 'NAME_NOT_OK' # verify name syntax if not validate_image_name(requester, new_image_name): return 'NAME_NOT_OK' # ok, all is fine # 2nd step: save the image image_fullname = format_image_fullname(username, new_image_name) # with the walt image cp command, the client sends a request to start a # container for receiving, then immediately starts to send a tar archive, # and then tries to commit the container through rpc commands. # we have to ensure here that the container was run and completed its job. while True: event = self.docker_events.next() if 'status' not in event: continue if event['status'] == 'die' and \ self.docker.local.get_container_name(event['id']) == self.container_name: break print 'committing %s...' % self.container_name self.docker.local.commit(self.container_name, image_fullname, 'Image modified using walt image [cp|shell]') if self.image.fullname == image_fullname: # same name, we are modifying the image # if image is mounted, umount/mount it in order to make changes # available to nodes if self.image.mounted: # umount self.images.umount_used_image(self.image) # re-mount self.images.update_image_mounts() # done. requester.stdout.write('Image %s updated.\n' % new_image_name) self.image.task_label = None return 'OK_BUT_REBOOT_NODES' else: # we are saving changes to a new image, leaving the initial one # unchanged self.images.register_image(image_fullname, True) requester.stdout.write('New image %s saved.\n' % new_image_name) self.image.task_label = None return 'OK_SAVED'
def do_duplicate(images, docker, image, new_name): new_fullname = format_image_fullname(image.user, new_name) # add a tag to the docker image docker.local.tag(image.fullname, new_fullname) # update the store images.register_image(new_fullname, True)