Created
June 19, 2016 23:15
-
-
Save bensallen/08c45f50684f5a4ef2231608104a996d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# | |
# Copyright (c) 2001-2003 Gregory M. Kurtzer | |
# | |
# Copyright (c) 2003-2011, The Regents of the University of California, | |
# through Lawrence Berkeley National Laboratory (subject to receipt of any | |
# required approvals from the U.S. Dept. of Energy). All rights reserved. | |
# | |
use CGI; | |
use Warewulf::Util; | |
use Warewulf::DataStore; | |
use Warewulf::Logger; | |
use Warewulf::Daemon; | |
use Warewulf::Node; | |
use Warewulf::Vnfs; | |
use Warewulf::Provision; | |
use File::Path; | |
use File::Basename; | |
use Fcntl qw(:flock); | |
&set_log_level("DEBUG"); | |
my $q = CGI->new(); | |
my $db = Warewulf::DataStore->new(); | |
my $vnfs_cachedir = "/var/tmp/warewulf_cache/"; | |
sub | |
lock | |
{ | |
my $lfh = shift; | |
# Non-Blocking Lock - Fail if lock cannot be obtained | |
my $ret = flock($lfh, LOCK_EX|LOCK_NB); | |
return $ret; | |
} | |
sub | |
unlock | |
{ | |
my $ufh = shift; | |
my $ret = flock($ufh, LOCK_UN); | |
return $ret; | |
} | |
if ($q->param('hwaddr')) { | |
my $hwaddr = $q->param('hwaddr'); | |
my $node; | |
if ($hwaddr =~ /^([a-zA-Z0-9:]+)$/) { | |
my $hwaddr = $1; | |
my $nodeSet = $db->get_objects("node", "_hwaddr", $hwaddr); | |
foreach my $tnode ($nodeSet->get_list()) { | |
if (! $tnode->enabled()) { | |
next; | |
} | |
$node = $tnode; | |
} | |
if ($node) { | |
my ($node_name) = $node->name(); | |
my ($vnfsid) = $node->vnfsid(); | |
if ($vnfsid) { | |
my $obj = $db->get_objects("vnfs", "_id", $vnfsid)->get_object(0); | |
if ($obj) { | |
my $vnfs_name = $obj->name(); | |
my $vnfs_checksum = $obj->checksum(); | |
my ($vnfs_nocache) = $obj->get("nocache"); | |
my $use_cache; | |
my $cache_in_progress = 0; | |
#&nprint("Sending VNFS '$vnfs_name' to node '$node_name'\n"); | |
$q->print("Content-Type: application/octet-stream; name=\"vnfs.img\"\r\n"); | |
if (my $size = $obj->size()) { | |
$q->print("Content-length: $size\r\n"); | |
} | |
$q->print("Content-Disposition: attachment; filename=\"vnfs.img\"\r\n"); | |
$q->print("\r\n"); | |
if (! $vnfs_nocache) { | |
if (-f "$vnfs_cachedir/$vnfs_name/image.$vnfs_checksum") { | |
&dprint("Found VNFS cache\n"); | |
# Perhaps do a better job checking here... one day. | |
$use_cache = 1; | |
} else { | |
&dprint("Building VNFS cache\n"); | |
my $rand = &rand_string(8); | |
my $cache_fh; | |
if (! -d "$vnfs_cachedir/$vnfs_name") { | |
mkpath("$vnfs_cachedir/$vnfs_name"); | |
} | |
my $lock_file = "$vnfs_cachedir/$vnfs_name/warewulf.cache.lock"; | |
my $lock_fh; | |
if (! open($lock_fh, '>', $lock_file) || ! &lock($lock_fh)) { | |
&eprint("Can't open VNFS cache. Locked by another request.\n"); | |
$cache_in_progress = 1; | |
$use_cache = 1; | |
} else { | |
&dprint("VNFS cache lock obtained.\n"); | |
open($cache_fh, "> $vnfs_cachedir/$vnfs_name/image.$vnfs_checksum.$rand"); | |
my $binstore = $db->binstore($obj->get("_id")); | |
while(my $buffer = $binstore->get_chunk()) { | |
print $cache_fh $buffer; | |
} | |
if (close($cache_fh)) { | |
rename("$vnfs_cachedir/$vnfs_name/image.$vnfs_checksum.$rand", "$vnfs_cachedir/$vnfs_name/image.$vnfs_checksum"); | |
foreach my $image (glob("$vnfs_cachedir/$vnfs_name/image.*")) { | |
if ($image =~ /^([a-zA-Z0-9\/\-\._]+?\/image\.[a-zA-Z0-9]+)$/) { | |
$image = $1; | |
my $basename = basename($image); | |
if ($basename ne "image.$vnfs_checksum") { | |
&wprint("Clearing old vnfs cache: $image\n"); | |
unlink($image); | |
} | |
} | |
} | |
$use_cache = 1; | |
} | |
&unlock($fh); | |
close($lock_fh) && unlink($lock_file); | |
} | |
} | |
} | |
if ($use_cache) { | |
if ($cache_in_progress) { | |
my $lock_file = "$vnfs_cachedir/$vnfs_name/warewulf.cache.lock"; | |
while(-e $lock_file) { | |
&dprint("Waiting for lock on cache to freed, then will attempt to use the new cache.\n"); | |
sleep(5); | |
} | |
} | |
my $cache_fh; | |
if (open($cache_fh, "$vnfs_cachedir/$vnfs_name/image.$vnfs_checksum")) { | |
&dprint("Sending cached VNFS\n"); | |
my $buffer; | |
while($buffer = <$cache_fh>) { | |
$q->print($buffer); | |
} | |
close($cache_fh); | |
} else { | |
&eprint("Can't open VNFS cache!\n"); | |
$q->print("Content-Type: application/octet-stream\r\n"); | |
$q->print("Status: 500\r\n"); | |
$q->print("\r\n"); | |
} | |
} elsif (! $cache_in_progress) { | |
&dprint("Sending VNFS from the data store\n"); | |
my $binstore = $db->binstore($obj->get("_id")); | |
while(my $buffer = $binstore->get_chunk()) { | |
$q->print($buffer); | |
} | |
} | |
} else { | |
&eprint("VNFS request for an unknown VNFS (VNFSID: $vnfsid)\n"); | |
$q->print("Content-Type: application/octet-stream\r\n"); | |
$q->print("Status: 404\r\n"); | |
$q->print("\r\n"); | |
} | |
} else { | |
&eprint("$node_name has no VNFS set\n"); | |
$q->print("Content-Type: application/octet-stream\r\n"); | |
$q->print("Status: 404\r\n"); | |
$q->print("\r\n"); | |
} | |
} else { | |
&eprint("VNFS request for an unknown node (HWADDR: $hwaddr)\n"); | |
$q->print("Content-Type: application/octet-stream\r\n"); | |
$q->print("Status: 404\r\n"); | |
$q->print("\r\n"); | |
} | |
} else { | |
&eprint("VNFS request for a bad hwaddr\n"); | |
$q->print("Content-Type: application/octet-stream\r\n"); | |
$q->print("Status: 404\r\n"); | |
$q->print("\r\n"); | |
} | |
} else { | |
&eprint("VNFS request without a hwaddr\n"); | |
$q->print("Content-Type: application/octet-stream\r\n"); | |
$q->print("Status: 404\r\n"); | |
$q->print("\r\n"); | |
} | |
# vim: filetype=perl:syntax=perl:expandtab:ts=4:sw=4: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment