aggregate_defs.php 12.2 KB
Newer Older
1 2
<?php
#
3
# Copyright (c) 2006-2019 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
#
#

26 27 28 29
# Set this variable when fetching health status of portal
# aggregates instead of using them.
$PORTAL_HEALTH = 0;

30 31 32
#
# This needs to go into the DB.
#
33 34 35
class Aggregate
{
    var	$aggregate;
36
    var $typeinfo;
37
    var $statusinfo;
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    
    #
    # Constructor by lookup by urn
    #
    function Aggregate($urn) {
	$safe_urn = addslashes($urn);

	$query_result =
	    DBQueryWarn("select * from apt_aggregates where urn='$safe_urn'");

	if (!$query_result || !mysql_num_rows($query_result)) {
	    $this->aggregate = null;
	    return;
	}
	$this->aggregate = mysql_fetch_array($query_result);
53 54 55 56 57 58 59 60 61 62 63 64 65
        $this->typeinfo  = array();

        #
        # Get the type info
        #
        $query_result =
            DBQueryWarn("select * from apt_aggregate_nodetypes ".
                        "where urn='$safe_urn'");
	while ($row = mysql_fetch_array($query_result)) {
	    $type = $row["type"];
            $this->typeinfo[$type] = array("count" => $row["count"],
                                           "free"  => $row["free"]);
        }
66 67 68 69 70 71 72 73 74 75

        #
        # And the status info.
        #
        $query_result =
            DBQueryWarn("select * from apt_aggregate_status ".
                        "where urn='$safe_urn'");
	if ($query_result || mysql_num_rows($query_result)) {
            $this->statusinfo = mysql_fetch_array($query_result);
        }
76 77 78 79 80 81 82
    }
    # accessors
    function field($name) {
	return (is_null($this->aggregate) ? -1 : $this->aggregate[$name]);
    }
    function name()	    { return $this->field('name'); }
    function nickname()	    { return $this->field('nickname'); }
83
    function urn()	    { return $this->field('urn'); }
84 85
    function abbreviation() { return $this->field('abbreviation'); }
    function weburl()	    { return $this->field('weburl'); }
86
    function disabled()     { return $this->field('disabled'); }
87
    function adminonly()    { return $this->field('adminonly'); }
88
    function has_datasets() { return $this->field('has_datasets'); }
89
    function reservations() { return $this->field('reservations'); }
90
    function nomonitor()    { return $this->field('nomonitor'); }
91
    function nolocalimages(){ return $this->field('nolocalimages'); }
92
    function portals()      { return $this->field('portals'); }
93
    function canuse_feature(){ return $this->field('canuse_feature'); }
94

95 96 97 98 99 100 101 102 103 104
    # accessors for the status info.
    function sfield($name) {
	return (is_null($this->statusinfo) ? null : $this->statusinfo[$name]);
    }
    function status()       { return $this->sfield('status'); }
    function last_success() { return $this->sfield('last_success'); }
    function last_attempt() { return $this->sfield('last_attempt'); }
    function pcount()       { return $this->sfield('pcount'); }
    function pfree()        { return $this->sfield('pfree'); }
    function vcount()       { return $this->sfield('vcount'); }
105
    function vfree()        { return $this->sfield('vfree'); }
106 107
    function last_error()   { return $this->sfield('last_error'); }

108 109 110 111 112
    # Hmm, how does one cause an error in a php constructor?
    function IsValid() {
	return !is_null($this->aggregate);
    }

113 114 115 116 117 118 119 120 121 122 123 124
    # Powder Portal, Emulab is not a "federate", all others are.
    function isfederate() {
        global $PORTAL_GENESIS;
        if ($PORTAL_GENESIS == "powder") {
            if ($this->nickname() == "Emulab") {
                return 0;
            }
            return 1;
        }
        return $this->field('isfederate');
    }

125 126 127 128 129 130 131 132 133 134
    # Lookup up by urn,
    function Lookup($urn) {
	$foo = new Aggregate($urn);

	if ($foo->IsValid()) {
	    return $foo;
	}	
	return null;
    }

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    function LookupByNickname($nickname) {
	$safe_nickname = addslashes($nickname);

	$query_result =
            DBQueryWarn("select urn from apt_aggregates ".
                        "where nickname='$safe_nickname'");

	if (!$query_result || !mysql_num_rows($query_result)) {
	    return null;
	}
	$row = mysql_fetch_array($query_result);
	$urn = $row['urn'];

        return Aggregate::Lookup($urn);
    }
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    #
    # Lookup using the short auth name (emulab.net).
    #
    function LookupByDomain($domain) {
        if (! preg_match("/^[-\w\.]+$/", $domain)) {
            return null;
        }
        $query_result =
            DBQueryWarn("select urn from apt_aggregates ".
                        "where urn like 'urn:publicid:IDN+${domain}+%'");
	if (!$query_result || !mysql_num_rows($query_result)) {
            return null;
        }
	$row = mysql_fetch_array($query_result);
	$urn = $row['urn'];

        return Aggregate::Lookup($urn);
    }
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
    #
    # Generate the free nodes URL from the web url.
    #
    function FreeNodesURL() {
        return $this->weburl() . "/node_usage/freenodes.svg";
    }

    #
    # Return a list of aggregates supporting datasets.
    #
    function SupportsDatasetsList() {
	$result  = array();

	$query_result =
	    DBQueryFatal("select urn from apt_aggregates ".
184
			 "where has_datasets!=0 and disabled=0");
185 186 187 188 189 190 191 192

	while ($row = mysql_fetch_array($query_result)) {
	    $urn = $row["urn"];

	    if (! ($aggregate = Aggregate::Lookup($urn))) {
		TBERROR("Aggregate::SupportsDatasetsList: ".
			"Could not load aggregate $urn!", 1);
	    }
193 194 195
            if ($aggregate->adminonly() && !(ISADMIN() || STUDLY())) {
                continue;
            }
196 197 198 199 200
	    $result[] = $aggregate;
	}
        return $result;
    }

201 202 203
    #
    # Return a list of aggregates supporting reservations,
    #
204 205 206
    function SupportsReservations($user = null) {
	$ordered   = array();
        $unordered = array();
207 208 209 210 211
        global $PORTAL_GENESIS;

        $query_result =
            DBQueryFatal("select urn from apt_aggregates ".
                         "where disabled=0 and reservations=1 and ".
212
                         "      FIND_IN_SET('$PORTAL_GENESIS', portals) ".
213 214
                         ($PORTAL_GENESIS != "powder" ?
                          "order by isfederate,name" : "order by nickname"));
215 216 217
        
	while ($row = mysql_fetch_array($query_result)) {
	    $urn = $row["urn"];
218
            $allowed = 1;
219 220 221 222 223

	    if (! ($aggregate = Aggregate::Lookup($urn))) {
		TBERROR("Aggregate::SupportsReservations: ".
			"Could not load aggregate $urn!", 1);
	    }
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
            # Admins always see everything.
            if (ISADMIN()) {
                $allowed = 1;
            }
            elseif ($aggregate->adminonly() && !(ISADMIN() || STUDLY())) {
                $allowed = 0;
            }
            elseif ($user && $aggregate->canuse_feature()) {
                $allowed = 0;
                $feature = $PORTAL_GENESIS . "-" . $aggregate->canuse_feature();

                # Does the user have the feature?
                if (FeatureEnabled($feature, $user, null, null)) {
                    $allowed = 1;
                }
                else {
                    # If not, see if in a project that has it enabled.
                    $projects = $user->ProjectMembershipList();
                    foreach ($projects as $project) {
                        $approved = 0;
                        $group    = $project->DefaultGroup();
                        
                        if ($project->approved() &&
                            !$project->disabled() &&
                            # Must be approved in the project.
                            $project->IsMember($user, $approved) && $approved &&
                            FeatureEnabled($feature, null, $group, null)) {
251
                            $allowed = 1;
252 253 254 255 256 257 258 259
                            break;
                        }
                    }
                }
            }
            if ($allowed) {
                $ordered[] = $aggregate;
                $unordered[$aggregate->nickname()] = $aggregate;
260
            }
261
	}
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
        #
        # Ick, Powder ordering. Need a better way to deal with this.
        #
        if ($PORTAL_GENESIS == "powder") {
            $ordered = array();
            $ordered[] = $unordered["Emulab"];
            $ordered[] = $unordered["Utah"];
            foreach ($unordered as $aggregate) {
                if ($aggregate->nickname() != "Emulab" &&
                    $aggregate->nickname() != "Utah") {
                    $ordered[] = $aggregate;
                }
            }
        }
        return $ordered;
277 278
    }

279 280 281
    #
    # Return the list of allowed aggregates based on the portal in use.
    #
282
    function DefaultAggregateList($user = null) {
283 284 285 286 287 288
        global $PORTAL_GENESIS, $PORTAL_HEALTH;
	$genesis = $PORTAL_GENESIS;
	if ($PORTAL_HEALTH)
	{
	  $genesis = "cloudlab";
	}
289
	$am_array = array();
290 291

        $query_result =
292
            DBQueryFatal("select urn from apt_aggregates ".
293
                         "where disabled=0 and ".
294
                         "      FIND_IN_SET('$genesis', portals)");
295 296 297
        
	while ($row = mysql_fetch_array($query_result)) {
            $urn       = $row["urn"];
298
            $allowed   = 1;
299

300
	    if (! ($aggregate = Aggregate::Lookup($urn))) {
301
		TBERROR("Aggregate::DefaultAggregateList: ".
302 303
			"Could not load aggregate $urn!", 1);
	    }
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
            # Admins always see everything.
            if (ISADMIN()) {
                $allowed = 1;
            }
            elseif ($aggregate->adminonly() && !(ISADMIN() || STUDLY())) {
                $allowed = 0;
            }
            elseif ($user && $aggregate->canuse_feature()) {
                $allowed = 0;
                $feature = $PORTAL_GENESIS . "-" . $aggregate->canuse_feature();

                # Does the user have the feature?
                if (FeatureEnabled($feature, $user, null, null)) {
                    $allowed = 1;
                }
                else {
                    # If not, see if in a project that has it enabled.
                    $projects = $user->ProjectMembershipList();
                    foreach ($projects as $project) {
                        $approved = 0;
                        $group    = $project->DefaultGroup();
                        
                        if ($project->approved() &&
                            !$project->disabled() &&
                            # Must be approved in the project.
                            $project->IsMember($user, $approved) && $approved &&
                            FeatureEnabled($feature, null, $group, null)) {
331
                            $allowed = 1;
332
                            break;
333

334 335 336 337
                        }
                    }
                }
            }
338 339 340
            if ($allowed) {
                $am_array[$urn] = $aggregate;
            }
341 342 343
        }
        return $am_array;
    }
344

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
    #
    # All aggregates
    #
    function AllAggregatesList() {
        $am_array = array();

        $query_result =
             DBQueryFatal("select urn from apt_aggregates");
        
	while ($row = mysql_fetch_array($query_result)) {
            $urn       = $row["urn"];
	    if (! ($aggregate = Aggregate::Lookup($urn))) {
		TBERROR("Aggregate::SupportsReservations: ".
			"Could not load aggregate $urn!", 1);
	    }
	    $am_array[$urn] = $aggregate;
        }
        return $am_array;
    }

365 366 367 368 369 370 371 372 373 374
    function ThisAggregate()
    {
        global $DEFAULT_AGGREGATE_URN;

        if (! ($aggregate = Aggregate::Lookup($DEFAULT_AGGREGATE_URN))) {
            TBERROR("Aggregate::SupportsReservations: ".
                    "Could not load aggregate $urn!", 1);
        }
        return $aggregate;
    }
375 376 377 378 379 380 381 382 383 384 385 386 387 388
}

#
# We use this in a lot of places, so build it all the time.
#
$urn_mapping = array();

$query_result =
    DBQueryFatal("select urn,abbreviation from apt_aggregates");
while ($row = mysql_fetch_array($query_result)) {
    $urn_mapping[$row["urn"]] = $row["abbreviation"];
}

?>