. # # }}} # # function TBvalid_rspec($token) { return TBcheck_dbslot($token, "apt_profiles", "rspec", TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR); } class Profile { var $profile; var $project; # # Constructor by lookup on unique index. # function Profile($token, $version = null) { $safe_profileid = addslashes($token); if (preg_match("/^\w+\-\w+\-\w+\-\w+\-\w+$/", $token)) { # # First look to see if the uuid is for the profile itself, # which means current version. Otherwise look for a # version with the uuid. # $query_result = DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid, ". " i.disabled as profile_disabled ". " from apt_profiles as i ". "left join apt_profile_versions as v on ". " v.profileid=i.profileid and ". " v.version=i.version ". "where i.uuid='$token' and v.deleted is null"); if (!$query_result || !mysql_num_rows($query_result)) { $query_result = DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid, ". " i.disabled as profile_disabled ". " from apt_profile_versions as v ". "left join apt_profiles as i on ". " v.profileid=i.profileid ". "where v.uuid='$token' and ". " v.deleted is null"); } } elseif (is_null($version)) { $query_result = DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid, ". " i.disabled as profile_disabled ". " from apt_profiles as i ". "left join apt_profile_versions as v on ". " v.profileid=i.profileid and ". " v.version=i.version ". "where i.profileid='$safe_profileid'"); } else { $safe_version = addslashes($version); $query_result = DBQueryWarn("select i.*,v.*,i.uuid as profile_uuid, ". " i.disabled as profile_disabled ". " from apt_profile_versions as v ". "left join apt_profiles as i on ". " i.profileid=v.profileid ". "where v.profileid='$safe_profileid' and ". " v.version='$safe_version' and ". " v.deleted is null"); } if (!$query_result || !mysql_num_rows($query_result)) { $this->profile = null; return; } $this->profile = mysql_fetch_array($query_result); # Load lazily; $this->project = null; } # accessors function field($name) { return (is_null($this->profile) ? -1 : $this->profile[$name]); } function name() { return $this->field('name'); } function profileid() { return $this->field('profileid'); } function version() { return $this->field('version'); } function creator() { return $this->field('creator'); } function creator_idx() { return $this->field('creator_idx'); } function updater() { return $this->field('updater'); } function updater_idx() { return $this->field('updater_idx'); } function pid() { return $this->field('pid'); } function pid_idx() { return $this->field('pid_idx'); } function created() { return $this->field('created'); } function published() { return $this->field('published'); } function deleted() { return $this->field('deleted'); } function uuid() { return $this->field('uuid'); } function profile_uuid() { return $this->field('profile_uuid'); } function ispublic() { return $this->field('public'); } function shared() { return $this->field('shared'); } function listed() { return $this->field('listed'); } function rspec() { return $this->field('rspec'); } function script() { return $this->field('script'); } function paramdefs() { return $this->field('paramdefs'); } function locked() { return $this->field('status'); } function status() { return $this->field('locked'); } function topdog() { return $this->field('topdog'); } function disabled() { return $this->field('disabled'); } function profile_disabled() { return $this->field('profile_disabled'); } function parent_profileid() { return $this->field('parent_profileid'); } function parent_version() { return $this->field('parent_version'); } # Private means only in the same project. function IsPrivate() { return !($this->ispublic() || $this->shared()); } # PP profiles have parameter defs. function isParameterized() { return ($this->paramdefs() != "" ? 1 : 0); } # A profile is disabled if version is disabled or entire profile is disabled function isDisabled() { return ($this->disabled() || $this->profile_disabled()); } # Hmm, how does one cause an error in a php constructor? function IsValid() { return !is_null($this->profile); } # Lookup up a single profile by idx. function Lookup($token, $version = null) { $foo = new Profile($token, $version); if ($foo->IsValid()) { # Insert into cache. return $foo; } return null; } function LookupByName($project, $name, $version = null) { if (is_object($project)) { $pid = $project->pid(); } else { $pid = addslashes($project); } $safe_name = addslashes($name); if (preg_match("/^\w+\-\w+\-\w+\-\w+\-\w+$/", $name)) { return Profile::Lookup($name); } elseif (is_null($version)) { $query_result = DBQueryWarn("select i.profileid,i.version ". " from apt_profiles as i ". "left join apt_profile_versions as v on ". " v.profileid=i.profileid and ". " v.version=i.version ". "where i.pid='$pid' and ". " i.name='$safe_name'"); } else { $safe_version = addslashes($version); $query_result = DBQueryWarn("select i.profileid,v.version ". " from apt_profiles as i ". "left join apt_profile_versions as v on ". " v.profileid=i.profileid ". "where i.pid='$pid' and ". " i.name='$safe_name' and ". " v.version='$safe_version'"); } if ($query_result && mysql_num_rows($query_result)) { $row = mysql_fetch_row($query_result); return Profile::Lookup($row[0], $row[1]); } return null; } # # Lookup the most recently published version of a profile. # function LookupMostRecentPublished() { $profileid = $this->profileid(); $query_result = DBQueryWarn("select version from apt_profile_versions as v ". "where v.profileid='$profileid' and ". " published is not null and ". " deleted is null ". "order by published desc limit 1"); if (!$query_result || !mysql_num_rows($query_result)) { return null; } $row = mysql_fetch_row($query_result); return Profile::Lookup($profileid, $row[0]); } # # Refresh an instance by reloading from the DB. # function Refresh() { if (! $this->IsValid()) return -1; $profileid = $this->profileid(); $version = $this->version(); $query_result = DBQueryWarn("select * from apt_profile_versions ". "where profileid='$profileid' and version='$version'"); if (!$query_result || !mysql_num_rows($query_result)) { $this->profile = NULL; $this->project = null; return -1; } $this->profile = mysql_fetch_array($query_result); $this->project = null; return 0; } # # URL. To the specific version of the profile. # function URL() { global $APTBASE, $ISVSERVER, $ISAPT; $uuid = $this->uuid(); if ($this->ispublic() || (!$ISAPT && $this->shared())) { $pid = $this->pid(); $name = $this->name(); $vers = $this->version(); if ($ISVSERVER) return "$APTBASE/p/$pid/$name/$vers"; return "$APTBASE/instantiate.php?profile=$name". "&project=$pid&version=$vers"; } else { if ($ISVSERVER) return "$APTBASE/p/$uuid"; return "$APTBASE/instantiate.php?profile=$uuid"; } } # And the URL of the profile itself. function ProfileURL() { global $APTBASE, $ISVSERVER, $ISAPT; $uuid = $this->profile_uuid(); if ($this->ispublic() || (!$ISAPT && $this->shared())) { $pid = $this->pid(); $name = $this->name(); if ($ISVSERVER) return "$APTBASE/p/$pid/$name"; return "$APTBASE/instantiate.php?profile=$name&project=$pid"; } else { if ($ISVSERVER) return "$APTBASE/p/$uuid"; return "$APTBASE/instantiate.php?profile=$uuid"; } } # # Is this profile the highest numbered version. # function IsHead() { $profileid = $this->profileid(); $query_result = DBQueryWarn("select max(version) from apt_profile_versions ". "where profileid='$profileid' and deleted is null"); if (!$query_result || !mysql_num_rows($query_result)) { return -1; } $row = mysql_fetch_row($query_result); return ($this->version() == $row[0] ? 1 : 0); } # # Does this profile have more then one version (history). # function HasHistory() { $profileid = $this->profileid(); $query_result = DBQueryWarn("select count(*) from apt_profile_versions ". "where profileid='$profileid'"); if (!$query_result || !mysql_num_rows($query_result)) { return -1; } $row = mysql_fetch_row($query_result); return ($row[0] > 1 ? 1 : 0); } # # A profile can be published if it is a > version then the most # recent published profile. # function CanPublish() { $profileid = $this->profileid(); # Already published. Might support unpublish at some point. if ($this->published()) return 0; $query_result = DBQueryWarn("select version from apt_profile_versions ". "where profileid='$profileid' and ". " published is not null ". "order by version desc limit 1"); if (!$query_result || !mysql_num_rows($query_result)) { return -1; } $row = mysql_fetch_row($query_result); $vers = $row[0]; return ($this->version() > $row[0] ? 1 : 0); } # # A profile can be modified if it is a >= version then the most # recent published profile. # function CanModify() { $profileid = $this->profileid(); $query_result = DBQueryWarn("select version from apt_profile_versions ". "where profileid='$profileid' and ". " published is not null ". "order by version desc limit 1"); if (!$query_result || !mysql_num_rows($query_result)) { return -1; } $row = mysql_fetch_row($query_result); $vers = $row[0]; return ($this->version() >= $row[0] ? 1 : 0); } # # Has a profile been instantiated? # function HasActivity() { $profileid = $this->profileid(); $query_result = DBQueryWarn("select count(h.uuid) from apt_instance_history as h ". "where h.profile_id='$profileid'"); if (!$query_result) { return 0; } if (mysql_num_rows($query_result)) { $row = mysql_fetch_row($query_result); if ($row[0] > 0) { return 1; } } $query_result = DBQueryWarn("select count(uuid) from apt_instances ". "where profile_id='$profileid'"); if (!$query_result) { return 0; } if (mysql_num_rows($query_result)) { $row = mysql_fetch_row($query_result); if ($row[0] > 0) { return 1; } } return 0; } # # Permission check; does user have permission to instantiate the # profile. At the moment, view/instantiate are the same. # function CanInstantiate($user) { $profileid = $this->profileid(); if (ISADMIN()) { return 1; } if ($this->shared() || $this->ispublic() || $this->creator_idx() == $user->uid_idx()) { return 1; } # Otherwise a project membership test. $project = Project::Lookup($this->pid_idx()); if (!$project) { return 0; } $isapproved = 0; if ($project->IsMember($user, $isapproved) && $isapproved) { return 1; } return 0; } function CanView($user) { return $this->CanInstantiate($user); } function CanClone($user) { return $this->CanInstantiate($user); } function CanEdit($user) { if ($this->creator_idx() == $user->uid_idx() || ISADMIN()) return 1; return 0; } function CanDelete($user) { # Want to know if the project is APT or Cloud/Emulab. APT projects # may not delete profiles (yet). $project = Project::Lookup($this->pid_idx()); if (!$project) { return 0; } if (!$this->IsHead()) { return 0; } if (ISADMIN() || STUDLY()) { return 1; } if (!$project->isAPT()) { return 1; } # APT profiles may not be deleted if published. if (!$this->published()) { return 1; } return 0; } function UsageInfo($user) { $profile_id = $this->profileid(); $userclause = ""; if ($user) { $creator_idx = $user->idx(); $userclause = "and creator_idx='$creator_idx' "; } # # This is last used. # $query_result = DBQueryFatal("select max(UNIX_TIMESTAMP(created)) ". " from apt_instances ". "where profile_id='$profile_id' ". $userclause); $row = mysql_fetch_row($query_result); if (!$row[0]) { $query_result = DBQueryFatal("select max(UNIX_TIMESTAMP(created)) ". " from apt_instance_history ". "where profile_id='$profile_id' ". $userclause); $row = mysql_fetch_row($query_result); } if (!$row[0]) { return array(0, 0); } $lastused = $row[0]; # # Now we want number of times used. # $count = 0; $query_result = DBQueryFatal("select ". "(select count(profile_id) ". " from apt_instances ". " where profile_id='$profile_id' ". $userclause . ") as count1, ". "(select count(profile_id) ". " from apt_instance_history ". " where profile_id='$profile_id' ". $userclause . ") as count2"); if (mysql_num_rows($query_result)) { $row = mysql_fetch_row($query_result); $count = ($row[0] ? $row[0] : 0) + ($row[1] ? $row[1] : 0); } return array($lastused, $count); } function isFavorite($user) { if (!$user) { return 0; } $profile_id = $this->profileid(); $user_idx = $user->idx(); $query_result = DBQueryFatal("select * from apt_profile_favorites ". "where uid_idx='$user_idx' and ". " profileid='$profile_id'"); return mysql_num_rows($query_result); } function MarkFavorite($user) { $profile_id = $this->profileid(); $user_uid = $user->uid(); $user_idx = $user->idx(); if (!DBQueryWarn("replace into apt_profile_favorites set ". " uid='$user_uid',uid_idx='$user_idx', ". " profileid='$profile_id',marked=now()")) { return -1; } return 0; } function ClearFavorite($user) { $profile_id = $this->profileid(); $user_uid = $user->uid(); $user_idx = $user->idx(); if (!DBQueryWarn("delete from apt_profile_favorites ". "where uid_idx='$user_idx' and ". " profileid='$profile_id'")) { return -1; } return 0; } function BestAggregate($rspec = null) { if (!$rspec) { $rspec = $this->rspec(); } $parsed_xml = simplexml_load_string($rspec); foreach ($parsed_xml->node as $node) { # No XEN VMs on Cloudlab yet. if ($node->sliver_type && $node->sliver_type["name"] && $node->sliver_type["name"] == "emulab-xen") { return "Utah APT"; } if ($node->hardware_type && $node->hardware_type["name"]) { if ($node->hardware_type["name"] == "m400") { return "Utah Cloudlab"; } elseif ($node->hardware_type["name"] == "dl360") { return "Utah DDC"; } elseif ($node->hardware_type["name"] == "r320" || $node->hardware_type["name"] == "c6220") { return "Utah APT"; } } # Check URL if (! ($node->sliver_type && $node->sliver_type->disk_image && ($node->sliver_type->disk_image["url"] || $node->sliver_type->disk_image["name"]))) { continue; } if ($node->sliver_type->disk_image["name"]) { $name = $node->sliver_type->disk_image["name"]; if (preg_match("/^http/", $name)) { $url = $name; } else { # # The only image that runs on Cloudlab is UBUNTU14-64-ARM # if (preg_match("/ARM/", $name) || preg_match("/HPC/", $name) || preg_match("/OSCNF/", $name)) { return "Utah Cloudlab"; } return "Utah APT"; } } else { $url = $node->sliver_type->disk_image["url"]; } if (preg_match("/utah\.cloudlab\.us/", $url)) { return "Utah Cloudlab"; } if (preg_match("/emulab\.net/", $url) || preg_match("/geniracks\.net/", $url) || preg_match("/instageni/", $url)) { return "Utah APT"; } } return null; } function GenerateFormFragment() { $json_data = $this->paramdefs(); if (!$json_data || $json_data == "") { return ""; } $fields = json_decode($json_data); $defaults = array(); $formBasic = ""; $formAdvanced = ""; $formGroups = ""; while (list ($name, $val) = each ($fields)) { $form = ""; $type = $val->type; $prompt = $val->description; $defval = $val->defaultValue; $options = $val->legalValues; $longhelp = $val->longDescription; $advanced = $val->advanced; $groupId = $val->groupId; $groupName = $val->groupName; $hasGroup = false; $data_help_string = ""; $advanced_attr = ""; $defaults[$name] = $defval; if (!isset($prompt) || !$prompt) { $prompt = $name; } if (!isset($advanced)) { $advanced = false; } # Let advanced-tagged params dominate groupId; we don't generate groupId yet anyway. if ($advanced) { $advanced_attr = " pp-param-group='advanced' pp-param-group-name='Advanced Parameters'"; } else if (isset($groupId) && $groupId && isset($groupName) && $groupName) { $advanced_attr = " pp-param-group='$groupId' pp-param-group-name='$groupName'"; $hasGroup = true; } if (isset($longhelp) && $longhelp) { $data_help_string = "data-help='$longhelp'"; } if ($type == "boolean") { $form .= " ". " style='margin: 0px; height: 34px;' ". " class='format-me' ". " data-key='$name' ". " data-label='$prompt' ". " $data_help_string $advanced_attr". " value='checked' ". " type='checkbox'>"; if ($defval) { $defaults[$name] = "checked"; } else { $defaults[$name] = ""; } } elseif ($options) { $form .= ""; } else { $form .= ""; } if ($advanced) { $formAdvanced .= $form; } else if ($hasGroup) { $formGroups .= $form; } else { $formBasic .= $form; } } $finalForm = $formBasic . $formAdvanced . $formGroups; return array($finalForm, $defaults); } } ?>