Class: Snapsync::LocalTarget

Inherits:
Object
  • Object
show all
Defined in:
lib/snapsync/local_target.rb

Defined Under Namespace

Classes: InvalidTargetPath, InvalidUUIDError, NoUUIDError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir, create_if_needed: true) ⇒ LocalTarget

Returns a new instance of LocalTarget.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/snapsync/local_target.rb', line 41

def initialize(dir, create_if_needed: true)
    if !dir.directory?
        raise ArgumentError, "#{dir} does not exist"
    end
    @dir = dir

    begin
        read_config
    rescue NoUUIDError
        if !create_if_needed
            raise
        end
        @uuid = SecureRandom.uuid
        @sync_policy = DefaultSyncPolicy.new
        @cleanup = nil
        @enabled = true
        @autoclean = true
    end
    write_config
end

Instance Attribute Details

#cleanupObject (readonly)

The cleanup object



15
16
17
# File 'lib/snapsync/local_target.rb', line 15

def cleanup
  @cleanup
end

#dirObject (readonly)

This target’s directory



9
10
11
# File 'lib/snapsync/local_target.rb', line 9

def dir
  @dir
end

#sync_policyObject (readonly)

The target sync policy



12
13
14
# File 'lib/snapsync/local_target.rb', line 12

def sync_policy
  @sync_policy
end

#uuidString (readonly)

The target’s UUID

Returns:

  • (String)


6
7
8
# File 'lib/snapsync/local_target.rb', line 6

def uuid
  @uuid
end

Class Method Details

.parse_policy(type, options) ⇒ (#filter_snapshots,#filter_snapshots)

Parse a policy specification as provided on the command line or saved in the config file into sync and cleanup policy objects

Parameters:

  • type (String)

    the policy type, either default, timeline or last

  • options (Array<String>)

    to be passed to the #from_config method on the underlying policy classes

Returns:

  • ((#filter_snapshots,#filter_snapshots))

    the sync policy and the cleanup policy. The cleanup policy might be nil

Raises:

See Also:



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/snapsync/local_target.rb', line 135

def self.parse_policy(type, options)
    case type
    when 'default'
        sync_policy = DefaultSyncPolicy
        cleanup     = nil
    when 'timeline'
        sync_policy = TimelineSyncPolicy
        cleanup     = TimelineSyncPolicy
    when 'last'
        sync_policy = SyncLastPolicy
        cleanup     = SyncLastPolicy
    else
        raise InvalidConfiguration, "synchronization policy '#{type}' does not exist"
    end
    sync_policy = sync_policy.from_config(options)
    cleanup =
        if cleanup
            Cleanup.new(cleanup.from_config(options))
        end
    return sync_policy, cleanup
end

.valid_policy?(type, options) ⇒ Boolean

Verifies that the given policy type and options are valid

Returns:

  • (Boolean)


158
159
160
161
162
163
# File 'lib/snapsync/local_target.rb', line 158

def self.valid_policy?(type, options)
    parse_policy(type, options)
    true
rescue InvalidConfiguration
    false
end

Instance Method Details

#autoclean?Boolean

Whether the target should be autocleaned on synchronization

Defaults to true

Returns:

  • (Boolean)


31
# File 'lib/snapsync/local_target.rb', line 31

def autoclean?; !!@autoclean end

#change_policy(type, options) ⇒ Object



165
166
167
168
# File 'lib/snapsync/local_target.rb', line 165

def change_policy(type, options)
    @sync_policy, @cleanup =
        self.class.parse_policy(type, options)
end

#config_pathPathname

Path to the target’s configuration file

Returns:

  • (Pathname)


120
121
122
# File 'lib/snapsync/local_target.rb', line 120

def config_path
    dir + "snapsync.config"
end

#delete(s, dry_run: false) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/snapsync/local_target.rb', line 170

def delete(s, dry_run: false)
    Snapsync.info "Removing snapshot #{s.num} #{s.date.to_time} at #{s.subvolume_dir}"
    return if dry_run

    begin
        Btrfs.run("subvolume", "delete", '--commit-each', s.subvolume_dir.to_s)
    rescue Btrfs::Error
        Snapsync.warn "failed to remove snapshot at #{s.subvolume_dir}, keeping the rest of the snapshot"
        return
    end

    Snapsync.info "Flushing data to disk"
    begin
        Btrfs.run("subvolume", "sync", self.dir.to_s)
    rescue Btrfs::Error
    end

    s.snapshot_dir.rmtree
end

#descriptionObject



37
38
39
# File 'lib/snapsync/local_target.rb', line 37

def description
    "local:#{dir}"
end

#disableObject

Disable this target, i.e. remove it from the auto synchronization and cleanup commands



26
# File 'lib/snapsync/local_target.rb', line 26

def disable; @enabled = false; self end

#each_snapshot(&block) ⇒ Object



65
66
67
# File 'lib/snapsync/local_target.rb', line 65

def each_snapshot(&block)
    Snapshot.each(dir, &block)
end

#each_snapshot_raw(&block) ⇒ Object



62
63
64
# File 'lib/snapsync/local_target.rb', line 62

def each_snapshot_raw(&block)
    Snapshot.each_snapshot_raw(dir, &block)
end

#enableObject

Enable this target, i.e. add it to the auto synchronization and cleanup commands



22
# File 'lib/snapsync/local_target.rb', line 22

def enable; @enabled = true; self end

#enabled?Boolean

Whether this target is enabled or not

Returns:

  • (Boolean)


18
# File 'lib/snapsync/local_target.rb', line 18

def enabled?; @enabled end

#parse_config(config) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/snapsync/local_target.rb', line 99

def parse_config(config)
    uuid = config['uuid']
    if uuid.length != 36
        raise InvalidUUIDError, "uuid in #{uuid_path} was expected to be 36 characters long, but is #{uuid.length}"
    end
    @uuid = uuid

    @enabled = config.fetch('enabled', true)
    @autoclean = config.fetch('autoclean', true)

    if policy_config = config['policy']
        change_policy(policy_config['type'], policy_config['options'] || Array.new)
    else
        @sync_policy = DefaultSyncPolicy.new
        @cleanup = nil
    end
end

#read_configObject



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/snapsync/local_target.rb', line 87

def read_config
    begin
        if !(raw_config = YAML.load(config_path.read))
            raise NoUUIDError, "empty configuration file found in #{config_path}"
        end

    rescue Errno::ENOENT => e
        raise NoUUIDError, e.message, e.backtrace
    end
    parse_config(raw_config)
end

#write_configObject



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/snapsync/local_target.rb', line 69

def write_config
    config = Hash['uuid' => uuid, 'policy' => Hash.new]
    config['policy']['type'] =
        case sync_policy
        when TimelineSyncPolicy then 'timeline'
        when SyncLastPolicy then 'last'
        when DefaultSyncPolicy then 'default'
        end
    config['policy']['options'] =
        sync_policy.to_config
    config['enabled'] = enabled?
    config['autoclean'] = autoclean?

    config_path.open('w') do |io|
        YAML.dump(config, io)
    end
end