From abfa1a7712040ce26dfea049adddca723a9f63d6 Mon Sep 17 00:00:00 2001 From: Naveenraj M <22456988+naveenrajm7@users.noreply.github.com> Date: Wed, 4 Dec 2024 15:12:13 -0700 Subject: [PATCH 1/4] notes: update release steps --- notes/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/notes/README.md b/notes/README.md index 48ec13b..6af5641 100644 --- a/notes/README.md +++ b/notes/README.md @@ -21,10 +21,12 @@ To release To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` GitHub action upon tag push with "v*" will publish gem to GHR and rubygems -1. Update the version number in `version.rb` -2. Run `bundle exec rake release` -3. Commit version and Gemlock file -4. Run `bundle exec rake release` again -5. Cancel push to rubygems.org +1. Update + CHANGELOG.md + version number in `version.rb` + version number Gemlock file +2. Commit +3. Run `bundle exec rake release` (Commit and tags are pushed) +4. Cancel push to rubygems.org GHA will publish gems to GHR and rubygems \ No newline at end of file From 1e0e0c2132adf3bc993ac23449ed605a1bceeede Mon Sep 17 00:00:00 2001 From: Naveenraj M <22456988+naveenrajm7@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:50:07 -0700 Subject: [PATCH 2/4] nfs: add initial support for nfs sync folder --- lib/vagrant_utm/action.rb | 24 +++++- .../action/prepare_nfs_settings.rb | 79 +++++++++++++++++++ .../action/prepare_nfs_valid_ids.rb | 24 ++++++ 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 lib/vagrant_utm/action/prepare_nfs_settings.rb create mode 100644 lib/vagrant_utm/action/prepare_nfs_valid_ids.rb diff --git a/lib/vagrant_utm/action.rb b/lib/vagrant_utm/action.rb index 8d29466..8ffdad5 100644 --- a/lib/vagrant_utm/action.rb +++ b/lib/vagrant_utm/action.rb @@ -40,6 +40,8 @@ module Action # rubocop:disable Metrics/ModuleLength autoload :PackageSetupFiles, action_root.join("package_setup_files") autoload :PackageSetupFolders, action_root.join("package_setup_folders") autoload :PackageVagrantfile, action_root.join("package_vagrantfile") + autoload :PrepareNFSSettings, action_root.join("prepare_nfs_settings") + autoload :PrepareNFSValidIds, action_root.join("prepare_nfs_valid_ids") autoload :PrepareForwardedPortCollisionParams, action_root.join("prepare_forwarded_port_collision_params") autoload :Resume, action_root.join("resume") autoload :SetId, action_root.join("set_id") @@ -66,6 +68,10 @@ def self.action_boot # rubocop:disable Metrics/AbcSize b.use EnvSet, port_collision_repair: true b.use PrepareForwardedPortCollisionParams b.use HandleForwardedPortCollisions + b.use PrepareNFSValidIds + b.use SyncedFolderCleanup + b.use SyncedFolders + b.use PrepareNFSSettings b.use ForwardPorts b.use SetHostname b.use Customize, "pre-boot" @@ -90,7 +96,7 @@ def self.action_boot # rubocop:disable Metrics/AbcSize # This is the action that is primarily responsible for completely # freeing the resources of the underlying virtual machine. # UTM equivalent of `utmctl delete ` - def self.action_destroy + def self.action_destroy # rubocop:disable Metrics/AbcSize Vagrant::Action::Builder.new.tap do |b| b.use CheckUtm b.use Call, Created do |env1, b2| @@ -106,6 +112,8 @@ def self.action_destroy b3.use CheckAccessible b3.use action_halt b3.use Destroy + b3.use PrepareNFSValidIds + b3.use SyncedFolderCleanup else b3.use MessageWillNotDestroy end @@ -160,7 +168,7 @@ def self.action_ip_address end # This action packages the virtual machine into a single box file. - def self.action_package + def self.action_package # rubocop:disable Metrics/AbcSize Vagrant::Action::Builder.new.tap do |b| b.use CheckUtm b.use Call, Created do |env, b2| @@ -174,6 +182,8 @@ def self.action_package b2.use CheckAccessible b2.use action_halt b2.use ClearForwardedPorts + b2.use PrepareNFSValidIds + b2.use SyncedFolderCleanup b2.use Package b2.use Export b2.use PackageVagrantfile @@ -405,6 +415,16 @@ def self.action_suspend end end + # This is the action that is called to sync folders to a running + # machine without a reboot. + def self.action_sync_folders + Vagrant::Action::Builder.new.tap do |b| + b.use PrepareNFSValidIds + b.use SyncedFolders + b.use PrepareNFSSettings + end + end + # This action brings the machine up from nothing, including importing # the box, configuring metadata, and booting. def self.action_up diff --git a/lib/vagrant_utm/action/prepare_nfs_settings.rb b/lib/vagrant_utm/action/prepare_nfs_settings.rb new file mode 100644 index 0000000..f75705d --- /dev/null +++ b/lib/vagrant_utm/action/prepare_nfs_settings.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +module VagrantPlugins + module Utm + module Action + # This action prepares the NFS settings for the machine. + class PrepareNFSSettings + include Vagrant::Action::Builtin::MixinSyncedFolders + include Vagrant::Util::Retryable + + def initialize(app, _env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::vm::nfs") + end + + def call(env) + @machine = env[:machine] + + @app.call(env) + + opts = { + cached: !env[:synced_folders_cached].nil?, + config: env[:synced_folders_config], + disable_usable_check: !env[:test].nil? + } + folders = synced_folders(env[:machine], **opts) + + return unless folders.key?(:nfs) + + @logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP") + add_ips_to_env!(env) + end + + # Extracts the proper host and guest IPs for NFS mounts and stores them + # in the environment for the SyncedFolder action to use them in + # mounting. + # + # The ! indicates that this method modifies its argument. + def add_ips_to_env!(env) + # Hardcoded IP for the host IP + host_ip = "10.0.2.2" + machine_ip = read_dynamic_machine_ip + + raise Vagrant::Errors::NFSNoHostonlyNetwork if !host_ip || !machine_ip + + env[:nfs_host_ip] = host_ip + env[:nfs_machine_ip] = machine_ip + end + + # Returns the IP address of the guest by looking at utm guest additions + # for the appropriate guest adapter. + # + # For DHCP interfaces, the guest property will not be present until the + # guest completes + # + # @param [Integer] adapter number to read IP for + # @return [String] ip address of adapter + def read_dynamic_machine_ip + # we need to wait for the guest's IP to show up as a guest property. + # retry thresholds are relatively high since we might need to wait + # for DHCP, but even static IPs can take a second or two to appear. + retryable(retry_options.merge(on: Vagrant::Errors::VirtualBoxGuestPropertyNotFound)) do + # Read the IP address from the list given by qemu-guest-agent + @machine.provider.driver.read_guest_ip[0] + end + rescue Vagrant::Errors::VirtualBoxGuestPropertyNotFound + # this error is more specific with a better error message directing + # the user towards the fact that it's probably a reportable bug + raise Vagrant::Errors::NFSNoGuestIP + end + + # Separating these out so we can stub out the sleep in tests + def retry_options + { tries: 15, sleep: 1 } + end + end + end + end +end diff --git a/lib/vagrant_utm/action/prepare_nfs_valid_ids.rb b/lib/vagrant_utm/action/prepare_nfs_valid_ids.rb new file mode 100644 index 0000000..6c1b844 --- /dev/null +++ b/lib/vagrant_utm/action/prepare_nfs_valid_ids.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +module VagrantPlugins + module Utm + module Action + # This action prepares the NFS valid IDs for the VMs. + # The ids that are valid and should not be pruned by NFS + class PrepareNFSValidIds + def initialize(app, _env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::vm::nfs") + end + + def call(env) + env[:nfs_valid_ids] = env[:machine].provider.driver.read_vms.keys + @app.call(env) + end + end + end + end +end From 64e55b95108bc3da92d310b93af01a4d0fea74e4 Mon Sep 17 00:00:00 2001 From: Naveenraj M <22456988+naveenrajm7@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:51:56 -0700 Subject: [PATCH 3/4] notes: update gems --- notes/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/notes/README.md b/notes/README.md index 6af5641..34298bc 100644 --- a/notes/README.md +++ b/notes/README.md @@ -29,4 +29,9 @@ GitHub action upon tag push with "v*" will publish gem to GHR and rubygems 3. Run `bundle exec rake release` (Commit and tags are pushed) 4. Cancel push to rubygems.org -GHA will publish gems to GHR and rubygems \ No newline at end of file +GHA will publish gems to GHR and rubygems + + +To update specific gems in the project + +`bundle update rubocop` \ No newline at end of file From f43982e101d63bf0d0a23c2469fc1d5771cbb7be Mon Sep 17 00:00:00 2001 From: Naveenraj M <22456988+naveenrajm7@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:11:27 -0700 Subject: [PATCH 4/4] update changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf06791..f9ad0f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## [Unreleased] + +WARNING: This version of the plugin adds initial synced folder support. By default, Vagrant will pick the directory share method which it supports and prefers. e.g., SMB. However, SMB is not fully tested, so you need to force the plugin to pick the one that is simple and tested `rsync` + +```ruby +Vagrant.configure("2") do |config| + config.vm.synced_folder ".", "/vagrant", type: "rsync" + config.vm.box = "utm/ubuntu-24.04" +end +``` + +### Added + +- Initial Synced Folder support with sync +- Warning: By default vagrant brings other sync methods eg: SMB, NFS but they are not ready to use. + ## [0.1.1] - 2024-12-03 IMPORTANT: This version of the plugin only works with UTM version 4.5.1 and above, and is incompatible with 0.0.1 version of the plugin.