def _CreateDisksFromSnapshots(self, snapshot_mappings, dest_zone): """Creates disks in the destination zone from the given snapshots. Args: snapshot_mappings: A dict of disk names to snapshot names. Disks are created in the destination zone from the given snapshot names. The disks will assume their previous names as indicated by the key-value pairs. dest_zone: The zone in which the disks will be created. """ if not snapshot_mappings: return print 'Recreating disks from snapshots...' requests = [] for disk_name, snapshot_name in snapshot_mappings.iteritems(): disk_resource = { 'name': disk_name, 'sourceSnapshot': self.NormalizeGlobalResourceName( self._project, 'snapshots', snapshot_name)} requests.append(self._disks_api.insert( project=self._project, body=disk_resource, zone=dest_zone)) results, exceptions = self.ExecuteRequests( requests, collection_name='disks') if exceptions: raise command_base.CommandError( 'Aborting due to errors while re-creating disks:\n%s' % utils.ListStrings(exceptions)) self._CheckForErrorsInOps(self.MakeListResult(results, 'operationList'))
def _DeleteInstances(self, instances, zone): """Deletes the given instances. Args: instances: A list of instance resources. zone: The zone to which the instances belong. Raises: CommandError: If one or more of the deletions fail. """ if not instances: return print 'Deleting instances...' requests = [] for instance in instances: requests.append(self._instances_api.delete( project=self._project, zone=zone, instance=instance['name'])) results, exceptions = self.ExecuteRequests( requests, collection_name='instances') if exceptions: raise command_base.CommandError( 'Aborting due to errors while deleting instances:\n%s' % utils.ListStrings(exceptions)) self._CheckForErrorsInOps(self.MakeListResult(results, 'operationList'))
def _CreateSnapshots(self, snapshot_mappings, src_zone, dest_zone): """Creates snapshots for the disks to be moved. Args: snapshot_mappings: A map of disk names that should be moved to the names that should be used for each disk's snapshot. src_zone: The source zone. All disks in snapshot_mappings must be in this zone. dest_zone: The zone the disks are destined for. """ if not snapshot_mappings: return print 'Snapshotting disks...' requests = [] for disk_name, snapshot_name in snapshot_mappings.iteritems(): snapshot_resource = { 'name': snapshot_name, 'sourceDisk': self.NormalizePerZoneResourceName( self._project, src_zone, 'disks', disk_name), 'description': ('Snapshot for moving disk %s from %s to %s.' % (disk_name, src_zone, dest_zone))} requests.append(self._snapshots_api.insert( project=self._project, body=snapshot_resource)) results, exceptions = self.ExecuteRequests( requests, collection_name='snapshots') if exceptions: raise command_base.CommandError( 'Aborting due to errors while creating snapshots:\n%s' % utils.ListStrings(exceptions)) self._CheckForErrorsInOps(self.MakeListResult(results, 'operationList')) self._WaitForSnapshots(snapshot_mappings.values())
def _DeleteDisks(self, disk_names, zone): """Deletes the given disks. Args: disk_names: A list of disk names to delete. zone: The zone to which the disks belong. """ if not disk_names: return print 'Deleting disks...' requests = [] for name in disk_names: requests.append( self._disks_api.delete(project=self._project, disk=name, zone=zone)) results, exceptions = self.ExecuteRequests(requests, collection_name='disks') if exceptions: raise command_base.CommandError( 'Aborting due to errors while deleting disks:\n%s' % utils.ListStrings(exceptions)) self._CheckForErrorsInOps(self.MakeListResult(results, 'operationList'))
def _DeleteSnapshots(self, snapshot_names, zone): """Deletes the given snapshots. Args: snapshot_names: A list of snapshot names to delete. zone: The zones to which the snapshots belong. """ if not snapshot_names or self._flags.keep_snapshots: return print 'Deleting snapshots...' requests = [] for name in snapshot_names: requests.append( self._snapshots_api.delete(project=self._project, snapshot=name)) results, exceptions = self.ExecuteRequests(requests, collection_name='snapshots') if exceptions: raise command_base.CommandError( 'Aborting due to errors while deleting snapshots:\n%s' % utils.ListStrings(exceptions)) self._CheckForErrorsInOps(self.MakeListResult(results, 'operationList'))
def _CheckForErrorsInOps(self, results): """Raises CommandError if any operations in results contains an error.""" _, ops = self._PartitionResults(results) errors = [] for op in (ops or []): if 'error' in op and 'errors' in op['error'] and op['error']['errors']: error = op['error']['errors'][0].get('message') if error: errors.append(error) if errors: raise command_base.CommandError( 'Encountered errors:\n%s' % utils.ListStrings(errors))
def _Confirm(self, instances_to_mv, instances_to_ignore, disks_to_mv, dest_zone): """Displays what is about to happen and prompts the user to proceed. Args: instances_to_mv: The instances that will be moved. instances_to_ignore: Instances that will not be moved because they're already in the destination zone. disks_to_mv: A list of the disk names that will be moved. dest_zone: The destination zone. Raises: CommandError: If the user declines to proceed. """ # Ensures that the parameters make sense. assert instances_to_mv, ( 'Cannot confirm move if there are no instances to move.') assert not [ i for i in instances_to_mv if i['zone'].endswith(dest_zone) ], ('Some instances in the move set are already in the destination zone.' ) assert ([ i for i in instances_to_ignore if i['zone'].endswith(dest_zone) ] == instances_to_ignore), ( 'Not all instances in ignore set are in destination zone.') if instances_to_ignore: print('These instances are already in %s and will not be moved:' % dest_zone) print utils.ListStrings(i['name'] for i in instances_to_ignore) print 'The following instances will be moved to %s:' % dest_zone print utils.ListStrings(i['name'] for i in instances_to_mv) if disks_to_mv: print 'The following disks will be moved to %s:' % dest_zone print utils.ListStrings(disks_to_mv) if not self._flags.force and not utils.Proceed(): raise command_base.CommandError('Move aborted.')
def _CheckDiskPreconditions(self, instances_to_ignore, disk_names): if len(disk_names) > MAX_DISKS_TO_MOVE: raise command_base.CommandError( 'At most %s disks can be moved at a ' 'time. Refine your query and try again.' % MAX_DISKS_TO_MOVE) res = self._CheckForDisksInUseByOtherInstances( instances_to_ignore, disk_names) if res: offending_instances = ['%s: %s' % (instance, ', '.join(disks)) for instance, disks in res] raise command_base.CommandError( 'Some of the instances you\'d like to move have disks that are in ' 'use by other instances: (Offending instance: disks attached)\n%s' % (utils.ListStrings(offending_instances)))
def _CreateInstances(self, instances, src_zone, dest_zone): """Creates the instance resources in the given list in dest_zone. The instance resources are changed in two ways: (1) Their zone fields are changed to dest_zone; and (2) Their ephemeral IPs are cleared. Args: instances: A list of instance resources. src_zone: The zone to which the instances belong. dest_zone: The destination zone. Raises: CommandError: If one or more of the insertions fail. """ if not instances: return print 'Recreating instances in %s...' % dest_zone ip_addresses = set( self._project_resource.get('externalIpAddresses', [])) self._SetIps(instances, ip_addresses) requests = [] for instance in instances: instance['zone'] = self.NormalizeTopLevelResourceName( self._project, 'zones', dest_zone) # Replaces the zones for the persistent disks. for disk in instance['disks']: if 'source' in disk: disk['source'] = disk['source'].replace( 'zones/' + src_zone, 'zones/' + dest_zone) requests.append( self._instances_api.insert(project=self._project, body=instance, zone=dest_zone)) results, exceptions = self.ExecuteRequests(requests, collection_name='instances') if exceptions: raise command_base.CommandError( 'Aborting due to errors while creating instances:\n%s' % utils.ListStrings(exceptions)) self._CheckForErrorsInOps(self.MakeListResult(results, 'operationList'))
def _CheckInstancePreconditions(self, instances_to_mv, instances_in_dest): if not instances_to_mv: raise command_base.CommandError('No matching instances were found.') if len(instances_to_mv) > MAX_INSTANCES_TO_MOVE: raise command_base.CommandError( 'At most %s instances can be moved at a ' 'time. Refine your query and try again.' % MAX_INSTANCES_TO_MOVE) # Checks for name collisions. src_names = [i['name'] for i in instances_to_mv] dest_names = [i['name'] for i in instances_in_dest] common_names = set(src_names) & set(dest_names) if common_names: raise command_base.CommandError( 'Encountered name collisions. Instances with the following names ' 'exist in both the source and destination zones: \n%s' % utils.ListStrings(common_names))