Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
emulab
emulab-devel
Commits
5acdd9ce
Commit
5acdd9ce
authored
Jul 01, 2014
by
Leigh B Stoller
Browse files
Checkpoint image provenance/versioning.
parent
5aff2d89
Changes
57
Expand all
Hide whitespace changes
Inline
Side-by-side
clientside/os/frisbee.redux/config_emulab.c
View file @
5acdd9ce
...
...
@@ -1308,36 +1308,49 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
if
(
imageid
!=
NULL
)
{
/* Interested in a specific image */
if
(
can_access
(
imageidx
,
ei
,
1
))
{
res
=
mydb_query
(
"SELECT pid,gid,imagename,"
" path,imageid"
" FROM images WHERE"
" pid='%s'"
" AND imagename='%s'"
,
res
=
mydb_query
(
"SELECT i.pid,i.gid,"
" i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
" WHERE i.pid='%s'"
" AND i.imagename='%s'"
,
5
,
wantpid
,
wantname
);
}
else
{
/*
* Pid of expt must be same as pid of image
* and gid the same or image "shared".
*/
res
=
mydb_query
(
"SELECT pid,gid,imagename,"
"path,imageid"
" FROM images WHERE"
" pid='%s' AND imagename='%s'"
" AND pid='%s'"
" AND (gid='%s' OR"
" (gid=pid AND shared=1))"
,
res
=
mydb_query
(
"SELECT i.pid,i.gid,"
" i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
" WHERE i.pid='%s' "
" AND i.imagename='%s'"
" AND i.pid='%s'"
" AND (i.gid='%s' OR"
" (i.gid=i.pid AND "
" v.shared=1))"
,
5
,
wantpid
,
wantname
,
ei
->
pid
,
ei
->
gid
);
}
}
else
{
/* Find all images that this pid/gid can PUT */
res
=
mydb_query
(
"SELECT pid,gid,imagename,"
"path,imageid"
" FROM images"
" WHERE pid='%s'"
" AND (gid='%s' OR"
" (gid=pid AND shared=1))"
" ORDER BY pid,gid,imagename"
,
res
=
mydb_query
(
"SELECT i.pid,i.gid,i.imagename,"
"v.path,i.imageid"
" FROM images as i"
" LEFT JOIN image_versions as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
" WHERE i.pid='%s'"
" AND (i.gid='%s' OR"
" (i.gid=i.pid AND v.shared=1))"
" ORDER BY i.pid,i.gid,i.imagename"
,
5
,
ei
->
pid
,
ei
->
gid
);
}
assert
(
res
!=
NULL
);
...
...
@@ -1436,34 +1449,48 @@ emulab_get_host_authinfo(struct in_addr *req, struct in_addr *host,
if
(
imageid
!=
NULL
)
{
/* Interested in a specific image */
if
(
can_access
(
imageidx
,
ei
,
0
))
{
res
=
mydb_query
(
"SELECT pid,gid,imagename,"
"path,imageid"
" FROM images WHERE"
" pid='%s'"
" AND imagename='%s'"
,
res
=
mydb_query
(
"SELECT i.pid,i.gid,"
"i.imagename,v.path,i.imageid"
" FROM images as i "
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
"WHERE i.pid='%s'"
" AND i.imagename='%s'"
,
5
,
wantpid
,
wantname
);
}
else
{
res
=
mydb_query
(
"SELECT pid,gid,imagename,"
"path,imageid"
" FROM images WHERE"
" pid='%s' AND imagename='%s'"
" AND (global=1"
" OR (pid='%s'"
" AND (gid='%s'"
" OR shared=1)))"
res
=
mydb_query
(
"SELECT i.pid,i.gid,"
"i.imagename,v.path,i.imageid"
" FROM images as i"
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
" WHERE i.pid='%s' "
" AND i.imagename='%s'"
" AND (v.global=1"
" OR (i.pid='%s'"
" AND (i.gid='%s'"
" OR v.shared=1)))"
" ORDER BY pid,gid,imagename"
,
5
,
wantpid
,
wantname
,
ei
->
pid
,
ei
->
gid
);
}
}
else
{
/* Find all images that this pid/gid can GET */
res
=
mydb_query
(
"SELECT pid,gid,imagename,"
"path,imageid"
" FROM images WHERE"
" (global=1"
" OR (pid='%s'"
" AND (gid='%s' OR shared=1)))"
" ORDER BY pid,gid,imagename"
,
res
=
mydb_query
(
"SELECT i.pid,i.gid,i.imagename,"
"v.path,i.imageid"
" FROM images as i"
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
" WHERE"
" (v.global=1"
" OR (i.pid='%s'"
" AND (i.gid='%s' OR v.shared=1)))"
" ORDER BY i.pid,i.gid,i.imagename"
,
5
,
ei
->
pid
,
ei
->
gid
);
}
assert
(
res
!=
NULL
);
...
...
@@ -1610,10 +1637,14 @@ dump_image_aliases(FILE *fd)
char
*
lastpid
;
/* First the global image alias */
res
=
mydb_query
(
"SELECT pid,imagename"
" FROM images"
" WHERE global=1"
" ORDER BY pid,imagename"
,
2
);
res
=
mydb_query
(
"SELECT i.pid,i.imagename"
" FROM images as i"
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
" WHERE v.global=1"
" ORDER BY i.pid,i.imagename"
,
2
);
assert
(
res
!=
NULL
);
nrows
=
mysql_num_rows
(
res
);
...
...
@@ -1662,10 +1693,14 @@ dump_image_aliases(FILE *fd)
free
(
lastpid
);
lastpid
=
mystrdup
(
row
[
0
]);
res2
=
mydb_query
(
"SELECT imagename"
" FROM images"
" WHERE pid='%s' AND shared=1"
" ORDER BY imagename"
,
res2
=
mydb_query
(
"SELECT i.imagename"
" FROM images as i"
" LEFT JOIN image_versions "
" as v on "
" v.imageid=i.imageid and "
" v.version=i.version "
" WHERE i.pid='%s' AND v.shared=1"
" ORDER BY i.imagename"
,
1
,
lastpid
);
assert
(
res2
!=
NULL
);
...
...
configure
View file @
5acdd9ce
...
...
@@ -659,6 +659,7 @@ TBOPSEMAIL
IPV6_SUBNET_PREFIX
IPV6_ENABLED
NFSMAPTOUSER
IMAGEPROVENANCE
BROWSER_CONSOLE_ENABLE
EC2META_ENABLE
NOSITECHECKIN
...
...
@@ -5091,6 +5092,7 @@ MANAGEMENT_NETWORK="10.249.249.0"
MANAGEMENT_NETMASK
=
"255.255.255.0"
MANAGEMENT_ROUTER
=
"10.249.249.253"
NFSMAPTOUSER
=
"root"
IMAGEPROVENANCE
=
0
#
# XXX You really don't want to change these!
...
...
configure.in
View file @
5acdd9ce
...
...
@@ -291,6 +291,7 @@ AC_SUBST(BROWSER_CONSOLE_ENABLE)
AC_SUBST(IPV6_ENABLED)
AC_SUBST(IPV6_SUBNET_PREFIX)
AC_SUBST(NFSMAPTOUSER)
AC_SUBST(IMAGEPROVENANCE)
#
# Offer both versions of the email addresses that have the @ escaped
...
...
@@ -433,6 +434,7 @@ MANAGEMENT_NETWORK="10.249.249.0"
MANAGEMENT_NETMASK="255.255.255.0"
MANAGEMENT_ROUTER="10.249.249.253"
NFSMAPTOUSER="root"
IMAGEPROVENANCE=0
#
# XXX You really don't want to change these!
...
...
db/Experiment.pm.in
View file @
5acdd9ce
...
...
@@ -193,10 +193,13 @@ $EXPT_RESOURCESHOSED = 0;
#
These
are
slots
in
the
node
table
that
need
to
be
restored
.
@
nodetable_fields
=
(
"def_boot_osid"
,
"def_boot_osid_vers"
,
"def_boot_path"
,
"def_boot_cmd_line"
,
"temp_boot_osid"
,
"temp_boot_osid_vers"
,
"next_boot_osid"
,
"next_boot_osid_vers"
,
"next_boot_path"
,
"next_boot_cmd_line"
,
"pxe_boot_path"
,
...
...
@@ -4506,12 +4509,14 @@ sub LinkTestCapable($$)
my $idx = $self->idx();
my $query_result =
DBQueryWarn("select v.vname, FIND_IN_SET('
linktest
',osfeatures) ".
DBQueryWarn("select v.vname, FIND_IN_SET('
linktest
',
ov.
osfeatures) ".
" from virt_nodes as v ".
"left join reserved as r on r.pid=v.pid and ".
" r.eid=v.eid and r.vname=v.vname ".
"left join nodes as n on n.node_id=r.node_id ".
"left join os_info as o on o.osid=n.def_boot_osid ".
"left join os_info_versions as ov on ".
" ov.osid=n.def_boot_osid and ".
" ov.vers=n.def_boot_osid_vers ".
"where v.exptidx='
$
idx
' and v.role!='
bridge
'");
return -1
if (!defined($query_result));
...
...
db/Image.pm.in
View file @
5acdd9ce
This diff is collapsed.
Click to expand it.
db/Node.pm.in
View file @
5acdd9ce
...
...
@@ -360,7 +360,7 @@ sub Create($$$$)
{
my
($
class
,
$
node_id
,
$
experiment
,
$
argref
)
=
@
_
;
my
($
control_iface
,$
virtnode_capacity
,$
adminmfs
,$
adminmfs_osid
);
my
($
priority
,
$
osid
,
$
opmode
,
$
state
);
my
($
priority
,
$
osid
,
$
osid_vers
,
$
opmode
,
$
state
);
require
OSinfo
;
require
NodeType
;
...
...
@@ -392,6 +392,7 @@ sub Create($$$$)
if
(
!defined($typeinfo));
my
$
isremote
=
$
typeinfo
->
isremotenode
();
$
osid_vers
=
0
;
if
($
role
eq
"testnode"
)
{
if
($
typeinfo
->
virtnode_capacity
(\$
virtnode_capacity
))
{
...
...
@@ -415,8 +416,9 @@ sub Create($$$$)
"*** Could not find OSinfo object for $osid!
\n
"
;
return
undef
;
}
$
osid
=
$
osinfo
->
osid
();
$
opmode
=
$
osinfo
->
op_mode
();
$
osid
=
$
osinfo
->
osid
();
$
osid_vers
=
$
adminmfs
->
vers
();
$
opmode
=
$
osinfo
->
op_mode
();
}
}
else
{
...
...
@@ -436,8 +438,9 @@ sub Create($$$$)
"*** Could not find OSinfo object for adminmfs!
\n
"
;
return
undef
;
}
$
osid
=
$
adminmfs
->
osid
();
$
opmode
=
$
adminmfs
->
op_mode
();
$
osid
=
$
adminmfs
->
osid
();
$
osid_vers
=
$
adminmfs
->
vers
();
$
opmode
=
$
adminmfs
->
op_mode
();
}
}
else
{
...
...
@@ -486,7 +489,7 @@ sub Create($$$$)
" phys_nodeid='$node_id', role='$role', "
.
" priority=$priority, "
.
" eventstate='$state', op_mode='$opmode', "
.
" def_boot_osid=$osid, "
.
" def_boot_osid=$osid,
def_boot_osid_vers='$osid_vers'
"
.
" inception=now(), uuid=$uuid, "
.
" state_timestamp=unix_timestamp(NOW()), "
.
" op_mode_timestamp=unix_timestamp(NOW())"
))
{
...
...
@@ -1687,6 +1690,7 @@ sub ClearBootAttributes($)
"tarballs='',failureaction='
fatal
', routertype='
none
', ".
"def_boot_cmd_line='',next_boot_cmd_line='', ".
"temp_boot_osid=NULL,next_boot_osid=NULL, ".
"temp_boot_osid_vers=0,next_boot_osid_vers=0, ".
"update_accounts=0,ipport_next=ipport_low,rtabid=0, ".
"sfshostid=NULL,allocstate='
$
allocFreeState
',boot_errno=0, ".
"destination_x=NULL,destination_y=NULL, ".
...
...
@@ -2171,17 +2175,13 @@ sub CreateVnodes($$$)
# table.
#
my $osid = $nodetype->default_osid();
my $query_result =
DBQueryWarn("select op_mode from os_info where osid='
$
osid
'");
return -1
if (! $query_result);
if (! $query_result->numrows) {
my $osinfo = OSinfo->Lookup($osid);
if (!defined($osinfo)) {
print STDERR "*** CreateVnodes: No such OSID '
$
osid
'\n";
return -1;
}
my ($opmode) = $query_result->fetchrow_array();
my ($opmode) = $osinfo->op_mode();
my $osid_vers = $osinfo->vers();
#
# Need IP for jailed nodes.
...
...
@@ -2426,6 +2426,7 @@ sub CreateVnodes($$$)
"eventstate" => $eventstate,
"allocstate" => $allocstate,
"def_boot_osid" => $osid,
"def_boot_osid_vers" => $osid_vers,
"update_accounts" => 1,
"jailflag" => $isjailed);
...
...
@@ -2759,6 +2760,8 @@ sub SetNodeHistory($$$$)
# Set the scheduled_reloads for a node. Type is optional and defaults to
# testbed default load type. See above.
#
# No image version info; we always reload the most current image.
#
sub SetSchedReload($$;$)
{
my ($self, $imageid, $type) = @_;
...
...
@@ -3136,13 +3139,18 @@ sub OSSelect($$$$)
if (!defined($field)) {
# Clear all osids.
DBQueryWarn("update nodes set ".
"def_boot_osid=NULL,next_boot_osid=NULL,temp_boot_osid=NULL ".
"def_boot_osid=NULL,next_boot_osid=NULL,".
"temp_boot_osid=NULL, ".
"def_boot_osid_vers=0,next_boot_osid_vers=0,".
"temp_boot_osid_vers=0 ".
"where node_id='
$
nodeid
'")
or return -1;
} else {
# Set/Clear the osid.
DBQueryWarn("update nodes set ${field}=".
(defined($osinfo) ? "'
" . $osinfo->osid() . "
' " : "NULL ") .
my $osid = (defined($osinfo) ? "'
" . $osinfo->osid() . "
'" : "NULL");
my $vers = (defined($osinfo) ? "'
" . $osinfo->vers() . "
'" : "'
0
'");
DBQueryWarn("update nodes set ${field}=$osid,${field}_vers=$vers ".
"where node_id='
$
nodeid
'")
or return -1;
...
...
@@ -3353,13 +3361,19 @@ sub ClearOsids($) {
DBQueryWarn("update nodes set ".
" def_boot_osid=NULL,".
" next_boot_osid=NULL,".
" temp_boot_osid=NULL ".
" temp_boot_osid=NULL, ".
" def_boot_osid_vers=0,".
" next_boot_osid_vers=0,".
" temp_boot_osid_vers=0 ".
"where node_id='
$
node_id
'")
or return -1;
$self->{"DBROW"}{"def_boot_osid"} = undef;
$self->{"DBROW"}{"temp_boot_osid"} = undef;
$self->{"DBROW"}{"next_boot_osid"} = undef;
$self->{"DBROW"}{"def_boot_osid_vers"} = 0;
$self->{"DBROW"}{"temp_boot_osid_vers"} = 0;
$self->{"DBROW"}{"next_boot_osid_vers"} = 0;
return 0;
}
...
...
@@ -3401,11 +3415,13 @@ sub IsOSLoaded($$)
$osinfo = $tmp;
}
my $osid = $osinfo->osid();
my $vers = $osinfo->vers();
my $nodeid = $self->node_id();
my $query_result =
DBQueryWarn("select osid from partitions as p ".
"where p.node_id='
$
nodeid
' and p.osid='
$
osid
'");
"where p.node_id='
$
nodeid
' and p.osid='
$
osid
' and ".
" p.osid_vers='
$
vers
'");
return -1
if (!$query_result);
...
...
@@ -3683,9 +3699,10 @@ sub RunningOsImage($)
my
($
self
)
=
@
_
;
my
$
nodeid
=
$
self
->
node_id
();
my
$
osid
=
$
self
->
def_boot_osid
();
my
$
imageid
;
my
$
vers
=
$
self
->
def_boot_osid_vers
();
my
$
image
;
my
$
osinfo
=
OSinfo
->
Lookup
($
osid
);
my
$
osinfo
=
OSinfo
->
Lookup
($
osid
,
$
vers
);
return
()
if
(
!defined($osinfo));
...
...
@@ -3693,19 +3710,19 @@ sub RunningOsImage($)
#
No
partition
entries
for
virtnodes
,
they
are
plain
EZ
images
.
#
if
($
self
->
isvirtnode
())
{
$
imageid
=
$
osid
;
#
XXX
No
version
info
,
need
that
.
$
image
=
Image
->
Lookup
($
osid
,
$
vers
);
}
else
{
my
$
query_result
=
DBQueryWarn
(
"select imageid from partitions as p "
.
DBQueryWarn
(
"select imageid
,imageid_version
from partitions as p "
.
"where p.node_id='$nodeid' and p.osid='$osid'"
);
return
()
if
(
!$query_result || !$query_result->numrows);
($
imageid
)
=
$
query_result
->
fetchrow_array
();
my
($
imageid
,$
version
)
=
$
query_result
->
fetchrow_array
();
$
image
=
Image
->
Lookup
($
imageid
,
$
version
);
}
#
This
might
not
exist
for
a
virtnode
;
caller
has
to
deal
with
it
.
my
$
image
=
Image
->
Lookup
($
imageid
);
return
($
osinfo
,
$
image
);
}
...
...
@@ -3836,14 +3853,14 @@ sub SyncTaintStates($)
my
$
node_id
=
$
self
->
node_id
();
my
$
query_result
=
DBQueryWarn
(
"select osid from partitions "
.
DBQueryWarn
(
"select osid
,osid_vers
from partitions "
.
"where node_id='$node_id' and osid is not null"
);
return
-
1
if
(
!$query_result);
my
@
taint_states
=
();
while
(
my
($
osid
)
=
$
query_result
->
fetchrow_array
())
{
my
$
osinfo
=
OSinfo
->
Lookup
($
osid
);
while
(
my
($
osid
,
$
vers
)
=
$
query_result
->
fetchrow_array
())
{
my
$
osinfo
=
OSinfo
->
Lookup
($
osid
,
$
vers
);
if
(
defined
($
osinfo
)
&&
$
osinfo
->
IsTainted
())
{
push
@
taint_states
,
$
osinfo
->
GetTaintStates
();
}
...
...
db/OSinfo.pm.in
View file @
5acdd9ce
#
!/usr/bin/perl -wT
#
#
Copyright
(
c
)
2007
-
201
3
University
of
Utah
and
the
Flux
Group
.
#
Copyright
(
c
)
2007
-
201
4
University
of
Utah
and
the
Flux
Group
.
#
#
{{{
EMULAB
-
LICENSE
#
...
...
@@ -104,74 +104,146 @@ sub mysystem($)
return
system
($
command
);
}
sub
BlessRow
($$)
{
my
($
class
,
$
row
)
=
@
_
;
my
$
self
=
{};
my
$
osid
=
$
row
->{
"osid"
};
$
self
->{
'OSINFO'
}
=
$
row
;
bless
($
self
,
$
class
);
return
$
self
;
}
#
#
Lookup
by
idx
or
pid
,
osname
,
depending
on
the
args
.
#
Lookup
by
idx
or
pid
,
osname
[:
version
]
depending
on
the
args
.
We
always
#
return
highest
numbered
version
on
this
path
,
if
no
version
specified
.
#
sub
Lookup
($$;$)
sub
Lookup
($$;$
$
)
{
my
($
class
,
$
arg1
,
$
arg2
)
=
@
_
;
my
$
osid
;
my
($
class
,
$
arg1
,
$
arg2
,
$
arg3
)
=
@
_
;
#
#
A
single
arg
is
either
an
index
or
a
"pid,osname"
or
"pid/osname"
string
.
#
A
single
arg
is
either
an
index
or
"pid,osname[:version]"
or
#
"pid/osname[:version]"
string
.
#
if
(
!defined($arg2)) {
if
($
arg1
=~
/^(\
d
*)$/)
{
$
osid
=
$
1
;
my
$
result
=
DBQueryWarn
(
"select o.*,v.* from os_info as o "
.
"left join os_info_versions as v on "
.
" v.osid=o.osid and v.vers=o.version "
.
"where o.osid='$arg1'"
);
return
undef
if
(
! $result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
elsif
($
arg1
=~
/^([-\
w
]*),([-\
w
\.\+]*)$/
||
$
arg1
=~
/^([-\
w
]*)\/([-\
w
\.\+]*)$/)
{
$
arg1
=
$
1
;
$
arg2
=
$
2
;
$
arg1
=~
/^([-\
w
]*)\/([-\
w
\.\+]*)$/)
{
my
$
result
=
DBQueryWarn
(
"select o.*,v.* from os_info as o "
.
"left join os_info_versions as v on "
.
" v.osid=o.osid and v.vers=o.version "
.
"where o.pid='$1' and o.osname='$2'"
);
return
undef
if
(
! $result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
else
{
return
undef
;
elsif
($
arg1
=~
/^([-\
w
]*),([-\
w
\.\+]*):(\
d
*)$/
||
$
arg1
=~
/^([-\
w
]*)\/([-\
w
\.\+]*):(\
d
*)$/)
{
my
$
result
=
DBQueryWarn
(
"select o.*,v.* from os_info as o "
.
"left join os_info_versions as v on "
.
" v.osid=o.osid "
.
"where o.pid='$arg1' and o.osname='$arg2' and "
.
" v.vers='$arg3' and v.deleted is null"
);
return
undef
if
(
!$result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
elsif
($
arg1
=~
/^\
w
+\-\
w
+\-\
w
+\-\
w
+\-\
w
+$/)
{
my
$
result
=
DBQueryWarn
(
"select * from os_info "
.
"where uuid='$arg1' and deleted is null"
);
return
undef
if
(
! $result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
return
undef
;
}
elsif
(
! (($arg1 =~ /^[-\w\.\+]*$/) && ($arg2 =~ /^[-\w\.\+]*$/))) {
elsif
(
!defined($arg3)) {
if
($
arg1
=~
/^\
d
+$/
&&
$
arg2
=~
/^\
d
+$/)
{
my
$
result
=
DBQueryWarn
(
"select o.*,v.* from os_info as o "
.
"left join os_info_versions as v on "
.
" v.osid=o.osid "
.
"where o.osid='$arg1' and v.vers='$arg2'"
);
return
undef
if
(
! $result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
elsif
($
arg1
=~
/^[-\
w
]*$/
&&
$
arg2
=~
/^([-\
w
\.\+]*):(\
d
+)$/)
{
my
$
result
=
DBQueryWarn
(
"select o.*,v.* from os_info as o "
.
"left join os_info_versions as v on "
.
" v.osid=o.osid "
.
"where o.pid='$arg1' and o.osname='$1' and "
.
" v.vers='$2'"
);
return
undef
if
(
! $result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
elsif
($
arg1
=~
/^[-\
w
]*$/
&&
$
arg2
=~
/^[-\
w
\.\+]*$/)
{
my
$
result
=
DBQueryWarn
(
"select o.*,v.* from os_info as o "
.
"left join os_info_versions as v on "
.
" v.osid=o.osid and v.vers=o.version "
.
"where o.pid='$arg1' and o.osname='$arg2'"
);
return
undef
if
(
! $result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
return
undef
;
}
#
#
Two
args
means
pid
/
osname
lookup
instead
of
gid_idx
.
#
if
(
defined
($
arg2
))
{
my
$
osid_result
=
DBQueryWarn
(
"select osid from os_info "
.
"where pid='$arg1' and osname='$arg2'"
);
return
undef
if
(
! $osid_result || !$osid_result->numrows);
($
osid
)
=
$
osid_result
->
fetchrow_array
();
else
{
if
($
arg1
=~
/^[-\
w
]*$/
&&
$
arg2
=~
/^[-\
w
\.\+]*$/
&&
$
arg3
=~
/^\
d
+$/)
{
my
$
result
=
DBQueryWarn
(
"select o.*,v.* from os_info as o "
.
"left join os_info_versions as v on "
.
" v.osid=o.osid "
.
"where o.pid='$arg1' and o.osname='$arg2' and "
.
" v.vers='$arg3' and v.deleted is null"
);
return
undef
if
(
!$result || !$result->numrows);
return
BlessRow
($
class
,
$
result
->
fetchrow_hashref
());
}
return
undef
;
}
#
Look
in
cache
first
return
$
osids
{
"$osid"
}
if
(
exists
($
osids
{
"$osid"
}));
my
$
query_result
=
DBQueryWarn
(
"select * from os_info where osid='$osid'"
);
return
undef
if
(
!$query_result || !$query_result->numrows);
return
LookupRow
($
class
,
$
query_result
->
fetchrow_hashref
());
return
undef
;
}
sub
LookupRow
($$)
#
#
Lookup
newest
version
of
osinfo
.
#