def install_cloud_sdk(g: guestfs.GuestFS, ubuntu_release: str) -> None: """ Installs Google Cloud SDK, supporting apt and snap. Args: g: A mounted GuestFS instance. ubuntu_release: The release nickname (eg: trusty). """ try: g.sh('gcloud --version') logging.info( 'Found gcloud. Skipping installation of Google Cloud SDK.') return except RuntimeError: logging.info('Did not find previous install of gcloud.') if g.gcp_image_major >= '18': # Starting at 18.04, the ubuntu-os-cloud images install the sdk # using snap. Running `snap install` directly is not an option # here since it requires the snapd daemon to be running on the guest. g.write('/etc/cloud/cloud.cfg.d/91-google-cloud-sdk.cfg', cloud_init_cloud_sdk) logging.info( 'Google Cloud SDK will be installed using snap with cloud-init.') else: g.write('/etc/apt/sources.list.d/partner.list', apt_cloud_sdk.format(ubuntu_release=ubuntu_release)) utils.update_apt(g) utils.install_apt_packages(g, 'google-cloud-sdk') logging.info('Installed Google Cloud SDK with apt.')
def DistroSpecific(g): install_gce = utils.GetMetadataAttribute('install_gce_packages') deb_release = utils.GetMetadataAttribute('debian_release') if install_gce == 'true': logging.info('Installing GCE packages.') utils.update_apt(g) utils.install_apt_packages(g, 'gnupg') g.command( ['wget', 'https://packages.cloud.google.com/apt/doc/apt-key.gpg', '-O', '/tmp/gce_key']) g.command(['apt-key', 'add', '/tmp/gce_key']) g.rm('/tmp/gce_key') g.write( '/etc/apt/sources.list.d/google-cloud.list', google_cloud.format(deb_release=deb_release)) # Remove Azure agent. try: g.command(['apt-get', 'remove', '-y', '-f', 'waagent', 'walinuxagent']) except Exception as e: logging.debug(str(e)) logging.warn('Could not uninstall Azure agent. Continuing anyway.') utils.update_apt(g) pkgs = ['google-cloud-packages-archive-keyring', 'google-compute-engine'] # Debian 8 differences: # 1. No NGE # 2. No Cloud SDK, since it requires Python 3.5+. # 3. No OS config agent. if deb_release == 'jessie': # Debian 8 doesn't support the new guest agent, so we need to install # the legacy Python version. pkgs += ['python-google-compute-engine', 'python3-google-compute-engine'] logging.info('Skipping installation of OS Config agent. ' 'Requires Debian 9 or newer.') else: pkgs += ['google-cloud-sdk', 'google-osconfig-agent'] utils.install_apt_packages(g, *pkgs) # Update grub config to log to console. g.command( ['sed', '-i""', r'/GRUB_CMDLINE_LINUX/s#"$# console=ttyS0,38400n8"#', '/etc/default/grub']) # Disable predictive network interface naming in Stretch. if deb_release == 'stretch': g.command( ['sed', '-i', r's#^\(GRUB_CMDLINE_LINUX=".*\)"$#\1 net.ifnames=0 biosdevname=0"#', '/etc/default/grub']) g.command(['update-grub2']) # Reset network for DHCP. logging.info('Resetting network to DHCP for eth0.') g.write('/etc/network/interfaces', interfaces)
def install_cloud_sdk(g: guestfs.GuestFS, ubuntu_release: str) -> None: """ Installs Google Cloud SDK, supporting apt and snap. Args: g: A mounted GuestFS instance. ubuntu_release: The release nickname (eg: trusty). """ try: run(g, 'gcloud --version') logging.info( 'Found gcloud. Skipping installation of Google Cloud SDK.') return except RuntimeError: logging.info('Did not find previous install of gcloud.') if g.gcp_image_major < '18': g.write('/etc/apt/sources.list.d/partner.list', apt_cloud_sdk.format(ubuntu_release=ubuntu_release)) utils.update_apt(g) utils.install_apt_packages(g, 'google-cloud-sdk') logging.info('Installed Google Cloud SDK with apt.') return # Starting at 18.04, Canonical installs the sdk using snap. # Running `snap install` directly is not an option here since it # requires the snapd daemon to be running on the guest. g.write('/etc/cloud/cloud.cfg.d/91-google-cloud-sdk.cfg', cloud_init_cloud_sdk) logging.info( 'Google Cloud SDK will be installed using snap with cloud-init.') # Include /snap/bin in the PATH for startup and shutdown scripts. # This was present in the old guest agent, but lost in the new guest # agent. for p in [ '/lib/systemd/system/google-shutdown-scripts.service', '/lib/systemd/system/google-startup-scripts.service' ]: logging.debug('[%s] Checking whether /bin/snap is on PATH.', p) if not g.exists(p): logging.debug('[%s] Skipping: Unit not found.', p) continue original_unit = g.cat(p) # Check whether the PATH is already set; if so, skip patching to avoid # overwriting existing directive. match = re.search('Environment=[\'"]?PATH.*', original_unit, flags=re.IGNORECASE) if match: logging.debug( '[%s] Skipping: PATH already defined in unit file: %s.', p, match.group()) continue # Add Environment directive to unit file, and show diff in debug log. patched_unit = original_unit.replace('[Service]', snap_env_directive) g.write(p, patched_unit) diff = '\n'.join(Differ().compare(original_unit.splitlines(), patched_unit.splitlines())) logging.debug('[%s] PATH not defined. Added:\n%s', p, diff)
def DistroSpecific(g): ubuntu_release = utils.GetMetadataAttribute('ubuntu_release') install_gce = utils.GetMetadataAttribute('install_gce_packages') # If present, remove any hard coded DNS settings in resolvconf. # This is a common workaround to include permanent changes: # https://askubuntu.com/questions/157154 if g.exists('/etc/resolvconf/resolv.conf.d/base'): logging.info('Resetting resolvconf base.') run(g, 'echo "" > /etc/resolvconf/resolv.conf.d/base') # Reset the network to DHCP. if ubuntu_release == 'trusty': g.write('/etc/network/interfaces', network_trusty) elif ubuntu_release == 'xenial': g.write('/etc/network/interfaces', network_xenial) elif g.is_dir('/etc/netplan'): run(g, 'rm -f /etc/netplan/*.yaml') g.write('/etc/netplan/config.yaml', network_netplan) run(g, 'netplan apply') if install_gce == 'true': utils.update_apt(g) logging.info('Installing cloud-init.') utils.install_apt_packages(g, 'cloud-init') # Ubuntu 14.04's version of cloud-init doesn't have `clean`. if g.gcp_image_major > '14': run(g, 'cloud-init clean') # Remove cloud-init configs that may conflict with GCE's. # # - subiquity disables automatic network configuration # https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1871975 for cfg in [ 'azure', 'curtin', 'waagent', 'walinuxagent', 'aws', 'amazon', 'subiquity' ]: run(g, 'rm -f /etc/cloud/cloud.cfg.d/*%s*' % cfg) remove_azure_agents(g) g.write('/etc/cloud/cloud.cfg.d/91-gce-system.cfg', cloud_init_repos) if g.gcp_image_major > '14': install_osconfig_agent(g) utils.install_apt_packages(g, 'gce-compute-image-packages') install_cloud_sdk(g, ubuntu_release) # Update grub config to log to console. run(g, [ 'sed', '-i', r's#^\(GRUB_CMDLINE_LINUX=".*\)"$#\1 console=ttyS0,38400n8"#', '/etc/default/grub' ]) run(g, ['update-grub2'])
def DistroSpecific(g): install_gce = utils.GetMetadataAttribute('install_gce_packages') deb_release = utils.GetMetadataAttribute('debian_release') if install_gce == 'true': logging.info('Installing GCE packages.') utils.update_apt(g) utils.install_apt_package(g, 'gnupg') g.command([ 'wget', 'https://packages.cloud.google.com/apt/doc/apt-key.gpg', '-O', '/tmp/gce_key' ]) g.command(['apt-key', 'add', '/tmp/gce_key']) g.rm('/tmp/gce_key') g.write('/etc/apt/sources.list.d/google-cloud.list', google_cloud.format(deb_release=deb_release)) # Remove Azure agent. try: g.command( ['apt-get', 'remove', '-y', '-f', 'waagent', 'walinuxagent']) except Exception as e: logging.debug(str(e)) logging.warn('Could not uninstall Azure agent. Continuing anyway.') utils.update_apt(g) utils.install_apt_package(g, 'google-cloud-packages-archive-keyring') utils.install_apt_package(g, 'google-cloud-sdk') utils.install_apt_package(g, 'google-compute-engine') utils.install_apt_package(g, 'python-google-compute-engine') utils.install_apt_package(g, 'python3-google-compute-engine') # Update grub config to log to console. g.command([ 'sed', '-i""', r'/GRUB_CMDLINE_LINUX/s#"$# console=ttyS0,38400n8"#', '/etc/default/grub' ]) # Disable predictive network interface naming in Stretch. if deb_release == 'stretch': g.command([ 'sed', '-i', r's#^\(GRUB_CMDLINE_LINUX=".*\)"$#\1 net.ifnames=0 biosdevname=0"#', '/etc/default/grub' ]) g.command(['update-grub2']) # Reset network for DHCP. logging.info('Resetting network to DHCP for eth0.') g.write('/etc/network/interfaces', interfaces)
def DistroSpecific(g): ubuntu_release = utils.GetMetadataAttribute('ubuntu_release') install_gce = utils.GetMetadataAttribute('install_gce_packages') # If present, remove any hard coded DNS settings in resolvconf. # This is a common workaround to include permanent changes: # https://askubuntu.com/questions/157154 if g.exists('/etc/resolvconf/resolv.conf.d/base'): logging.info('Resetting resolvconf base.') run(g, 'echo "" > /etc/resolvconf/resolv.conf.d/base') # Reset the network to DHCP. if ubuntu_release == 'trusty': g.write('/etc/network/interfaces', network_trusty) elif ubuntu_release == 'xenial': g.write('/etc/network/interfaces', network_xenial) elif g.is_dir('/etc/netplan'): run(g, 'rm -f /etc/netplan/*.yaml') g.write('/etc/netplan/config.yaml', network_netplan) run(g, 'netplan apply') if install_gce == 'true': utils.update_apt(g) setup_cloud_init(g) remove_azure_agents(g) if g.gcp_image_major > '14': install_osconfig_agent(g) utils.install_apt_packages(g, 'gce-compute-image-packages') install_cloud_sdk(g, ubuntu_release) # Update grub config to log to console. run(g, [ 'sed', '-i', r's#^\(GRUB_CMDLINE_LINUX=".*\)"$#\1 console=ttyS0,38400n8"#', '/etc/default/grub' ]) run(g, ['update-grub2'])
def DistroSpecific(g): ubu_release = utils.GetMetadataAttribute('ubuntu_release') install_gce = utils.GetMetadataAttribute('install_gce_packages') # Remove any hard coded DNS settings in resolvconf. if ubu_release != 'bionic': logging.info('Resetting resolvconf base.') g.sh('echo "" > /etc/resolvconf/resolv.conf.d/base') # Try to reset the network to DHCP. if ubu_release == 'trusty': g.write('/etc/network/interfaces', trusty_network) elif ubu_release == 'xenial': g.write('/etc/network/interfaces', xenial_network) if install_gce == 'true': utils.update_apt(g) logging.info('Installing cloud-init.') utils.install_apt_package(g, 'cloud-init') # Try to remove azure or aws configs so cloud-init has a chance. g.sh('rm -f /etc/cloud/cloud.cfg.d/*azure*') g.sh('rm -f /etc/cloud/cloud.cfg.d/*curtin*') g.sh('rm -f /etc/cloud/cloud.cfg.d/*waagent*') g.sh('rm -f /etc/cloud/cloud.cfg.d/*walinuxagent*') g.sh('rm -f /etc/cloud/cloud.cfg.d/*aws*') g.sh('rm -f /etc/cloud/cloud.cfg.d/*amazon*') if ubu_release == 'bionic': g.sh('rm -f /etc/netplan/*') logging.debug(g.sh('cloud-init clean')) remove_azure_agents(g) g.write('/etc/apt/sources.list.d/partner.list', partner_list.format(ubu_release=ubu_release)) g.write('/etc/cloud/cloud.cfg.d/91-gce-system.cfg', gce_system) # Use host machine as http proxy so cloud-init can access GCE API with open('/etc/tinyproxy/tinyproxy.conf', 'w') as cfg: cfg.write(tinyproxy_cfg) utils.Execute(['/etc/init.d/tinyproxy', 'restart']) default_gw = g.sh("ip route | awk '/default/ { printf $3 }'") try: logging.debug( g.sh('http_proxy="http://%s:8888" cloud-init -d init' % default_gw)) except Exception as e: logging.debug('Failed to run cloud-init. Details: {}.'.format(e)) raise RuntimeError( 'Failed to run cloud-init. Connect to a shell in the original VM ' 'and ensure that the following command executes successfully: ' 'apt-get install -y --no-install-recommends cloud-init ' '&& cloud-init -d init') logging.info('Installing GCE packages.') utils.update_apt(g) utils.install_apt_package(g, 'gce-compute-image-packages') utils.install_apt_package(g, 'google-cloud-sdk') # Update grub config to log to console. g.command([ 'sed', '-i', r's#^\(GRUB_CMDLINE_LINUX=".*\)"$#\1 console=ttyS0,38400n8"#', '/etc/default/grub' ]) g.command(['update-grub2'])