def test_pull(self, mock_from_env):
        mock_from_env.return_value = self.fake_client

        client = containers.DockerClient()
        client.logged_in = True
        client.pull('image1')
        self.assertTrue('image1' in self.fake_client.images.images)
    def test_has_image(self, mock_from_env):
        self.fake_client.images.images.append('image1')
        mock_from_env.return_value = self.fake_client

        client = containers.DockerClient()
        self.assertTrue(client.has_image('image1'))
        self.assertFalse(client.has_image('image99'))
    def test_login_no_creds(self, mock_path_exists, mock_from_env):
        mock_from_env.return_value = self.fake_client
        mock_path_exists.return_value = False

        client = containers.DockerClient()
        self.assertRaises(OSError, client.login, 'registry_url.com',
                          '/path/to/creds')
    def test_ping_success(self, mock_sleep, mock_from_env):
        self.fake_client.responsive = True
        mock_from_env.return_value = self.fake_client
        mock_sleep.return_value = None

        client = containers.DockerClient()
        self.assertTrue(client.ping())
    def test_stop_old_containers(self, mock_from_env):
        young_container = FakeContainer('young_container', uptime=10)
        old_container = FakeContainer('old_container', uptime=999)
        mock_from_env.return_value = self.fake_client

        containers.DockerClient().stop_old_containers(
            [young_container, old_container], 100)
        self.assertFalse(young_container.swarming_bot_killed)
        self.assertTrue(old_container.swarming_bot_killed)
    def test_login(self, mock_path_exists, mock_from_env):
        mock_from_env.return_value = self.fake_client
        mock_path_exists.return_value = True

        client = containers.DockerClient()
        with mock.patch('__builtin__.open',
                        mock.mock_open(read_data='omg creds')):
            client.login('registry_url.com', '/path/to/creds')

        self.assertTrue(client.logged_in, True)
        self.assertEquals(self.fake_client.creds[1], 'omg creds')
    def test_ping_fail(self, mock_sleep, mock_from_env):
        self.fake_client.responsive = False
        mock_from_env.return_value = self.fake_client
        mock_sleep.return_value = None

        client = containers.DockerClient()
        self.assertFalse(client.ping(retries=5))
        mock_sleep.assert_has_calls(
            [mock.call(1),
             mock.call(2),
             mock.call(4),
             mock.call(8)])
    def test_create_missing_containers(self, mock_from_env):
        running_containers = [
            FakeContainer('android_serial1'),
            FakeContainer('android_serial2'),
        ]
        devices = [
            FakeDevice('serial1', 1),
            FakeDevice('serial2', 2),
            FakeDevice('serial3', 3),
        ]
        self.fake_client.containers = FakeContainerList(running_containers)
        mock_from_env.return_value = self.fake_client

        needs_cgroup_update = containers.DockerClient(
        ).create_missing_containers(running_containers, devices, 'image',
                                    'swarm-url.com')
        # Ensure serial3 needs to be rebooted. This indicates that a new container
        # was created for it.
        self.assertEquals([d.serial for d in needs_cgroup_update], ['serial3'])
Exemple #9
0
def main():
  parser = argparse.ArgumentParser(
      description='Manage docker containers that wrap an android device.')
  parser.add_argument(
      '-v', '--verbose', action='store_true', help='Enable verbose logging.')
  parser.add_argument(
      '--device', action='append', dest='devices', default=[],
      help='Serial number of device whose container is to be managed. Defaults '
      'to ALL local devices.')
  subparsers = parser.add_subparsers()

  add_subparser = subparsers.add_parser(
      'add_device', help='Give a container access to its device.'
  )
  add_subparser.set_defaults(func=add_device, name='add_device')

  launch_subparser = subparsers.add_parser(
      'launch',
      help='Ensures the specified devices have a running container. Will send '
           'a kill signal to containers that exceed max uptime.'
  )
  launch_subparser.set_defaults(func=launch, name='launch')
  launch_subparser.add_argument(
      '--max-container-uptime', type=int, default=60 * 4,
      help='Max uptime of a container, in minutes.')
  launch_subparser.add_argument(
      '--max-host-uptime', type=int, default=60 * 24,
      help='Max uptime of the host, in minutes.')
  launch_subparser.add_argument(
      '--image-name', default='android_docker:latest',
      help='Name of docker image to launch from.')
  launch_subparser.add_argument(
      '--swarming-server', default='https://chromium-swarm.appspot.com',
      help='URL of the swarming server to connect to.')
  launch_subparser.add_argument(
      '--registry-project', default='chromium-container-registry',
      help='Name of gcloud project id for the container registry.')
  launch_subparser.add_argument(
      '--credentials-file',
      default='/creds/service_accounts/'
              'service-account-container_registry_puller.json',
      help='Path to service account json file used to access the gcloud '
           'container registry.')
  args = parser.parse_args()

  logger = logging.getLogger()
  logger.setLevel(logging.DEBUG if args.verbose else logging.WARNING)
  log_fmt = logging.Formatter(
      '%(asctime)s.%(msecs)03d %(levelname)s %(message)s',
      datefmt='%y%m%d %H:%M:%S')

  # Udev-triggered runs of this script run as root while the crons run as
  # non-root. Manually set umask to ensure the world can read/write to the log
  # files even if they're owned by root.
  os.umask(0o000)
  file_handler = logging.handlers.RotatingFileHandler(
      '/var/log/chrome-infra/android_containers.log',
      maxBytes=10 * 1024 * 1024, backupCount=5)
  file_handler.setFormatter(log_fmt)
  logger.addHandler(file_handler)
  stdout_handler = logging.StreamHandler(sys.stdout)
  logger.addHandler(stdout_handler)

  # Quiet the cmd_helper module. It can be quite noisy.
  cmd_helper_logger= logging.getLogger('devil.utils.cmd_helper')
  cmd_helper_logger.setLevel(logging.ERROR)

  logging.debug('Killing any host-side ADB processes.')
  kill_adb()

  logging.debug('Running %s on devices: %s', args.name, args.devices or 'all')

  docker_client = containers.DockerClient()
  if not docker_client.ping():
    logging.error('Docker engine unresponsive. Quitting early.')
    return 1
  android_devices = usb_device.get_android_devices(args.devices)

  args.func(docker_client, android_devices, args)

  return 0
    def test_delete_stopped_containers(self, mock_from_env):
        mock_from_env.return_value = self.fake_client

        containers.DockerClient().delete_stopped_containers()
        self.assertTrue(
            all(c.was_deleted for c in self.fake_client.containers.list()))
    def test_get_missing_container(self, mock_from_env):
        mock_from_env.return_value = self.fake_client
        fake_device = FakeDevice('missing_device', 1)

        container = containers.DockerClient().get_container(fake_device)
        self.assertEqual(container, None)
    def test_get_container(self, mock_from_env):
        mock_from_env.return_value = self.fake_client
        fake_device = FakeDevice('serial2', 2)

        container = containers.DockerClient().get_container(fake_device)
        self.assertEqual(container.name, 'android_serial2')
    def test_get_running_containers(self, mock_from_env):
        mock_from_env.return_value = self.fake_client

        running_containers = containers.DockerClient().get_running_containers()
        self.assertEqual(set(c.name for c in running_containers),
                         set(self.container_names))
    def test_pull_not_logged_in(self, mock_from_env):
        mock_from_env.return_value = self.fake_client

        client = containers.DockerClient()
        client.logged_in = False
        self.assertRaises(Exception, client.pull, 'image1')