Overview
  • Namespace
  • Class

Namespaces

  • OpenCloud
    • Autoscale
      • Resource
    • CloudMonitoring
      • Collection
      • Exception
      • Resource
    • Common
      • Collection
      • Constants
      • Exceptions
      • Http
        • Message
      • Log
      • Resource
      • Service
    • Compute
      • Constants
      • Exception
      • Resource
    • Database
      • Resource
    • DNS
      • Collection
      • Resource
    • Identity
      • Constants
      • Resource
    • Image
      • Enum
      • Resource
        • JsonPatch
        • Schema
    • LoadBalancer
      • Collection
      • Enum
      • Resource
    • Networking
      • Resource
    • ObjectStore
      • Constants
      • Exception
      • Resource
      • Upload
    • Orchestration
      • Resource
    • Queues
      • Collection
      • Exception
      • Resource
    • Volume
      • Resource

Classes

  • OpenCloud\Volume\Resource\Snapshot
  • OpenCloud\Volume\Resource\Volume
  • OpenCloud\Volume\Resource\VolumeType
  1 <?php
  2 /**
  3  * Copyright 2012-2014 Rackspace US, Inc.
  4  *
  5  * Licensed under the Apache License, Version 2.0 (the "License");
  6  * you may not use this file except in compliance with the License.
  7  * You may obtain a copy of the License at
  8  *
  9  * http://www.apache.org/licenses/LICENSE-2.0
 10  *
 11  * Unless required by applicable law or agreed to in writing, software
 12  * distributed under the License is distributed on an "AS IS" BASIS,
 13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  * See the License for the specific language governing permissions and
 15  * limitations under the License.
 16  */
 17 
 18 namespace OpenCloud\Compute\Resource;
 19 
 20 use OpenCloud\Common\Resource\NovaResource;
 21 use OpenCloud\DNS\Resource\HasPtrRecordsInterface;
 22 use OpenCloud\Image\Resource\ImageInterface;
 23 use OpenCloud\Networking\Resource\NetworkInterface;
 24 use OpenCloud\Volume\Resource\Volume;
 25 use OpenCloud\Common\Exceptions;
 26 use OpenCloud\Common\Http\Message\Formatter;
 27 use OpenCloud\Common\Lang;
 28 use OpenCloud\Compute\Constants\ServerState;
 29 use OpenCloud\Compute\Service;
 30 
 31 /**
 32  * A virtual machine (VM) instance in the Cloud Servers environment.
 33  *
 34  * @note This implementation supports extension attributes OS-DCF:diskConfig,
 35  * RAX-SERVER:bandwidth, rax-bandwidth:bandwidth.
 36  */
 37 class Server extends NovaResource implements HasPtrRecordsInterface
 38 {
 39     /**
 40      * The server status. {@see \OpenCloud\Compute\Constants\ServerState} for supported types.
 41      *
 42      * @var string
 43      */
 44     public $status;
 45 
 46     /**
 47      * @var string The time stamp for the last update.
 48      */
 49     public $updated;
 50 
 51     /**
 52      * The compute provisioning algorithm has an anti-affinity property that
 53      * attempts to spread customer VMs across hosts. Under certain situations,
 54      * VMs from the same customer might be placed on the same host. $hostId
 55      * represents the host your server runs on and can be used to determine this
 56      * scenario if it is relevant to your application.
 57      *
 58      * @var string
 59      */
 60     public $hostId;
 61 
 62     /**
 63      * @var type Public and private IP addresses for this server.
 64      */
 65     public $addresses;
 66 
 67     /**
 68      * @var array Server links.
 69      */
 70     public $links;
 71 
 72     /**
 73      * The Image for this server.
 74      *
 75      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Images-d1e4435.html
 76      * @var ImageInterface
 77      */
 78     public $image;
 79 
 80     /**
 81      * The bootable volume for this server.
 82      *
 83      * @var Volume
 84      */
 85     public $volume;
 86 
 87     /**
 88      * Whether to delete the bootable volume when the server is terminated (deleted).
 89      * @var boolean
 90      */
 91      public $volumeDeleteOnTermination;
 92 
 93     /**
 94      * The Flavor for this server.
 95      *
 96      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/List_Flavors-d1e4188.html
 97      * @var type
 98      */
 99     public $flavor;
100 
101     /**
102      * @var type
103      */
104     public $networks = array();
105 
106     /**
107      * @var string The server ID.
108      */
109     public $id;
110 
111     /**
112      * @var string The user ID.
113      */
114     public $user_id;
115 
116     /**
117      * @var string The server name.
118      */
119     public $name;
120 
121     /**
122      * @var string The time stamp for the creation date.
123      */
124     public $created;
125 
126     /**
127      * @var string The tenant ID.
128      */
129     public $tenant_id;
130 
131     /**
132      * @var string The public IP version 4 access address.
133      */
134     public $accessIPv4;
135 
136     /**
137      * @var string The public IP version 6 access address.
138      */
139     public $accessIPv6;
140 
141     /**
142      * The build completion progress, as a percentage. Value is from 0 to 100.
143      * @var int
144      */
145     public $progress;
146 
147     /**
148      * @var string The root password (only populated on server creation).
149      */
150     public $adminPass;
151 
152     /**
153      * @var mixed Metadata key and value pairs.
154      */
155     public $metadata;
156 
157     /**
158      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ext_status.html
159      * @var string Virtual machine status.
160      */
161     public $extendedStatus;
162 
163     /**
164      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ext_status.html
165      * @var string Status indicating a running task
166      */
167     public $taskStatus;
168 
169     /**
170      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ext_status.html
171      * @var int Power status of the VM
172      */
173     public $powerStatus;
174 
175     protected static $json_name = 'server';
176     protected static $url_resource = 'servers';
177 
178     /** @var string|object Keypair or string representation of keypair name */
179     public $keypair;
180 
181     /**
182      * @var array Uploaded file attachments
183      */
184     private $personality = array();
185 
186     /**
187      * @var type Image reference (for create)
188      */
189     private $imageRef;
190 
191     /**
192      * @var type Flavor reference (for create)
193      */
194     private $flavorRef;
195 
196     /**
197      * Cloud-init boot executable code
198      * @var string
199      */
200     public $user_data;
201 
202     /**
203      * {@inheritDoc}
204      */
205     protected $aliases = array(
206         'OS-EXT-STS:vm_state'    => 'extendedStatus',
207         'OS-EXT-STS:task_state'  => 'taskStatus',
208         'OS-EXT-STS:power_state' => 'powerStatus',
209     );
210 
211     /**
212      * Creates a new Server object and associates it with a Compute service
213      *
214      * @param mixed $info
215      *      * If NULL, an empty Server object is created
216      *      * If an object, then a Server object is created from the data in the
217      *      object
218      *      * If a string, then it's treated as a Server ID and retrieved from the
219      *      service
220      *      The normal use case for SDK clients is to treat it as either NULL or an
221      *      ID. The object value parameter is a special case used to construct
222      *      a Server object from a ServerList element to avoid a secondary
223      *      call to the Service.
224      * @throws ServerNotFound if a 404 is returned
225      * @throws UnknownError if another error status is reported
226      */
227     public function __construct(Service $service, $info = null)
228     {
229         // make the service persistent
230         parent::__construct($service, $info);
231 
232         // the metadata item is an object, not an array
233         $this->metadata = $this->metadata();
234     }
235 
236     /**
237      * Returns the primary external IP address of the server
238      *
239      * This function is based upon the accessIPv4 and accessIPv6 values.
240      * By default, these are set to the public IP address of the server.
241      * However, these values can be modified by the user; this might happen,
242      * for example, if the server is behind a firewall and needs to be
243      * routed through a NAT device to be reached.
244      *
245      * @api
246      * @param integer $type the type of IP version (4 or 6) to return
247      * @return string IP address
248      */
249     public function ip($type = null)
250     {
251         switch ($type) {
252             default:
253             case 4:
254                 $value = $this->accessIPv4;
255                 break;
256             case 6:
257                 $value = $this->accessIPv6;
258                 break;
259         }
260 
261         return $value;
262     }
263 
264     /**
265      * {@inheritDoc}
266      */
267     public function create($params = array())
268     {
269         $this->id = null;
270         $this->status = null;
271 
272         if (isset($params['imageId'])) {
273             $this->imageRef = $params['imageId'];
274         }
275 
276         if (isset($params['flavorId'])) {
277             $this->flavorRef = $params['flavorId'];
278         }
279 
280         return parent::create($params);
281     }
282 
283     /**
284      * Rebuilds an existing server
285      *
286      * @api
287      * @param array $params - an associative array of key/value pairs of
288      *                      attributes to set on the new server
289      */
290     public function rebuild($params = array())
291     {
292         if (!isset($params['adminPass'])) {
293             throw new Exceptions\RebuildError(
294                 Lang::Translate('adminPass required when rebuilding server')
295             );
296         }
297 
298         if (!isset($params['image'])) {
299             throw new Exceptions\RebuildError(
300                 Lang::Translate('image required when rebuilding server')
301             );
302         }
303 
304         $object = (object) array(
305             'rebuild' => (object) array(
306                     'imageRef'  => $params['image']->id(),
307                     'adminPass' => $params['adminPass'],
308                     'name'      => (array_key_exists('name', $params) ? $params['name'] : $this->name)
309                 )
310         );
311 
312         return $this->action($object);
313     }
314 
315     /**
316      * Reboots a server
317      *
318      * A "soft" reboot requests that the operating system reboot itself; a "hard" reboot is the equivalent of pulling
319      * the power plug and then turning it back on, with a possibility of data loss.
320      *
321      * @api
322      * @param  string $type A particular reboot State. See Constants\ServerState for string values.
323      * @return \Guzzle\Http\Message\Response
324      */
325     public function reboot($type = null)
326     {
327         if (!$type) {
328             $type = ServerState::REBOOT_STATE_HARD;
329         }
330 
331         $object = (object) array('reboot' => (object) array('type' => $type));
332 
333         return $this->action($object);
334     }
335 
336     /**
337      * Creates a new image from a server
338      *
339      * @api
340      * @param string $name     The name of the new image
341      * @param array  $metadata Optional metadata to be stored on the image
342      * @return boolean|Image New Image instance on success; FALSE on failure
343      * @throws Exceptions\ImageError
344      */
345     public function createImage($name, $metadata = array())
346     {
347         if (empty($name)) {
348             throw new Exceptions\ImageError(
349                 Lang::translate('Image name is required to create an image')
350             );
351         }
352 
353         // construct a createImage object for jsonization
354         $object = (object) array('createImage' => (object) array(
355                 'name'     => $name,
356                 'metadata' => (object) $metadata
357             ));
358 
359         $response = $this->action($object);
360 
361         if (!$response || !($location = $response->getHeader('Location'))) {
362             return false;
363         }
364 
365         return new Image($this->getService(), basename($location));
366     }
367 
368     /**
369      * Schedule daily image backups
370      *
371      * @api
372      * @param mixed $retention - false (default) indicates you want to
373      *                         retrieve the image schedule. $retention <= 0 indicates you
374      *                         want to delete the current schedule. $retention > 0 indicates
375      *                         you want to schedule image backups and you would like to
376      *                         retain $retention backups.
377      * @return mixed an object or FALSE on error
378      * @throws Exceptions\ServerImageScheduleError if an error is encountered
379      */
380     public function imageSchedule($retention = false)
381     {
382         $url = $this->getUrl('rax-si-image-schedule');
383 
384         if ($retention === false) {
385             // Get current retention
386             $request = $this->getClient()->get($url);
387         } elseif ($retention <= 0) {
388             // Delete image schedule
389             $request = $this->getClient()->delete($url);
390         } else {
391             // Set image schedule
392             $object = (object) array('image_schedule' =>
393                                         (object) array('retention' => $retention)
394             );
395             $body = json_encode($object);
396             $request = $this->getClient()->post($url, self::getJsonHeader(), $body);
397         }
398 
399         $body = Formatter::decode($request->send());
400 
401         return (isset($body->image_schedule)) ? $body->image_schedule : (object) array();
402     }
403 
404     /**
405      * Initiates the resize of a server
406      *
407      * @api
408      * @param  Flavor  $flavorRef a Flavor object indicating the new server size
409      * @return boolean TRUE on success; FALSE on failure
410      */
411     public function resize(Flavor $flavorRef)
412     {
413         // construct a resize object for jsonization
414         $object = (object) array(
415             'resize' => (object) array('flavorRef' => $flavorRef->id)
416         );
417 
418         return $this->action($object);
419     }
420 
421     /**
422      * confirms the resize of a server
423      *
424      * @api
425      * @return boolean TRUE on success; FALSE on failure
426      */
427     public function resizeConfirm()
428     {
429         $object = (object) array('confirmResize' => null);
430         $response = $this->action($object);
431         $this->refresh($this->id);
432 
433         return $response;
434     }
435 
436     /**
437      * reverts the resize of a server
438      *
439      * @api
440      * @return boolean TRUE on success; FALSE on failure
441      */
442     public function resizeRevert()
443     {
444         $object = (object) array('revertResize' => null);
445 
446         return $this->action($object);
447     }
448 
449     /**
450      * Sets the root password on the server
451      *
452      * @api
453      * @param  string  $newPassword The new root password for the server
454      * @return boolean TRUE on success; FALSE on failure
455      */
456     public function setPassword($newPassword)
457     {
458         $object = (object) array(
459             'changePassword' => (object) array('adminPass' => $newPassword)
460         );
461 
462         return $this->action($object);
463     }
464 
465     /**
466      * Puts the server into *rescue* mode
467      *
468      * @api
469      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/rescue_mode.html
470      * @return string the root password of the rescue server
471      * @throws Exceptions\ServerActionError if the server has no ID (i.e., has not
472      *      been created yet)
473      */
474     public function rescue()
475     {
476         $this->checkExtension('os-rescue');
477 
478         if (empty($this->id)) {
479             throw new Exceptions\ServerActionError(
480                 Lang::translate('Server has no ID; cannot Rescue()')
481             );
482         }
483 
484         $data = (object) array('rescue' => 'none');
485 
486         $response = $this->action($data);
487         $body = Formatter::decode($response);
488 
489         return (isset($body->adminPass)) ? $body->adminPass : false;
490     }
491 
492     /**
493      * Takes the server out of RESCUE mode
494      *
495      * @api
496      * @link http://docs.rackspace.com/servers/api/v2/cs-devguide/content/rescue_mode.html
497      * @return HttpResponse
498      * @throws Exceptions\ServerActionError if the server has no ID (i.e., has not
499      *      been created yet)
500      */
501     public function unrescue()
502     {
503         $this->checkExtension('os-rescue');
504 
505         if (!isset($this->id)) {
506             throw new Exceptions\ServerActionError(Lang::translate('Server has no ID; cannot Unescue()'));
507         }
508 
509         $object = (object) array('unrescue' => null);
510 
511         return $this->action($object);
512     }
513 
514     /**
515      * Retrieves the metadata associated with a Server.
516      *
517      * If a metadata item name is supplied, then only the single item is
518      * returned. Otherwise, the default is to return all metadata associated
519      * with a server.
520      *
521      * @api
522      * @param string $key - the (optional) name of the metadata item to return
523      * @return ServerMetadata object
524      * @throws Exceptions\MetadataError
525      */
526     public function metadata($key = null)
527     {
528         return new ServerMetadata($this, $key);
529     }
530 
531     /**
532      * Returns the IP address block for the Server or for a specific network.
533      *
534      * @api
535      * @param string $network - if supplied, then only the IP(s) for the
536      *                        specified network are returned. Otherwise, all IPs are returned.
537      * @return object
538      * @throws Exceptions\ServerIpsError
539      */
540     public function ips($network = null)
541     {
542         $url = Lang::noslash($this->Url('ips/' . $network));
543 
544         $response = $this->getClient()->get($url)->send();
545         $body = Formatter::decode($response);
546 
547         return (isset($body->addresses)) ? $body->addresses :
548             ((isset($body->network)) ? $body->network : (object) array());
549     }
550 
551     /**
552      * Attaches a volume to a server
553      *
554      * Requires the os-volumes extension. This is a synonym for
555      * `VolumeAttachment::create()`
556      *
557      * @api
558      * @param OpenCloud\Volume\Resource\Volume $volume The volume to attach. If
559      *                                                 "auto" is specified (the default), then the first available
560      *                                                 device is used to mount the volume (for example, if the primary
561      *                                                 disk is on `/dev/xvhda`, then the new volume would be attached
562      *                                                 to `/dev/xvhdb`).
563      * @param string                           $device the device to which to attach it
564      */
565     public function attachVolume(Volume $volume, $device = 'auto')
566     {
567         $this->checkExtension('os-volumes');
568 
569         return $this->volumeAttachment()->create(array(
570             'volumeId' => $volume->id,
571             'device'   => ($device == 'auto' ? null : $device)
572         ));
573     }
574 
575     /**
576      * Removes a volume attachment from a server
577      *
578      * Requires the os-volumes extension. This is a synonym for
579      * `VolumeAttachment::delete()`
580      * @param OpenCloud\Volume\Resource\Volume $volume The volume to remove
581      */
582     public function detachVolume(Volume $volume)
583     {
584         $this->checkExtension('os-volumes');
585 
586         return $this->volumeAttachment($volume->id)->delete();
587     }
588 
589     /**
590      * Returns a VolumeAttachment object
591      *
592      */
593     public function volumeAttachment($id = null)
594     {
595         $resource = new VolumeAttachment($this->getService());
596         $resource->setParent($this)->populate($id);
597 
598         return $resource;
599     }
600 
601     /**
602      * Returns a Collection of VolumeAttachment objects
603      * @return Collection
604      */
605     public function volumeAttachmentList()
606     {
607         return $this->getService()->collection(
608             'OpenCloud\Compute\Resource\VolumeAttachment', null, $this
609         );
610     }
611 
612     /**
613      * Adds a "personality" file to be uploaded during create() or rebuild()
614      *
615      * @api
616      * @param string $path The path where the file will be stored on the
617      *                     target server (up to 255 characters)
618      * @param string $data the file contents (max size set by provider)
619      * @return void
620      */
621     public function addFile($path, $data)
622     {
623         $this->personality[$path] = base64_encode($data);
624     }
625 
626     /**
627      * Returns a console connection
628      * Note: Where is this documented?
629      *
630      * @codeCoverageIgnore
631      */
632     public function console($type = 'novnc')
633     {
634         $action = (strpos('spice', $type) !== false) ? 'os-getSPICEConsole' : 'os-getVNCConsole';
635         $object = (object) array($action => (object) array('type' => $type));
636 
637         $response = $this->action($object);
638         $body = Formatter::decode($response);
639 
640         return (isset($body->console)) ? $body->console : false;
641     }
642 
643     protected function createJson()
644     {
645         // Convert some values
646         $this->metadata->sdk = $this->getService()->getClient()->getUserAgent();
647 
648         if ($this->image instanceof ImageInterface) {
649             $this->imageRef = $this->image->getId();
650         }
651         if ($this->flavor instanceof Flavor) {
652             $this->flavorRef = $this->flavor->id;
653         }
654 
655         // Base object
656         $server = (object) array(
657             'name'      => $this->name,
658             'imageRef'  => $this->imageRef,
659             'flavorRef' => $this->flavorRef
660         );
661 
662         if ($this->metadata->count()) {
663             $server->metadata = $this->metadata->toArray();
664         }
665 
666         // Boot from volume
667         if ($this->volume instanceof Volume) {
668             $this->checkExtension('os-block-device-mapping-v2-boot');
669 
670             $server->block_device_mapping_v2 = array();
671             $server->block_device_mapping_v2[] = (object) array(
672                 'source_type' => 'volume',
673                 'destination_type' => 'volume',
674                 'uuid' => $this->volume->id,
675                 'boot_index' => 0,
676                 'delete_on_termination' => (boolean) $this->volumeDeleteOnTermination
677             );
678         }
679 
680         // Networks
681         if (is_array($this->networks) && count($this->networks)) {
682             $server->networks = array();
683 
684             foreach ($this->networks as $network) {
685                 if (!$network instanceof NetworkInterface) {
686                     throw new Exceptions\InvalidParameterError(sprintf(
687                         'When creating a server, the "networks" key must be an ' .
688                         'array of objects which implement OpenCloud\Networking\Resource\NetworkInterface;' .
689                         'variable passed in was a [%s]',
690                         gettype($network)
691                     ));
692                 }
693                 if (!($networkId = $network->getId())) {
694                     $this->getLogger()->warning('When creating a server, the '
695                         . 'network objects passed in must have an ID'
696                     );
697                     continue;
698                 }
699                 // Stock networks array
700                 $server->networks[] = (object) array('uuid' => $networkId);
701             }
702         }
703 
704         // Personality files
705         if (!empty($this->personality)) {
706             $server->personality = array();
707             foreach ($this->personality as $path => $data) {
708                 // Stock personality array
709                 $server->personality[] = (object) array(
710                     'path'     => $path,
711                     'contents' => $data
712                 );
713             }
714         }
715 
716         // Keypairs
717         if (!empty($this->keypair)) {
718             if (is_string($this->keypair)) {
719                 $server->key_name = $this->keypair;
720             } elseif (isset($this->keypair['name']) && is_string($this->keypair['name'])) {
721                 $server->key_name = $this->keypair['name'];
722             } elseif ($this->keypair instanceof Keypair && $this->keypair->getName()) {
723                 $server->key_name = $this->keypair->getName();
724             }
725         }
726 
727         // Cloud-init executable
728         if (!empty($this->user_data)) {
729             $server->user_data = $this->user_data;
730         }
731 
732         return (object) array('server' => $server);
733     }
734 
735     protected function updateJson($params = array())
736     {
737         return (object) array('server' => (object) $params);
738     }
739 
740     /**
741      * Suspend a server
742      *
743      * A suspend request suspend an instance, its VM state is stored on disk, all memory is written
744      * to disk, and the virtual machine is stopped. Suspending an instance is similar to placing a
745      * device in hibernation; memory and vCPUs become available to create other instances.
746      *
747      * @api
748      * @return \Guzzle\Http\Message\Response
749      */
750     public function suspend()
751     {
752         // The suspend action is only available when the os-admin-actions extension is installed.
753         $this->checkExtension('os-admin-actions');
754 
755         $object = (object) array('suspend' => 'none');
756 
757         return $this->action($object);
758     }
759 
760     /**
761      * Resume a server
762      *
763      * A resume request resumes a suspended instance, its VM state was stored on disk, all memory was written
764      * to disk, and the virtual machine was stopped. Resuming a suspended instance is similar to resuming a
765      * device from hibernation.
766      *
767      * @api
768      * @return \Guzzle\Http\Message\Response
769      */
770     public function resume()
771     {
772         // The resume action is only available when the os-admin-actions extension is installed.
773         $this->checkExtension('os-admin-actions');
774 
775         $object = (object) array('resume' => 'none');
776 
777         return $this->action($object);
778     }
779 
780     /**
781      * Get server diagnostics
782      *
783      * Gets basic usage data for a specified server.
784      *
785      * @api
786      * @return object
787      */
788     public function diagnostics()
789     {
790         // The diagnostics is only available when the os-server-diagnostics extension is installed.
791         $this->checkExtension('os-server-diagnostics');
792 
793         $url = $this->getUrl('diagnostics');
794 
795         $response = $this->getClient()->get($url)->send();
796         $body = Formatter::decode($response);
797 
798         return $body ?: (object) array();
799     }
800 
801     /**
802      * Start a server
803      *
804      * Starts a stopped server and changes its status to ACTIVE.
805      *
806      * @api
807      * @return \Guzzle\Http\Message\Response
808      */
809     public function start()
810     {
811         // The start action is only available when the os-server-start-stop extension is installed.
812         $this->checkExtension('os-server-start-stop');
813 
814         $object = (object) array('os-start' => null);
815 
816         return $this->action($object);
817     }
818 
819     /**
820      * Stop a server
821      *
822      * Stops a running server and changes its status to STOPPED.
823      *
824      * @api
825      * @return \Guzzle\Http\Message\Response
826      */
827     public function stop()
828     {
829         // The stop action is only available when the os-server-start-stop extension is installed.
830         $this->checkExtension('os-server-start-stop');
831 
832         $object = (object) array('os-stop' => null);
833 
834         return $this->action($object);
835     }
836 }
837 
API documentation generated by ApiGen