Ejemplo n.º 1
0
  def testWithNoPagingAndSlicing(self):

    def mockFunc(project=None, maxResults=None, filter=None, pageToken=None):
      return mock_api.MockRequest({'kind': 'numbers', 'items': [1, 2, 3]})

    self.assertEqual(utils.All(mockFunc, 'my-project', max_results=2),
                     {'kind': 'numbers', 'items': [1, 2]})
Ejemplo n.º 2
0
 def _CalculateNumCpus(self, instances_to_mv):
   """Calculates the amount of CPUs used by the given instances."""
   machines = utils.All(
       self._machine_type_api.list,
       self._project)['items']
   num_cpus = dict((m['selfLink'], m['guestCpus']) for m in machines)
   return sum(float(num_cpus[i['machineType']]) for i in instances_to_mv)
Ejemplo n.º 3
0
  def testWithEmptyResponse(self):

    def mockFunc(project=None, maxResults=None, filter=None, pageToken=None):
      return mock_api.MockRequest({'kind': 'numbers', 'items': []})

    self.assertEqual(utils.All(mockFunc, 'my-project'),
                     {'kind': 'numbers', 'items': []})
Ejemplo n.º 4
0
  def testWithZones(self):
    def mockFunc(project=None, maxResults=None, filter=None, pageToken=None,
                 zone=None):
      self.assertEqual('some-zone', zone)
      return mock_api.MockRequest(
          {'kind': 'numbers', 'items': [1, 2, 3]})

    utils.All(mockFunc, 'my-project', zone='some-zone')
Ejemplo n.º 5
0
 def _CalculateTotalDisksSizeGb(self, disk_names, zone):
   """Calculates the total size of the given disks."""
   disk_names = set(disk_names)
   disks = utils.All(
       self._disks_api.list,
       self._project,
       zone=zone)['items']
   disk_sizes = [float(d['sizeGb']) for d in disks if d['name'] in disk_names]
   return sum(disk_sizes)
Ejemplo n.º 6
0
  def testWithPagingAndSlicing(self):
    responses = [
        mock_api.MockRequest(
            {'kind': 'numbers', 'items': [1, 2, 3], 'nextPageToken': 'abc'}),
        mock_api.MockRequest(
            {'kind': 'numbers', 'items': [4, 5, 6]})]

    def mockFunc(project=None, maxResults=None, filter=None, pageToken=None):
      self._page += 1
      return responses[self._page - 1]

    self.assertEqual(utils.All(mockFunc, 'my-project', max_results=5),
                     {'kind': 'numbers', 'items': [1, 2, 3, 4, 5]})
Ejemplo n.º 7
0
  def testArgumentPlumbing(self):

    def mockFunc(project=None, maxResults=None, filter=None, pageToken=None):
      self.assertEqual(project, 'my-project')
      self.assertEqual(maxResults, 651)
      self.assertEqual(filter, 'name eq my-instance')
      self.assertEqual(pageToken, None)
      return mock_api.MockRequest(
          {'kind': 'numbers', 'items': [1, 2, 3]})

    utils.All(mockFunc, 'my-project',
              max_results=651,
              filter='name eq my-instance')
Ejemplo n.º 8
0
    def testMaxResults(self):
        def mockFunc(project=None,
                     maxResults=None,
                     filter=None,
                     pageToken=None):
            self.assertEqual(maxResults, 37)
            return mock_api.MockRequest({
                'kind': 'numbers',
                'items': [1, 2, 3]
            })

        utils.All(mockFunc,
                  'my-project',
                  max_results=37,
                  filter='name eq my-instance')
Ejemplo n.º 9
0
  def _WaitForSnapshots(self, snapshots):
    """Waits for the given snapshots to be in the READY state."""
    snapshots = set(snapshots)
    start_sec = time.time()
    while True:
      if time.time() - start_sec > self._flags.max_wait_time:
        raise command_base.CommandError(
            'Timeout reached while waiting for snapshots to be ready.')

      all_snapshots = [
          s for s in utils.All(self._snapshots_api.list, self._project)['items']
          if s['name'] in snapshots and s['status'] != 'READY']
      if not all_snapshots:
        break
      LOGGER.info('Waiting for snapshots to be READY. Sleeping for %ss' %
                  self._flags.sleep_between_polls)
      time.sleep(self._flags.sleep_between_polls)
Ejemplo n.º 10
0
    def testMaxResults(self):
        maxResultValues = [
        ]  # values of maxResult parameter collected by mockFunc
        returnedCounts = [80, 40, 50]  # Server returns these counts of objects

        def mockFunc(project=None,
                     maxResults=None,
                     filter=None,
                     pageToken=None):
            maxResultValues.append(maxResults)
            return mock_api.MockRequest({
                'kind':
                'numbers',
                'items':
                range(returnedCounts[len(maxResultValues) - 1]),
                'nextPageToken':
                'next'
            })

        utils.All(mockFunc,
                  'my-project',
                  max_results=150,
                  filter='name eq my-instance')
        self.assertEqual((None, 70, 30), tuple(maxResultValues))
Ejemplo n.º 11
0
  def HandleMove(self, log_path):
    """Attempts the move dictated in the given log file.

    This method first checks the current state of the project to see
    which instances have already been moved before moving the
    instances that were left behind in a previous failed move.

    The user is prompted to continue before any changes are made.

    Args:
      log_path: The path to the replay log.
    """
    if not os.path.exists(log_path):
      raise command_base.CommandError('File not found: %s' % log_path)

    log = self._ParseLog(log_path)

    src_zone = self._GetKey(log, 'src_zone')
    print 'Source zone is %s.' % src_zone

    dest_zone = self._GetKey(log, 'dest_zone')
    print 'Destination zone is %s.' % dest_zone

    snapshot_mappings = self._GetKey(log, 'snapshot_mappings')
    instances_to_mv = self._GetKey(log, 'instances')

    instances_in_dest = utils.All(
        self._instances_api.list, self._project, zone=dest_zone)['items']
    instances_in_source = utils.All(
        self._instances_api.list, self._project, zone=src_zone)['items']

    # Note that we cannot use normal set intersection and subtraction
    # because two different instance resources could be referring to
    # the same instance (e.g., the instance was restarted by the
    # system).
    instances_to_ignore = self._Intersect(instances_to_mv, instances_in_dest)
    instances_to_mv = self._Subtract(instances_to_mv, instances_in_dest)

    if not instances_to_mv:
      raise command_base.CommandError(
          'All instances are already in %s.' % dest_zone)

    # Figures out which disks have not been moved.
    disks_in_dest = set(utils.AllNames(
        self._disks_api.list, self._project, zone=dest_zone))
    disks_in_src = set(utils.AllNames(
        self._disks_api.list, self._project, zone=src_zone))

    disks_to_mv = set(snapshot_mappings.keys()) & disks_in_src

    instances_to_delete = self._Intersect(instances_to_mv, instances_in_source)

    # For the disks that are still in the source zone, figures out
    # which ones still need to be snapshotted before being deleted.
    snapshot_mappings_for_unmoved_disks = {}
    if disks_to_mv:
      current_snapshots = utils.AllNames(
          self._snapshots_api.list, self._project)

      for disk, snapshot in snapshot_mappings.iteritems():
        if disk in disks_to_mv and snapshot not in current_snapshots:
          snapshot_mappings_for_unmoved_disks[disk] = snapshot

    # Ensures that the current quotas can support the move and prompts
    # the user for confirmation.
    self._CheckQuotas(instances_to_mv, disks_to_mv, src_zone, dest_zone,
                      snapshots_to_create=snapshot_mappings_for_unmoved_disks)
    self._Confirm(instances_to_mv, instances_to_ignore,
                  disks_to_mv, dest_zone)

    self._DeleteInstances(instances_to_delete, src_zone)
    self._CreateSnapshots(snapshot_mappings_for_unmoved_disks,
                          src_zone, dest_zone)
    self._DeleteDisks(disks_to_mv, src_zone)

    # Create disks in destination zone from snapshots.
    all_snapshots = set(utils.AllNames(
        self._snapshots_api.list, self._project))
    disks_to_create = {}
    for disk, snapshot in snapshot_mappings.iteritems():
      if snapshot in all_snapshots and disk not in disks_in_dest:
        disks_to_create[disk] = snapshot
    self._CreateDisksFromSnapshots(disks_to_create, dest_zone)

    self._CreateInstances(instances_to_mv, src_zone, dest_zone)
    self._DeleteSnapshots(disks_to_create.values(), dest_zone)

    if not self._flags.keep_log_file:
      # We have succeeded, so it's safe to delete the log file.
      os.remove(log_path)
Ejemplo n.º 12
0
  def HandleMove(self, *instance_regexes):
    """Handles the actual move.

    Args:
      *instance_regexes: The sequence of name regular expressions used
        for filtering.
    """
    self._ValidateFlags()

    if not instance_regexes:
      raise app.UsageError(
          'You must specify at least one regex for instances to move.')

    self._flags.destination_zone = self.DenormalizeResourceName(
        self._flags.destination_zone)
    self._CheckDestinationZone()

    print 'Retrieving instances in %s matching: %s...' % (
        self._flags.source_zone, ' '.join(instance_regexes))
    instances_to_mv = utils.All(
        self._instances_api.list,
        self._project,
        filter=utils.RegexesToFilterExpression(instance_regexes),
        zone=self._flags.source_zone)['items']
    instances_in_dest = utils.All(
        self._instances_api.list,
        self._project,
        filter=utils.RegexesToFilterExpression(instance_regexes),
        zone=self._flags.destination_zone)['items']

    self._CheckInstancePreconditions(instances_to_mv, instances_in_dest)

    instances_to_ignore = utils.All(
        self._instances_api.list,
        self._project,
        filter=utils.RegexesToFilterExpression(instance_regexes, op='ne'),
        zone=self._flags.source_zone)['items']

    print 'Checking disk preconditions...'
    disks_to_mv = self._GetPersistentDiskNames(instances_to_mv)
    self._CheckDiskPreconditions(instances_to_ignore, disks_to_mv)
    # At this point, all disks in use by instances_to_mv are only
    # attached to instances in the set instances_to_mv.

    # Check the snapshots quota and the quota in the destination zone
    # to make sure that enough quota exists to support the move.
    self._CheckQuotas(instances_to_mv, disks_to_mv, self._flags.source_zone,
                      self._flags.destination_zone)

    self._Confirm(instances_to_mv, [], disks_to_mv,
                  self._flags.destination_zone)

    log_path = self._GenerateLogPath()
    snapshot_mappings = self._GenerateSnapshotNames(disks_to_mv)
    self._WriteLog(log_path, instances_to_mv, snapshot_mappings)

    self._DeleteInstances(instances_to_mv, self._flags.source_zone)

    # Assuming no other processes have modified the user's project, at
    # this point, we can assume that all disks-to-be-moved are
    # dormant.
    self._CreateSnapshots(snapshot_mappings,
                          self._flags.source_zone,
                          self._flags.destination_zone)
    self._DeleteDisks(disks_to_mv, self._flags.source_zone)
    self._CreateDisksFromSnapshots(snapshot_mappings,
                                   self._flags.destination_zone)
    self._CreateInstances(instances_to_mv,
                          self._flags.source_zone,
                          self._flags.destination_zone)

    self._DeleteSnapshots(snapshot_mappings.values(),
                          self._flags.destination_zone)

    # We have succeeded, so it's safe to delete the log file.
    os.remove(log_path)