1: <?php
2: /**
3: * PHP OpenCloud library.
4: *
5: * @copyright Copyright 2013 Rackspace US, Inc. See COPYING for licensing information.
6: * @license https://www.apache.org/licenses/LICENSE-2.0 Apache 2.0
7: * @version 1.6.0
8: * @author Glen Campbell <glen.campbell@rackspace.com>
9: * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
10: */
11:
12: namespace OpenCloud\DNS;
13:
14: use OpenCloud\Common\Service as AbstractService;
15: use OpenCloud\Common\Lang;
16: use OpenCloud\Common\Exceptions;
17: use OpenCloud\OpenStack;
18: use OpenCloud\Compute\Server;
19:
20: /**
21: * DNS Service.
22: */
23: class Service extends AbstractService
24: {
25:
26: /**
27: * creates a new DNS object
28: *
29: * @param \OpenCloud\OpenStack $conn connection object
30: * @param string $serviceName the name of the service
31: * @param string $serviceRegion (not currently used; DNS is regionless)
32: * @param string $urltype the type of URL
33: */
34: public function __construct(
35: OpenStack $connection,
36: $serviceName,
37: $serviceRegion,
38: $urltype
39: ) {
40:
41: $this->getLogger()->info('Initializing DNS...');
42:
43: parent::__construct(
44: $connection,
45: 'rax:dns',
46: $serviceName,
47: $serviceRegion,
48: $urltype
49: );
50: }
51:
52: /**
53: * returns a DNS::Domain object
54: *
55: * @api
56: * @param mixed $info either the ID, an object, or array of parameters
57: * @return DNS\Domain
58: */
59: public function domain($info = null)
60: {
61: return new Domain($this, $info);
62: }
63:
64: /**
65: * returns a Collection of DNS::Domain objects
66: *
67: * @api
68: * @param array $filter key/value pairs to use as query strings
69: * @return \OpenCloud\Collection
70: */
71: public function domainList($filter = array())
72: {
73: $url = $this->url(Domain::ResourceName(), $filter);
74: return $this->collection('OpenCloud\DNS\Domain', $url);
75: }
76:
77: /**
78: * returns a PtrRecord object for a server
79: *
80: * @param mixed $info ID, array, or object containing record data
81: * @return Record
82: */
83: public function ptrRecord($info = null)
84: {
85: return new PtrRecord($this, $info);
86: }
87:
88: /**
89: * returns a Collection of PTR records for a given Server
90: *
91: * @param \OpenCloud\Compute\Server $server the server for which to
92: * retrieve the PTR records
93: * @return Collection
94: */
95: public function ptrRecordList(Server $server)
96: {
97: $url = $this->url('rdns/' . $server->getService()->name(), array(
98: 'href' => $server->url()
99: ));
100: return $this->collection('\OpenCloud\DNS\PtrRecord', $url);
101: }
102:
103: /**
104: * performs a HTTP request
105: *
106: * This method overrides the request with JSON content type
107: *
108: * @param string $url the URL to target
109: * @param string $method the HTTP method to use
110: * @param array $headers key/value pairs for headers to include
111: * @param string $body the body of the request (for PUT and POST)
112: * @return \OpenCloud\HttpResponse
113: */
114: public function request(
115: $url,
116: $method = 'GET',
117: array $headers = array(),
118: $body = null
119: ) {
120: $headers['Accept'] = RAXSDK_CONTENT_TYPE_JSON;
121: $headers['Content-Type'] = RAXSDK_CONTENT_TYPE_JSON;
122: return parent::request($url, $method, $headers, $body);
123: }
124:
125: /**
126: * retrieves an asynchronous response
127: *
128: * This method calls the provided `$url` and expects an asynchronous
129: * response. It checks for various HTTP error codes and returns
130: * an `AsyncResponse` object. This object can then be used to poll
131: * for the status or to retrieve the final data as needed.
132: *
133: * @param string $url the URL of the request
134: * @param string $method the HTTP method to use
135: * @param array $headers key/value pairs for headers to include
136: * @param string $body the body of the request (for PUT and POST)
137: * @return DNS\AsyncResponse
138: */
139: public function asyncRequest($url, $method = 'GET', $headers = array(), $body = null)
140: {
141: // perform the initial request
142: $resp = $this->request($url, $method, $headers, $body);
143:
144: // @codeCoverageIgnoreStart
145: if ($resp->HttpStatus() > 204) {
146: throw new Exceptions\AsyncHttpError(sprintf(
147: Lang::translate('Unexpected HTTP status for async request: URL [%s] method [%s] status [%s] response [%s]'),
148: $url,
149: $method,
150: $resp->HttpStatus(),
151: $resp->HttpBody()
152: ));
153: }
154: // @codeCoverageIgnoreEnd
155:
156: // debug
157: $this->getLogger()->info('AsyncResponse [{body}]', array(
158: 'body' => $resp->httpBody()
159: ));
160:
161: // return an AsyncResponse object
162: return new AsyncResponse($this, $resp->httpBody());
163: }
164:
165: /**
166: * imports domain records
167: *
168: * Note that this function is called from the service (DNS) level, and
169: * not (as you might suspect) from the Domain object. Because the function
170: * return an AsyncResponse, the domain object will not actually exist
171: * until some point after the import has occurred.
172: *
173: * @api
174: * @param string $data the BIND_9 formatted data to import
175: * @return DNS\AsyncResponse
176: */
177: public function import($data)
178: {
179: // determine the URL
180: $url = $this->url('domains/import');
181:
182: $object = (object) array(
183: 'domains' => array(
184: (object) array(
185: 'contents' => $data,
186: 'contentType' => 'BIND_9'
187: )
188: )
189: );
190:
191: // encode it
192: $json = json_encode($object);
193:
194: // debug it
195: $this->getLogger()->info('Importing [{json}]', array('json' => $json));
196:
197: // perform the request
198: return $this->asyncRequest($url, 'POST', array(), $json);
199: }
200:
201: /**
202: * returns a list of limits
203: *
204: */
205: public function limits($type = null)
206: {
207: $url = $this->url('limits') . ($type ? "/$type" : '');
208: $object = $this->simpleRequest($url);
209: return ($type) ? $object : $object->limits;
210: }
211:
212: /**
213: * returns an array of limit types
214: *
215: * @return array
216: */
217: public function limitTypes()
218: {
219: $object = $this->simpleRequest($this->url('limits/types'));
220: return $object->limitTypes;
221: }
222:
223: /**
224: * Performs a simple request and returns the JSON as an object
225: *
226: * @param string $url the URL to GET
227: */
228: public function simpleRequest($url)
229: {
230: // Perform the request
231: $response = $this->request($url);
232:
233: // Check for errors
234: // @codeCoverageIgnoreStart
235: if ($response->HttpStatus() > 202) {
236: throw new Exceptions\HttpError(sprintf(
237: Lang::translate('Unexpected status [%s] for URL [%s], body [%s]'),
238: $response->HttpStatus(),
239: $url,
240: $response->HttpBody()
241: ));
242: }
243: // @codeCoverageIgnoreEnd
244:
245: // Decode the JSON
246: $json = $response->httpBody();
247: $this->getLogger()->info('Limit Types JSON [{json}]', array('json' => $json));
248:
249: $object = json_decode($json);
250:
251: $this->checkJsonError();
252:
253: return $object;
254: }
255:
256: }
257: