source: ProjectBuilder/projects/casparbuster/devel/bin/cbusterize@ 1494

Last change on this file since 1494 was 1494, checked in by Bruno Cornec, 12 years ago
  • Add support for cbplugindirsandfiles. This param provides support for direstories and all their children, whereas cbplugindirs is restricted to the directory alone. Usefull for named support
  • Add named plugin
  • cbusterize wworks now mostly for named (access to root owned file is still aproblem to solve)
  • cb also supports the new cbplugindirsandfiles param
  • Property svn:executable set to *
File size: 9.8 KB
Line 
1#!/usr/bin/perl -w
2#
3=head1 NAME
4
5cbusterize - Creates the correct CasparBuster structure in your CMS environment
6
7=head1 SYNOPSIS
8
9cbusterize [options] --source /path/to/file/to/CasparBusterize
10
11 Options:
12 --debug |-d debug mode
13 --help |-h brief help message
14 --man full documentation
15 --force |-f force copy of files, even if they exist
16 --source |-s <file/dir> directory or files to copy in the CasparBuster tree (',' separated if many)
17 --plugin |-p <plugin name> plugin defining what to copy in the CasparBuster tree (',' separated if many)
18 --machine|-m <machine> machine to consider in the subtree
19
20=head1 OPTIONS
21
22=over 4
23
24=item B<--debug>
25
26Enter debug mode. This will print what would be done. No commands are executed,
27so this is safe to use when testing.
28
29=item B<--help>
30
31Print a brief help message and exits.
32
33=item B<--man>
34
35Prints the manual page and exits.
36
37=item B<--machine> I<machine name>
38
39Specify the machine to consider when dealing with the CasparBuster structure.
40The file will be taken from this machine, and a subdirectory named after the machine
41will be used under the basedir to host the directory structure to manage
42
43=item B<--source> I<path>
44
45Specify the path to the source file or directory to manage with CasparBuster. Multiple paths can be specified separated by ','.
46
47=item B<--plugin> I<name>
48
49Specify the name of the plugin to manage with CasparBuster. Multiple plugins can be specified separated by ','.
50A plugin defines a set of files (with their mode and owner), a set of directories (with their mode and owner) and a set of scripts to launch once the files are copied remotely.
51
52=back
53
54=head1 DESCRIPTION
55
56Creates a directory under the machine dir passed as parameter in working
57directory or directory passed as parameter named like the last path
58element of the parameter, and creates the standard CasparBuster setup
59that refers to the parameter path in the new directory, and configuration
60files when possible. It also copies the original config file into the new dir.
61Is reasonably picky about path names, tries to avoid common errors.
62
63Schema looks like:
64
65Base dir
66 |
67 |- machine1 (optional)
68 | |
69 | |-- conf dir1
70 | | |
71 | | |- conf file 1
72 | [...] [...]
73 |
74 |- machine2 (optional)
75 | |
76 | |-- conf dir2
77 | | |
78 | | |- conf file 2
79 | [...] [...]
80
81Use of machines require use of option -m (if using cbusemachines in cb.conf)
82If not, the conf dirs are directly attached to the base dir
83
84=head1 EXAMPLES
85
86 # this will create the appropriate CasparBuster environment
87 # under the base ~/prj/musique-ancienne.org directory (Cf cbbasedir in cb.conf)
88 # containing the directory victoria2 for this machine
89 # under which it will copy the required structure if needed (/etc/ssh)
90 # to finaly put a copy of the file sshd_conf in it from the victoria2 machine
91
92 cbusterize -m victoria2 -s /etc/ssh/sshd_config
93
94=head1 AUTHOR
95
96=over 4
97
98Bruno Cornec, http://brunocornec.wordpress.com
99
100=back
101
102=head1 LICENSE
103
104Copyright (C) 2012 Bruno Cornec <bruno@project-builder.org>
105Released under the GPLv2 or the Artistic license at your will.
106
107=cut
108use strict;
109use CasparBuster::Version;
110use CasparBuster::Env;
111use CasparBuster::Plugin;
112use File::Basename;
113use File::Path;
114use Getopt::Long;
115use Pod::Usage;
116use Data::Dumper;
117use Net::SSH2;
118use ProjectBuilder::Base;
119use ProjectBuilder::Conf;
120use ProjectBuilder::VCS;
121
122# settings
123my $debug = 0;
124my $help = undef;
125my $man = undef;
126my $source = undef;
127my $machine = undef;
128my $plugin = undef;
129my $quiet = undef;
130my $force = undef;
131my $log = undef;
132my $LOG = undef;
133
134my ($cbver,$cbrev) = cb_version_init();
135my $appname = "cb";
136$ENV{'PBPROJ'} = $appname;
137pb_temp_init();
138
139# Initialize the syntax string
140pb_syntax_init("$appname (aka CasparBuster) Version $cbver-$cbrev\n");
141
142# parse command-line options
143GetOptions(
144 'machine|m=s' => \$machine,
145 'debug|d+' => \$debug,
146 'help|h' => \$help,
147 'quiet|q' => \$quiet,
148 'force|f' => \$force,
149 'man' => \$man,
150 'logfile|l=s' => \$log,
151 'source|s=s' => \$source,
152 'plugin|p=s' => \$plugin,
153) || pb_syntax(-1,0);
154
155if (defined $help) {
156 pb_syntax(0,1);
157}
158if (defined $man) {
159 pb_syntax(0,2);
160}
161if (defined $quiet) {
162 $debug=-1;
163}
164if (defined $log) {
165 open(LOG,"> $log") || die "Unable to log to $log: $!";
166 $LOG = \*LOG;
167 $debug = 0 if ($debug == -1);
168}
169
170$pbdebug = $debug;
171pb_log_init($debug, $LOG);
172pb_log(0,"Starting cbusterize\n");
173
174# Get conf file in context
175pb_conf_init($appname);
176# The personal one if there is such
177pb_conf_add("$ENV{'HOME'}/.cbrc") if (-f "$ENV{'HOME'}/.cbrc");
178# The system one
179pb_conf_add(cb_env_conffile());
180
181# Get configuration parameters
182my %cb;
183my $cb = \%cb;
184($cb->{'basedir'},$cb->{'usemachines'},$cb->{'cms'}) = pb_conf_get("cbbasedir","cbusemachines","cbcms");
185pb_log(2,"%cb: ",Dumper($cb));
186
187# Check for mandatory params
188pod2usage("Error: --source or --plugin is a mandatory argument\n") if ((not defined $source) && (not defined $plugin));
189pod2usage("Error: --machine is a mandatory argument when configure with cbusemachines = true\n") if (($cb->{'usemachines'}->{$appname} =~ /true/) && (not defined $machine));
190
191if (defined $plugin) {
192 # Load plugins
193 cb_plugin_load();
194}
195
196my $basedir = $cb->{'basedir'}->{$appname};
197eval { $basedir =~ s/(\$ENV.+\})/$1/eeg };
198
199pb_log(1, "DEBUG MODE, not doing anything, just printing\nDEBUG: basedir = $basedir\n");
200pb_log(1, "DEBUG: source = $source\n") if (defined $source);
201pb_log(1, "DEBUG: machine = $machine\n") if (defined $machine);
202
203# Use potentially a remote account if defined
204my $account = undef;
205my $remote = undef;
206($account) = pb_conf_get_if("cbaccount") if (defined $machine);
207$remote = $account->{$machine} if ((defined $account) && (defined $machine) && (defined $account->{$machine}));
208pb_log(1, "DEBUG: remote account1 = $remote\n") if (defined $remote);
209$remote = getpwuid($<) if (not defined $remote);
210pb_log(1, "DEBUG: remote account2 = $remote\n");
211
212# Create basedir if it doesn't exist
213if (not -d $basedir) {
214 if ($debug) {
215 pb_log(1, "DEBUG: Creating recursively directory $basedir\n");
216 } else {
217 pb_mkdir_p($basedir) || die "Unable to recursively create $basedir: $!";
218 }
219}
220
221if (defined $source) {
222 foreach my $f (split(/,/,$source)) {
223 cb_busterize($f,"true");
224 }
225}
226
227# Now handle plugins if any
228my $cbp = ();
229
230if (defined $plugin) {
231 foreach my $p (split(/,/,$plugin)) {
232 pb_log(1,"Getting context for plugin $p\n");
233 $cbp = cb_plugin_get($p,$cbp);
234 pb_log(2,"cbp: ".Dumper($cbp)."\n");
235 foreach my $k (keys %{$cbp->{$plugin}->{'dirsandfiles'}}) {
236 cb_busterize($k,"true");
237 }
238 foreach my $k ((keys %{$cbp->{$plugin}->{'dirs'}}),(keys %{$cbp->{$plugin}->{'files'}})) {
239 cb_busterize($k,"false");
240 }
241 }
242}
243
244sub cb_busterize {
245
246my $source = shift;
247my $recur = shift;
248
249pb_log(2,"Entering cb_busterize source: $source\n");
250# Is the source a file or a dir ? Split the source parameter in 2
251my $srcdir = undef;
252my $srcfile = undef;
253my $cmd = undef;
254my $ssh2;
255my $sftp;
256
257if (not defined $machine) {
258 if (-d $source) {
259 $srcdir = $source;
260 } else {
261 $srcdir = dirname($source);
262 $srcfile = basename($source);
263 }
264} else {
265 $ssh2 = Net::SSH2->new();
266 $ssh2->connect($machine);
267 my $hdir = (getpwnam(getpwuid($<)))[7];
268 if ($ssh2->auth_publickey($remote,"$hdir/.ssh/id_dsa.pub","$hdir/.ssh/id_dsa")) {
269 $sftp = $ssh2->sftp;
270 my %dirs = $sftp->stat("$source/.");
271 my $res = 0;
272 $res = -1 if (not defined $dirs{'mode'});
273 pb_log(2,"DEBUG: Found res = $res\n");
274 if ($res == 0) {
275 $srcdir = $source;
276 pb_log(1,"DEBUG: Found remote dir = $source\n");
277 } else {
278 $srcdir = dirname($source);
279 $srcfile = basename($source);
280 pb_log(1,"DEBUG: Found remote file = $source\n");
281 }
282 }
283}
284
285pb_log(1,"DEBUG: Found srcdir = $srcdir\n");
286if (defined $srcfile) {
287 pb_log(1,"DEBUG: Found srcfile = $srcfile\n");
288} else {
289 pb_log(1,"DEBUG: Found no srcfile\n");
290}
291
292# Deduce the target directory from the local structure and the source
293my $target = $basedir;
294$target .= "/$machine" if defined ($machine);
295$target .= "$srcdir";
296
297my $scheme = $cb->{'cms'}->{$appname};
298
299# If both source and target are dirs, then copy into the parent of the target
300$target = basename($target) if ((not defined $srcfile) && (-d $target));
301
302# Create target if it doesn't exist
303if (not -d $target) {
304 if ($debug) {
305 pb_log(1,"DEBUG: Creating recursively directory $target\n");
306 } else {
307 pb_mkdir_p($target) || die "Unable to recursively create $target: $!";
308 }
309 # Add all the dirs in it to VCS (in reverse order)
310 my $tdir = $target;
311 my @tab = ();
312 while ($tdir ne $basedir) {
313 push(@tab,$tdir);
314 $tdir = dirname($tdir);
315 pb_log(3,"tdir is now $tdir\n");
316 }
317 if ($debug) {
318 pb_log(0,"INFO: Added to your $scheme system the dirs: ".join(' ',reverse(@tab))."\n");
319 } else {
320 pb_vcs_add($scheme,reverse(@tab));
321 }
322}
323
324# We need to know where to get the content from
325my $cmdopt = "";
326
327# Recursive if we copy dirs
328$cmdopt = "-r" if (not defined $srcfile);
329
330if (defined $machine) {
331 $cmd = "scp -p -q $cmdopt $remote\@$machine:\'$source\' $target";
332} else {
333 $cmd = "cp -p $cmdopt $source $target";
334}
335
336# Now add content if not already there
337if (defined $srcfile) {
338 # File case
339 if ((! -f "$target/$srcfile") || (defined $force)) {
340 if ($debug) {
341 pb_log(1,"DEBUG: launching $cmd\n");
342 } else {
343 pb_system($cmd);
344 pb_vcs_add($scheme,"$target/$srcfile");
345 pb_log(0,"INFO: Created $target/$srcfile and added it to your $scheme system\n");
346 }
347 } else {
348 pb_log(0,"INFO: File $target/$srcfile already there\n");
349 }
350} else {
351 # Directory case
352 if ($debug) {
353 if ($recur eq "true") {
354 pb_log(1,"DEBUG: launching $cmd\n");
355 } else {
356 pb_log(1,"DEBUG: mkdir -p $target\n");
357 }
358 } else {
359 if ($recur eq "true") {
360 pb_system($cmd);
361 }
362 pb_vcs_add($scheme,"$target");
363 pb_log(0,"INFO: Created $target and added it to your $scheme system\n");
364 }
365}
366$ssh2->disconnect() if (defined $machine);
367pb_log(2,"Exiting cb_busterize\n");
368}
Note: See TracBrowser for help on using the repository browser.