/** * Returns name of this database. Because it's so important (i.e. as an * identifier), it will throw an error if not set/empty. * * @return type * @throws Exceptions\DatabaseNameError */ public function getName() { if (empty($this->name)) { throw new Exceptions\DatabaseNameError(Lang::translate('The database does not have a Url yet')); } return $this->name; }
/** * creates the JSON for update * * @return stdClass */ protected function updateJson($params = array()) { if (!$this->getUpdateKeys()) { throw new Exceptions\UpdateError(Lang::translate('Missing [updateKeys]')); } return $this->getJson($this->getUpdateKeys()); }
/** * constructur ensures that the record type is PTR */ public function __construct($parent, $info = null) { $this->type = 'PTR'; parent::__construct($parent, $info); if ($this->type != 'PTR') { throw new Exceptions\RecordTypeError(sprintf(Lang::translate('Invalid record type [%s], must be PTR'), $this->type)); } }
public function __construct(Client $client, $type = null, $name = null, $region = null, $urlType = null) { parent::__construct($client, $type, $name, $region, $urlType); if (strpos($this->getUrl()->getPath(), '/v1') !== false) { throw new Exceptions\UnsupportedVersionError(sprintf(Lang::translate('Sorry; API version /v1 is not supported [%s]'), $this->getUrl())); } $this->loadNamespaces(); }
/** * sets the shared secret value for the TEMP_URL * * @param string $secret the shared secret * @return HttpResponse */ public function SetTempUrlSecret($secret) { $response = $this->Request($this->Url(), 'POST', array('X-Account-Meta-Temp-Url-Key' => $secret)); if ($response->HttpStatus() > 204) { throw new Exceptions\HttpError(sprintf(Lang::translate('Error in request, status [%d] for URL [%s] [%s]'), $response->HttpStatus(), $this->Url(), $response->HttpBody())); } return $response; }
/** * Sets the shared secret value for the TEMP_URL * * @param string $secret the shared secret * @return HttpResponse */ public function setTempUrlSecret($secret) { $response = $this->request($this->url(), 'POST', array('X-Account-Meta-Temp-Url-Key' => $secret)); // @codeCoverageIgnoreStart if ($response->httpStatus() > 204) { throw new Exceptions\HttpError(sprintf(Lang::translate('Error in request, status [%d] for URL [%s] [%s]'), $response->httpStatus(), $this->url(), $response->httpBody())); } // @codeCoverageIgnoreEnd return $response; }
/** * Deletes an isolated network * * @api * @return \OpenCloud\HttpResponse * @throws NetworkDeleteError if HTTP status is not Success */ public function Delete() { switch ($this->id) { case RAX_PUBLIC: case RAX_PRIVATE: throw new Exceptions\DeleteError(Lang::translate('Network may not be deleted')); break; default: return parent::Delete(); break; } }
/** * Called when creating a new Compute service object * * _NOTE_ that the order of parameters for this is *different* from the * parent Service class. This is because the earlier parameters are the * ones that most typically change, whereas the later ones are not * modified as often. * * @param \OpenCloud\Identity $conn - a connection object * @param string $serviceRegion - identifies the region of this Compute * service * @param string $urltype - identifies the URL type ("publicURL", * "privateURL") * @param string $serviceName - identifies the name of the service in the * catalog */ public function __construct(OpenStack $conn, $serviceName, $serviceRegion, $urltype) { $this->getLogger()->info(Lang::translate('Initializing compute...')); parent::__construct($conn, 'compute', $serviceName, $serviceRegion, $urltype); // check the URL version $path = parse_url($this->Url(), PHP_URL_PATH); if (substr($path, 0, 3) == '/v1') { throw new Exceptions\UnsupportedVersionError(sprintf(Lang::translate('Sorry; API version /v1 is not supported [%s]'), $this->Url())); } $this->load_namespaces(); $this->_namespaces[] = 'OS-FLV-DISABLED'; }
/** * Returns the JSON object for creating the backup */ protected function createJson() { if (!isset($this->instanceId)) { throw new Exceptions\BackupInstanceError(Lang::translate('The `instanceId` attribute is required and must be a string')); } if (!isset($this->name)) { throw new Exceptions\BackupNameError(Lang::translate('Backup name is required')); } $out = ['backup' => ['name' => $this->name, 'instance' => $this->instanceId]]; if (isset($this->description)) { $out['backup']['description'] = $this->description; } return (object) $out; }
/** * Always throws an error; updates are not permitted * * @throws NetworkUpdateError always */ public function Update($params = array()) { throw new Exceptions\NetworkUpdateError(Lang::translate('Isolated networks cannot be updated')); }
/** * returns a (default) name of the object * * The name is constructed by the object class and the object's ID. * * @api * @return string */ public function Name() { return sprintf(Lang::translate('%s-%s'), get_class($this), $this->Parent()->Id()); }
public function getUrl($path = null, array $params = array()) { if (!$this->name) { throw new Exceptions\NoNameError(Lang::translate('Object has no name')); } return $this->container->getUrl($this->name); }
/** * Checks the most recent JSON operation for errors. * * @throws Exceptions\JsonError * @codeCoverageIgnore */ public static function checkJsonError() { switch (json_last_error()) { case JSON_ERROR_NONE: return; case JSON_ERROR_DEPTH: $jsonError = 'JSON error: The maximum stack depth has been exceeded'; break; case JSON_ERROR_STATE_MISMATCH: $jsonError = 'JSON error: Invalid or malformed JSON'; break; case JSON_ERROR_CTRL_CHAR: $jsonError = 'JSON error: Control character error, possibly incorrectly encoded'; break; case JSON_ERROR_SYNTAX: $jsonError = 'JSON error: Syntax error'; break; case JSON_ERROR_UTF8: $jsonError = 'JSON error: Malformed UTF-8 characters, possibly incorrectly encoded'; break; default: $jsonError = 'Unexpected JSON error'; break; } if (isset($jsonError)) { throw new JsonError(Lang::translate($jsonError)); } }
/** * Formats the credentials array (as a string) for authentication * * @return string * @throws Common\Exceptions\CredentialError */ public function getCredentials() { if (!empty($this->secret['username']) && !empty($this->secret['password'])) { $credentials = array('auth' => array('passwordCredentials' => array('username' => $this->secret['username'], 'password' => $this->secret['password']))); if (!empty($this->secret['tenantName'])) { $credentials['auth']['tenantName'] = $this->secret['tenantName']; } elseif (!empty($this->secret['tenantId'])) { $credentials['auth']['tenantId'] = $this->secret['tenantId']; } return json_encode($credentials); } else { throw new Exceptions\CredentialError(Lang::translate('Unrecognized credential secret')); } }
/** * Creates the JSON for creating a new server * * @param string $element creates {server ...} by default, but can also * create {rebuild ...} by changing this parameter * @return json */ protected function CreateJson() { // create a blank object $obj = new \stdClass(); // set a bunch of properties $obj->server = new \stdClass(); $obj->server->imageRef = $this->imageRef; $obj->server->name = $this->name; $obj->server->flavorRef = $this->flavorRef; $obj->server->metadata = $this->metadata; if (is_array($this->networks) && count($this->networks)) { $obj->server->networks = array(); foreach ($this->networks as $net) { if (get_class($net) != 'OpenCloud\\Compute\\Network') { throw new Exceptions\InvalidParameterError(sprintf(Lang::translate('"networks" parameter must be an ' . 'array of Compute\\Network objects; [%s] found'), get_class($net))); } $netobj = new \stdClass(); $netobj->uuid = $net->id; $obj->server->networks[] = $netobj; } } // handle personality files if (count($this->personality)) { $obj->server->personality = array(); foreach ($this->personality as $path => $data) { $fileobj = new \stdClass(); $fileobj->path = $path; $fileobj->contents = $data; $obj->server->personality[] = $fileobj; } } return json_encode($obj); }
/** * Returns the resource name for the URL of the object; must be overridden * in child classes * * For example, a server is `/servers/`, a database instance is * `/instances/`. Must be overridden in child classes. * * @throws Exceptions\UrlError */ public static function resourceName() { if (isset(static::$url_resource)) { return static::$url_resource; } throw new Exceptions\UrlError(sprintf(Lang::translate('No URL resource defined for class [%s] in ResourceName()'), get_class())); }
/** * Called when creating a new Compute service object * * _NOTE_ that the order of parameters for this is *different* from the * parent Service class. This is because the earlier parameters are the * ones that most typically change, whereas the later ones are not * modified as often. * * @param \OpenCloud\Identity $conn - a connection object * @param string $serviceRegion - identifies the region of this Compute * service * @param string $urltype - identifies the URL type ("publicURL", * "privateURL") * @param string $serviceName - identifies the name of the service in the * catalog */ public function __construct(OpenStack $conn, $serviceType, $serviceName, $serviceRegion, $urltype) { parent::__construct($conn, $serviceType, $serviceName, $serviceRegion, $urltype); $this->_url = Lang::noslash(parent::Url()); $this->getLogger()->info(Lang::translate('Initializing Nova...')); }
/** * Generates the JSON string for Create() * * @return \stdClass */ protected function createJson() { if (empty($this->flavor) || !is_object($this->flavor)) { throw new Exceptions\InstanceFlavorError(Lang::translate('The `flavor` attribute is required and must be a Flavor object')); } if (!isset($this->name)) { throw new Exceptions\InstanceError(Lang::translate('Instance name is required')); } return (object) array('instance' => (object) array('flavorRef' => $this->flavor->links[0]->href, 'name' => $this->name, 'volume' => $this->volume)); }
/** * Generic Service factory method * * Contains code reused by the other service factory methods. * * @param string $class the name of the Service class to produce * @param string $name the name of the Compute service to attach to * @param string $region the name of the region to use * @param string $urltype the URL type (normally "publicURL") * @return Service (or subclass such as Compute, ObjectStore) * @throws ServiceValueError */ public function Service($class, $name = null, $region = null, $urltype = null) { // debug message $this->debug('Factory for class [%s] [%s/%s/%s]', $class, $name, $region, $urltype); if (strpos($class, '\\OpenCloud\\') === 0) { $class = str_replace('\\OpenCloud\\', '', $class); } // check for defaults if (!isset($name)) { $name = $this->defaults[$class]['name']; } if (!isset($region)) { $region = $this->defaults[$class]['region']; } if (!isset($urltype)) { $urltype = $this->defaults[$class]['urltype']; } // report errors if (!$name) { throw new Exceptions\ServiceValueError(Lang::translate('No value for ' . $class . ' name')); } if (!$region) { throw new Exceptions\ServiceValueError(Lang::translate('No value for ' . $class . ' region')); } if (!$urltype) { throw new Exceptions\ServiceValueError(Lang::translate('No value for ' . $class . ' URL type')); } // return the object $fullclass = '\\OpenCloud\\' . $class . '\\Service'; return new $fullclass($this, $name, $region, $urltype); }
/** * Executes the current request * * This method actually performs the request using the values set * previously. It throws a OpenCloud\HttpError exception on * any CURL error. * * @return OpenCloud\HttpResponse * @throws OpenCloud\HttpError * * @codeCoverageIgnore */ public function execute() { // set all the headers $headarr = array(); foreach ($this->headers as $name => $value) { $headarr[] = $name . ': ' . $value; } $this->setOption(CURLOPT_HTTPHEADER, $headarr); // set up to retry if necessary $try_counter = 0; do { $data = curl_exec($this->handle); if (curl_errno($this->handle) && $try_counter < $this->retries) { $this->getLogger()->info(Lang::translate('Curl error [%d]; retrying [%s]'), array('error' => curl_errno($this->handle), 'url' => $this->url)); } } while (++$try_counter <= $this->retries && curl_errno($this->handle) != 0); // log retries error if ($this->retries && curl_errno($this->handle)) { throw new HttpRetryError(sprintf(Lang::translate('No more retries available, last error [%d]'), curl_errno($this->handle))); } // check for CURL errors switch (curl_errno($this->handle)) { case 0: // everything's ok break; case 3: throw new HttpUrlError(sprintf(Lang::translate('Malformed URL [%s]'), $this->url)); break; case 28: // timeout throw new HttpTimeoutError(Lang::translate('Operation timed out; check RAXSDK_TIMEOUT value')); break; default: throw new HttpError(sprintf(Lang::translate('HTTP error on [%s], curl code [%d] message [%s]'), $this->url, curl_errno($this->handle), curl_error($this->handle))); } // otherwise, return the HttpResponse return new Response\Http($this, $data); }
public function __set($key, $value) { // if a key was supplied when creating the object, then we can't set // any other values if ($this->key && $key != $this->key) { throw new Exceptions\MetadataKeyError(sprintf(Lang::translate('You cannot set extra values on [%s]'), $this->Url())); } // otherwise, just set it; parent::__set($key, $value); }
/** * Returns the IP address block for the Server or for a specific network * * @api * @param string $network - if supplied, then only the IP(s) for * the specified network are returned. Otherwise, all IPs are returned. * @return object * @throws ServerIpsError */ public function ips($network = null) { $url = Lang::noslash($this->Url('ips/' . $network)); $response = $this->Service()->Request($url); // @codeCoverageIgnoreStart if ($response->HttpStatus() >= 300) { throw new Exceptions\ServerIpsError(sprintf(Lang::translate('Error in Server::ips(), status [%d], response [%s]'), $response->HttpStatus(), $response->HttpBody())); } $object = json_decode($response->httpBody()); $this->checkJsonError(); if (isset($object->addresses)) { return $object->addresses; } elseif (isset($object->network)) { return $object->network; } else { return new \stdClass(); } // @codeCoverageIgnoreEnd }
/** * Returns a Collection of images (class Image) * * This is a factory method and should normally be used instead of creating * an ImageList object directly. * * @api * @param boolean $details - if TRUE (the default), returns complete image * details. Set to FALSE to improve performance, but only return a * minimal set of data * @param array $filter - key/value pairs to pass to the images resource. * The actual values available here are determined by the OpenStack * code and any extensions installed by your cloud provider; * see http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Images-d1e4435.html * for current filters available. * @return Collection */ public function ImageList($details = true, $filter = array()) { // validate arguments if (!is_bool($details)) { throw new Exceptions\InvalidParameterError(Lang::translate('Invalid argument for Compute::ImageList(); boolean required')); } if ($details) { $url = $this->Url('images/detail', $filter); } else { $url = $this->Url('images', $filter); } return $this->Collection('\\OpenCloud\\Compute\\Image', $url); }
/** * Test the validity of certain parameters for the resource. * * @access public * @param array $params (default: array()) * @param bool $debug (default: false) * @return void */ public function test($params = array(), $debug = false) { if (!empty($params)) { foreach ($params as $key => $value) { $this->{$key} = $value; } } $obj = $this->CreateJson(); $json = json_encode($obj); if ($this->CheckJsonError()) { return false; } // send the request $response = $this->Service()->Request($this->testUrl($debug), 'POST', array(), $json); // check the return code if ($response->HttpStatus() > 204) { throw new Exceptions\TestException(sprintf(Lang::translate('Error updating [%s] with [%s], status [%d] response [%s]'), get_class($this), $json, $response->HttpStatus(), $response->HttpBody())); } return $response; }
/** * adds a virtual IP to the load balancer * * You can use the strings `'PUBLIC'` or `'SERVICENET`' to indicate the * public or internal networks, or you can pass the `Id` of an existing * IP address. * * @api * @param string $id either 'public' or 'servicenet' or an ID of an * existing IP address * @param integer $ipVersion either null, 4, or 6 (both, IPv4, or IPv6) * @return void */ public function addVirtualIp($type = 'PUBLIC', $ipVersion = NULL) { $object = new \stdClass(); /** * check for PUBLIC or SERVICENET */ switch (strtoupper($type)) { case 'PUBLIC': case 'SERVICENET': $object->type = strtoupper($type); break; default: $object->id = $type; break; } if ($ipVersion) { switch ($ipVersion) { case 4: $object->version = 'IPV4'; break; case 6: $object->version = 'IPV6'; break; default: throw new Exceptions\DomainError(sprintf(Lang::translate('Value [%s] for ipVersion is not valid'), $ipVersion)); } } /** * If the load balancer exists, we want to add it immediately. * If not, we add it to the virtualIps list and add it when the load * balancer is created. */ if ($this->Id()) { $virtualIp = $this->VirtualIp(); $virtualIp->type = $type; $virtualIp->ipVersion = $object->version; $http = $virtualIp->Create(); $this->getLogger()->info('AddVirtualIp:response [{body}]', array('body' => $http->httpBody())); return $http; } else { // queue it $this->virtualIps[] = $object; } return true; }
/** * Returns the IP address block for the Server or for a specific network. * * @api * @param string $network - if supplied, then only the IP(s) for the * specified network are returned. Otherwise, all IPs are returned. * @return object * @throws Exceptions\ServerIpsError */ public function ips($network = null) { $url = Lang::noslash($this->Url('ips/' . $network)); $response = $this->getClient()->get($url)->send(); $body = Formatter::decode($response); return isset($body->addresses) ? $body->addresses : (isset($body->network) ? $body->network : (object) array()); }
/** * updates are not permitted * * @throws OpenCloud\UpdateError always */ public function update($params = array()) { throw new Exceptions\UpdateError(Lang::translate('Updates are not permitted')); }
/** * Always throws an error; updates are not permitted * * @throws OpenCloud\UpdateError always */ public function Update($params = array()) { throw new Exceptions\UpdateError(Lang::translate('Block storage volumes cannot be updated')); }
/** * Retrieves a single object, parses headers * * @return void * @throws NoNameError, ObjFetchError */ private function fetch() { if (!$this->name) { throw new Exceptions\NoNameError(Lang::translate('Cannot retrieve an unnamed object')); } $response = $this->getService()->request($this->url(), 'HEAD', array('Accept' => '*/*')); // check for errors // @codeCoverageIgnoreStart if ($response->httpStatus() >= 300) { throw new Exceptions\ObjFetchError(sprintf(Lang::translate('Problem retrieving object [%s]'), $this->url())); } // @codeCoverageIgnoreEnd // set headers as metadata? $this->saveResponseHeaders($response); // parse the metadata $this->getMetadata($response); }
/** * deletes are not permitted * * @throws OpenCloud\DeleteError */ public function Delete() { throw new Exceptions\DeleteError(Lang::translate('VolumeType cannot be deleted')); }