]>
git.proxmox.com Git - pve-guest-common.git/blob - PVE/ReplicationConfig.pm
1 package PVE
:: ReplicationConfig
;
8 use PVE
:: JSONSchema
qw(get_standard_option) ;
10 use PVE
:: SectionConfig
;
11 use PVE
:: CalendarEvent
;
13 use PVE
:: Cluster
qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file) ;
15 use base
qw(PVE::SectionConfig) ;
17 my $replication_cfg_filename = 'replication.cfg' ;
19 cfs_register_file
( $replication_cfg_filename,
20 sub { __PACKAGE__-
> parse_config ( @_ ); },
21 sub { __PACKAGE__-
> write_config ( @_ ); });
23 PVE
:: JSONSchema
:: register_standard_option
( 'pve-replication-id' , {
24 description
=> "Replication Job ID." ,
26 pattern
=> '[1-9][0-9]{2,8}-\d{1,9}' ,
31 type
=> { description
=> "Section type." },
32 id
=> get_standard_option
( 'pve-replication-id' ),
34 description
=> "Flag to disable/deactivate the entry." ,
39 description
=> "Description." ,
45 description
=> "Mark the replication job for removal. The job will remove all local replication snapshots. When set to 'full', it also tries to remove replicated volumes on the target. The job then removes itself from the configuration file." ,
47 enum
=> [ 'local' , 'full' ],
50 guest
=> get_standard_option
( 'pve-vmid' , {
52 completion
=> \
& PVE
:: Cluster
:: complete_vmid
}),
54 description
=> "Rate limit in mbps (megabytes per second) as floating point number." ,
60 description
=> "Storage replication schedule. The format is a subset of `systemd` calender events." ,
61 type
=> 'string' , format
=> 'pve-calendar-event' ,
73 sub parse_section_header
{
74 my ( $class, $line ) = @_ ;
76 if ( $line =~ m/^(\S+):\s*(\d+)-(\d+)\s*$/ ) {
77 my ( $type, $guest, $subid ) = ( lc ( $1 ), int ( $2 ), int ( $3 ));
78 my $id = " $guest - $subid " ; # use parsed integers
79 my $errmsg = undef ; # set if you want to skip whole section
81 die "invalid replication job id ' $id ' \n " if $subid < 1 ;
82 PVE
:: JSONSchema
:: pve_verify_vmid
( $guest );
85 my $config = { guest
=> $guest };
86 return ( $type, $id, $errmsg, $config );
91 # Note: We want only one replication job per target to
92 # avoid confusion. This method should return a string
93 # which uniquely identifies the target.
94 sub get_unique_target_id
{
95 my ( $class, $data ) = @_ ;
97 die "please overwrite in subclass" ;
101 my ( $class, $filename, $raw ) = @_ ;
103 my $cfg = $class -> SUPER :: parse_config
( $filename, $raw );
105 my $target_hash = {};
107 foreach my $id ( sort keys %{ $cfg ->{ ids
}}) {
108 my $data = $cfg ->{ ids
}->{ $id };
110 $data ->{ comment
} = PVE
:: Tools
:: decode_text
( $data ->{ comment
})
111 if defined ( $data ->{ comment
});
113 my $plugin = $class -> lookup ( $data ->{ type
});
114 my $tid = $plugin -> get_unique_target_id ( $data );
115 my $vmid = $data ->{ guest
};
117 # should not happen, but we want to be sure
118 if ( defined ( $target_hash ->{ $vmid }->{ $tid })) {
119 warn "delete job $id : replication job for guest ' $vmid ' to target ' $tid ' already exists \n " ;
120 delete $cfg ->{ ids
}->{ $id };
122 $target_hash ->{ $vmid }->{ $tid } = 1 ;
129 my ( $class, $filename, $cfg ) = @_ ;
131 my $target_hash = {};
133 foreach my $id ( keys %{ $cfg ->{ ids
}}) {
134 my $data = $cfg ->{ ids
}->{ $id };
136 my $plugin = $class -> lookup ( $data ->{ type
});
137 my $tid = $plugin -> get_unique_target_id ( $data );
138 my $vmid = $data ->{ guest
};
140 die "replication job for guest ' $vmid ' to target ' $tid ' already exists \n "
141 if defined ( $target_hash ->{ $vmid }->{ $tid });
142 $target_hash ->{ $vmid }->{ $tid } = 1 ;
144 $data ->{ comment
} = PVE
:: Tools
:: encode_text
( $data ->{ comment
})
145 if defined ( $data ->{ comment
});
148 $class -> SUPER :: write_config
( $filename, $cfg );
154 my $class = ref ( $type ) || $type ;
156 my $cfg = cfs_read_file
( $replication_cfg_filename );
158 return bless $cfg, $class ;
164 cfs_write_file
( $replication_cfg_filename, $cfg );
168 my ( $code, $errmsg ) = @_ ;
170 cfs_lock_file
( $replication_cfg_filename, undef , $code );
173 $errmsg ?
die " $errmsg : $err " : die $err ;
177 sub check_for_existing_jobs
{
178 my ( $cfg, $vmid, $noerr ) = @_ ;
180 foreach my $id ( keys %{ $cfg ->{ ids
}}) {
181 my $data = $cfg ->{ ids
}->{ $id };
183 if ( $data ->{ guest
} == $vmid ) {
185 die "There is a replication job ' $id ' for guest ' $vmid ' - " .
186 "Please remove that first. \n "
193 package PVE
:: ReplicationConfig
:: Cluster
;
195 use base
qw(PVE::ReplicationConfig) ;
204 description
=> "Target node." ,
205 type
=> 'string' , format
=> 'pve-node' ,
212 guest
=> { fixed
=> 1 , optional
=> 0 },
213 target
=> { fixed
=> 1 , optional
=> 0 },
214 disable
=> { optional
=> 1 },
215 comment
=> { optional
=> 1 },
216 rate
=> { optional
=> 1 },
217 schedule
=> { optional
=> 1 },
218 remove_job
=> { optional
=> 1 },
222 sub get_unique_target_id
{
223 my ( $class, $data ) = @_ ;
225 return "local/ $data ->{target}" ;
228 PVE
:: ReplicationConfig
:: Cluster-
> register ();
229 PVE
:: ReplicationConfig-
> init ();