def InstallGoogleCloudSdk():
  # TODO: There's a google-cloud-sdk in AUR which should be used
  # but it's not optimal for cloud use. The image is too large.
  utils.LogStep('Install Google Cloud SDK')
  usr_share_google = '/usr/share/google'
  archive = os.path.join(usr_share_google, 'google-cloud-sdk.zip')
  unzip_dir = os.path.join(usr_share_google, 'google-cloud-sdk')
  utils.CreateDirectory(usr_share_google)
  utils.DownloadFile(
      'https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.zip', archive)
  utils.Run(['unzip', archive, '-d', usr_share_google])
  utils.AppendFile('/etc/bash.bashrc',
                   'export CLOUDSDK_PYTHON=/usr/bin/python2')
  utils.Run([os.path.join(unzip_dir, 'install.sh'),
             '--usage-reporting', 'false',
             '--bash-completion', 'true',
             '--disable-installation-options',
             '--rc-path', '/etc/bash.bashrc',
             '--path-update', 'true'],
            cwd=unzip_dir,
            env={'CLOUDSDK_PYTHON': '/usr/bin/python2'})
  utils.Symlink(os.path.join(unzip_dir, 'bin/gcloud'), '/usr/bin/gcloud')
  utils.Symlink(os.path.join(unzip_dir, 'bin/gcutil'), '/usr/bin/gcutil')
  utils.Symlink(os.path.join(unzip_dir, 'bin/gsutil'), '/usr/bin/gsutil')
  utils.SecureDeleteFile(archive)
def main():
  image = utils.GetMetadataAttribute('image', raise_on_not_found=True)
  package = utils.GetMetadataAttribute('gcs_package_path',
                                       raise_on_not_found=True)
  package_name = package.split('/')[-1]

  mount_disk = get_mount_disk(image)
  logging.info('Mount device %s at /mnt', mount_disk)
  run(f'mount {mount_disk} /mnt')

  # The rpm utility requires /dev/random to initialize GnuTLS
  logging.info('Mount dev filesystem in chroot')
  run('mount -o bind /dev /mnt/dev')

  utils.DownloadFile(package, f'/mnt/tmp/{package_name}')

  distribution = get_distro_from_image(image)
  if distribution == 'debian':
    util = 'apt-get'
  elif distribution == 'enterprise_linux':
    util = 'yum'
  else:
    logging.error('Unknown Linux distribution.')
    return

  logging.info('Installing package %s', package_name)
  run(f'chroot /mnt {util} install -y /tmp/{package_name}')

  # Best effort to unmount prior to shutdown.
  run('sync', check=False)
  run('umount /mnt/dev', check=False)
  run('umount /mnt', check=False)

  logging.success('Package %s installed successfully', package_name)
def main():
  image = utils.GetMetadataAttribute('image', raise_on_not_found=True)
  package = utils.GetMetadataAttribute('gcs_package_path',
                                       raise_on_not_found=True)
  package_name = package.split('/')[-1]

  mount_disk = get_mount_disk(image)
  logging.info('Mount device %s at /mnt', mount_disk)
  run(f'mount {mount_disk} /mnt')

  # The rpm utility requires /dev/random to initialize GnuTLS
  logging.info('Mount dev filesystem in chroot')
  run('mount -o bind /dev /mnt/dev')

  utils.DownloadFile(package, f'/mnt/tmp/{package_name}')

  distribution = get_distro_from_image(image)
  if distribution == 'debian':
    util = 'apt-get'
  elif distribution == 'enterprise_linux':
    util = 'yum'
  else:
    logging.error('Unknown Linux distribution.')
    return

  logging.info('Installing package %s', package_name)
  run(f'chroot /mnt {util} install -y /tmp/{package_name}')
  if distribution == 'enterprise_linux':
    # (google-guest-agent)-20210723.01
    m = re.search(r'(.+)-[0-9]{8}\.[0-9]{2}.*', package_name)
    if not m:
      logging.error('unknown package name, cant relabel')
      return
    package_short_name = m.group(1)

    out = run(f'chroot /mnt rpm -ql {package_short_name}')
    with open('/mnt/tmp/relabel', 'w') as fp:
      fp.write(out.stdout)
    run('chroot /mnt /sbin/setfiles -v -F -f /tmp/relabel '
        '/etc/selinux/targeted/contexts/files/file_contexts')

  # Best effort to unmount prior to shutdown.
  run('sync', check=False)
  run('umount /mnt/dev', check=False)
  run('umount /mnt', check=False)

  logging.success('Package %s installed successfully', package_name)
def DownloadArchBootstrap(bootstrap_tarball):
    utils.LogStep('Download Arch Linux Bootstrap')
    if bootstrap_tarball:
        url = bootstrap_tarball
        sha1sum = None
    else:
        url, sha1sum = GetLatestBootstrapUrl()
    logging.debug('Downloading %s', url)
    local_bootstrap = os.path.join(os.getcwd(), os.path.basename(url))
    if os.path.isfile(local_bootstrap):
        logging.debug('Using local file instead.')
        if sha1sum and utils.Sha1Sum(local_bootstrap) == sha1sum:
            return local_bootstrap
    utils.DownloadFile(url, local_bootstrap)
    if not sha1sum or utils.Sha1Sum(local_bootstrap) != sha1sum:
        raise ValueError('Bad checksum')
    return local_bootstrap