From 3fff793cffd8170e0f15a8138e5f9fd7e40cb0cc Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Wed, 16 Jun 2010 09:18:25 +0000 Subject: add --zeroconf support in urpmi.addmedia --- NEWS | 2 ++ README.zeroconf | 30 +++++++++++++++++++++++ pod/urpmi.addmedia.8.pod | 6 +++++ urpm/args.pm | 1 + urpm/media.pm | 57 ++++++++++++++++++++++++++++++++++++++++++- urpmi-repository-http.service | 16 ++++++++++++ urpmi.addmedia | 5 +++- 7 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 README.zeroconf create mode 100644 urpmi-repository-http.service diff --git a/NEWS b/NEWS index f63a5913..927b6590 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +- add --zeroconf support in urpmi.addmedia + Version 6.37 - 28 May 2010 - urpmq o fix listing of groups when listing all packages (also fixes #59321) diff --git a/README.zeroconf b/README.zeroconf new file mode 100644 index 00000000..4df14066 --- /dev/null +++ b/README.zeroconf @@ -0,0 +1,30 @@ +urpmi can automatically find the media repository path using DNS-SD +(Zeroconf), with the "--zeroconf" option: + urpmi.addmedia --distrib --zeroconf + urpmi.addmedia --zeroconf main media/main/release + +This option can also be used together with the "--mirrorlist" option, +in which case the repositories are configured using Zeroconf if found, +and mirrorlist is used as a fallback: + urpmi.addmedia --distrib --zeroconf --mirrorlist + +When searching for the repository using Zeroconf, the request timeouts +after a delay of 10 seconds, to avoid hanging urpmi if some hosts are +unresolvable. + +If a repository is found using DNS-SD, urpmi.addmedia will build a +complete repository path using fields from /etc/product.id, this way: +/lowercase()// + +To advertise an urpmi repository using DNS-SD, a service record with +the instance "_mdv_urpmi" has to be created, specifying the target +host and target port where the service is located. +In addition, two DNS-SD TXT records must be specified, in the form of +key/value pairs: protocol (http, ftp or rsync) and path (repository root). + +The path value should be the full path to the media repository root, +for example /dis if the distribution repository is reachable on +http://host:port/dis/official/2010.1/i586 + +See the urpmi-repository-http.service file for an example of urpmi +repository advertising using Avahi. diff --git a/pod/urpmi.addmedia.8.pod b/pod/urpmi.addmedia.8.pod index c7d223a6..6d404716 100644 --- a/pod/urpmi.addmedia.8.pod +++ b/pod/urpmi.addmedia.8.pod @@ -156,6 +156,12 @@ available. nb: $MIRRORLIST is a special variable which gives the default URL for the current distribution/arch. $MIRRORLIST is the default mirrorlist. +=item B<--zeroconf> + +Find a media repository for the current distribution using zeroconf (DNS-SD). +It can be used together with B<--distrib> or by specifying a media name and a +path to the media directory, relative to the repository root. + =item B<--distrib> Retrieve a set of media from a distribution. Typically, the URL provided diff --git a/urpm/args.pm b/urpm/args.pm index 71902b36..d5e584cc 100644 --- a/urpm/args.pm +++ b/urpm/args.pm @@ -344,6 +344,7 @@ my %options_spec = ( 'no-probe' => sub { $options{probe_with} = undef }, distrib => sub { $options{distrib} = 1 }, 'mirrorlist:s' => sub { $options{mirrorlist} = $_[1] || '$MIRRORLIST' }, + zeroconf => sub { $options{zeroconf} = 1 }, interactive => sub { $options{interactive} = 1 }, 'all-media' => sub { $options{allmedia} = 1 }, virtual => \$options{virtual}, diff --git a/urpm/media.pm b/urpm/media.pm index b7b7f6cb..9f8c138c 100644 --- a/urpm/media.pm +++ b/urpm/media.pm @@ -755,10 +755,61 @@ sub _compute_flags_for_instlist { } +sub maybe_find_zeroconf { + my ($urpm, $url, $options) = @_; + if (delete $options->{zeroconf}) { + $url and die "unexpected url $url together with zeroconf\n"; + $url = find_zeroconf_repository($urpm); + if ($url) { + $url = urpm::mirrors::_add__with_dir($url, delete $options->{"with-dir"}); + delete $options->{mirrorlist}; + } + } + return $url; +} + +sub find_zeroconf_repository { + my ($urpm) = @_; + + my $zeroconf_timeout = 10; + my $res; + eval { + local $SIG{ALRM} = sub { die "timeout" }; + alarm($zeroconf_timeout); + + $urpm->{debug} and $urpm->{debug}("trying to find a zeroconf repository"); + require Net::Bonjour; + $res = Net::Bonjour->new('mdv_urpmi'); + + alarm(0); + }; + + if ($@) { + $urpm->{error}("zeroconf error: $@"), return; + } + + require urpm::mirrors; + my $product_id = urpm::mirrors::parse_LDAP_namespace_structure(cat_('/etc/product.id')); + my $path_suffix = join('/', lc($product_id->{branch}), $product_id->{version}, $product_id->{arch}); + + foreach my $entry ($res->entries) { + my $base_url = $entry->attribute('protocol') . '://' .$entry->address . ':' . $entry->port . $entry->attribute('path'); + my $url = $base_url . '/' . $path_suffix; + my $distribconf = _new_distribconf_and_download($urpm, { url => $url }); + if ($distribconf) { + $urpm->{log}(sprintf("found zeroconf repository: %s", $url)); + return $url; + }; + } + + $urpm->{debug} and $urpm->{debug}("unable to find zeroconf repository"); + return; +} + #- add a new medium, sync the config file accordingly. #- returns the new medium's name. (might be different from the requested #- name if index_name was specified) -#- options: ignore, index_name, nolock, update, virtual, media_info_dir, mirrorlist, with-dir, xml-info, on_the_fly +#- options: ignore, index_name, nolock, update, virtual, media_info_dir, mirrorlist, zeroconf, with-dir, xml-info, on_the_fly sub add_medium { my ($urpm, $name, $url, $with_synthesis, %options) = @_; @@ -777,6 +828,8 @@ sub add_medium { name2medium($urpm, $name) and $urpm->{fatal}(5, N("medium \"%s\" already exists", $name)); } + $url = maybe_find_zeroconf($urpm, $url, \%options); + $url =~ s,/*$,,; #- clear URLs for trailing /es. #- creating the medium info. @@ -878,6 +931,7 @@ sub _register_media_cfg { #- - ask_media : callback to know whether each media should be added #- - only_updates : only add "update" media (used by rpmdrake) #- - mirrorlist +#- - zeroconf #- other options are passed to add_medium(): ignore, nolock, virtual sub add_distrib_media { my ($urpm, $name, $url, %options) = @_; @@ -903,6 +957,7 @@ sub add_distrib_media { _register_media_cfg($urpm, $dir, undef, $distribconf, $media_cfg); } } else { + $url = maybe_find_zeroconf($urpm, $url, \%options); if ($options{mirrorlist}) { $url and die "unexpected url $url together with mirrorlist $options{mirrorlist}\n"; } diff --git a/urpmi-repository-http.service b/urpmi-repository-http.service new file mode 100644 index 00000000..735d30bc --- /dev/null +++ b/urpmi-repository-http.service @@ -0,0 +1,16 @@ + + + + + Mandriva urpmi repository on %h (HTTP) + + + _mdv_urpmi._tcp + _http._sub._mdv_urpmi._tcp + distro.local + 80 + protocol=http + path=/dis + + + diff --git a/urpmi.addmedia b/urpmi.addmedia index 872e93b4..415d1e4a 100755 --- a/urpmi.addmedia +++ b/urpmi.addmedia @@ -48,6 +48,7 @@ examples: urpmi.addmedia --distrib --mirrorlist '\$MIRRORLIST' urpmi.addmedia --mirrorlist '\$MIRRORLIST' backports media/main/backports + urpmi.addmedia --distrib --zeroconf and [options] are from @@ -101,7 +102,7 @@ my $with_dir; $options{quiet} = 1 if $options{verbose} < 0; $url or ($url, $name) = ($name, ''); -if ($options{mirrorlist}) { +if ($options{mirrorlist} || $options{zeroconf}) { if ($options{distrib}) { $url and die N("no argument needed for --distrib --mirrorlist ") . "\n"; } else { @@ -144,6 +145,7 @@ if ($options{distrib}) { $name, $url, mirrorlist => $options{mirrorlist}, + zeroconf => $options{zeroconf}, virtual => $options{virtual}, only_updates => $options{update}, probe_with => $options{probe_with}, @@ -167,6 +169,7 @@ if ($options{distrib}) { urpm::media::add_medium($urpm, $name, $url, $relative_synthesis, mirrorlist => $options{mirrorlist}, + zeroconf => $options{zeroconf}, 'with-dir' => $with_dir, virtual => $options{virtual}, update => $options{update}, -- cgit v1.2.1