~openstack-charmers-next/charms/wily/hacluster/trunk

« back to all changes in this revision

Viewing changes to ocf/maas/maasclient/apidriver.py

  • Committer: James Page
  • Author(s): David Ames
  • Date: 2016-06-23 08:45:49 UTC
  • Revision ID: james.page@ubuntu.com-20160623084549-btxjk9fkzcx7ruts
DNS HA

Allow DNS be the HA resource in leiu of a VIP when using MAAS 2.0.
Added an OCF resource dns
Added maas_dns.py as the api script to update a MAAS 2.0 DNS resource
record.

Charmhelpers sync to pull in DNS HA helpers

Change-Id: I0b71feec86a77643892fadc08f2954204b541d01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2016 Canonical Ltd
 
2
#
 
3
# Licensed under the Apache License, Version 2.0 (the "License");
 
4
# you may not use this file except in compliance with the License.
 
5
# You may obtain a copy of the License at
 
6
#
 
7
#  http://www.apache.org/licenses/LICENSE-2.0
 
8
#
 
9
# Unless required by applicable law or agreed to in writing, software
 
10
# distributed under the License is distributed on an "AS IS" BASIS,
 
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
12
# See the License for the specific language governing permissions and
 
13
# limitations under the License.
 
14
 
 
15
import yaml
 
16
import logging
 
17
 
 
18
from apiclient import maas_client as maas
 
19
from .driver import MAASDriver
 
20
from .driver import Response
 
21
 
 
22
try:
 
23
    from urllib2 import HTTPError
 
24
except ImportError:
 
25
    from urllib3.exceptions import HTTPError
 
26
 
 
27
log = logging.getLogger('vmaas.main')
 
28
OK = 200
 
29
 
 
30
 
 
31
class APIDriver(MAASDriver):
 
32
    """
 
33
    A MAAS driver implementation which uses the MAAS API.
 
34
    """
 
35
 
 
36
    def __init__(self, api_url, api_key, *args, **kwargs):
 
37
        if api_url[-1] != '/':
 
38
            api_url += '/'
 
39
        if api_url.find('/api/') < 0:
 
40
            api_url = api_url + 'api/2.0/'
 
41
        super(APIDriver, self).__init__(api_url, api_key, *args, **kwargs)
 
42
        self._client = None
 
43
        self._oauth = None
 
44
 
 
45
    @property
 
46
    def client(self):
 
47
        """
 
48
        MAAS client
 
49
 
 
50
        :rtype: MAASClient
 
51
        """
 
52
        if self._client:
 
53
            return self._client
 
54
 
 
55
        self._client = maas.MAASClient(auth=self.oauth,
 
56
                                       dispatcher=maas.MAASDispatcher(),
 
57
                                       base_url=self.api_url)
 
58
        return self._client
 
59
 
 
60
    @property
 
61
    def oauth(self):
 
62
        """
 
63
        MAAS OAuth information for interacting with the MAAS API.
 
64
 
 
65
        :rtype: MAASOAuth
 
66
        """
 
67
        if self._oauth:
 
68
            return self._oauth
 
69
 
 
70
        if self.api_key:
 
71
            api_key = self.api_key.split(':')
 
72
            self._oauth = maas.MAASOAuth(consumer_key=api_key[0],
 
73
                                         resource_token=api_key[1],
 
74
                                         resource_secret=api_key[2])
 
75
            return self._oauth
 
76
        else:
 
77
            return None
 
78
 
 
79
    def validate_maas(self):
 
80
        return self._get('/')
 
81
 
 
82
    def _get(self, path, **kwargs):
 
83
        """
 
84
        Issues a GET request to the MAAS REST API, returning the data
 
85
        from the query in the python form of the json data.
 
86
        """
 
87
        response = self.client.get(path, **kwargs)
 
88
        payload = response.read()
 
89
        log.debug("Request %s results: [%s] %s", path, response.getcode(),
 
90
                  payload)
 
91
 
 
92
        if response.getcode() == OK:
 
93
            return Response(True, yaml.load(payload))
 
94
        else:
 
95
            return Response(False, payload)
 
96
 
 
97
    def _post(self, path, op='update', **kwargs):
 
98
        """
 
99
        Issues a POST request to the MAAS REST API.
 
100
        """
 
101
        try:
 
102
            response = self.client.post(path, **kwargs)
 
103
            payload = response.read()
 
104
            log.debug("Request %s results: [%s] %s", path, response.getcode(),
 
105
                      payload)
 
106
 
 
107
            if response.getcode() == OK:
 
108
                return Response(True, yaml.load(payload))
 
109
            else:
 
110
                return Response(False, payload)
 
111
        except HTTPError as e:
 
112
            log.error("Error encountered: %s for %s with params %s",
 
113
                      str(e), path, str(kwargs))
 
114
            return Response(False, None)
 
115
        except Exception as e:
 
116
            log.error("Post request raised exception: %s", e)
 
117
            return Response(False, None)
 
118
 
 
119
    def _put(self, path, **kwargs):
 
120
        """
 
121
        Issues a PUT request to the MAAS REST API.
 
122
        """
 
123
        try:
 
124
            response = self.client.put(path, **kwargs)
 
125
            payload = response.read()
 
126
            log.debug("Request %s results: [%s] %s", path, response.getcode(),
 
127
                      payload)
 
128
            if response.getcode() == OK:
 
129
                return Response(True, payload)
 
130
            else:
 
131
                return Response(False, payload)
 
132
        except HTTPError as e:
 
133
            log.error("Error encountered: %s with details: %s for %s with "
 
134
                      "params %s", e, e.read(), path, str(kwargs))
 
135
            return Response(False, None)
 
136
        except Exception as e:
 
137
            log.error("Put request raised exception: %s", e)
 
138
            return Response(False, None)
 
139
 
 
140
    ###########################################################################
 
141
    #  DNS API - http://maas.ubuntu.com/docs2.0/api.html#dnsresource
 
142
    ###########################################################################
 
143
    def get_dnsresources(self):
 
144
        """
 
145
        Get a listing of the MAAS dnsresources
 
146
 
 
147
        :returns: a list of MAAS dnsresrouce objects
 
148
        """
 
149
        return self._get('/dnsresources/')
 
150
 
 
151
    def update_dnsresource(self, rid, fqdn, ip_address):
 
152
        """
 
153
        Updates a DNS resource with a new ip_address
 
154
 
 
155
        :param rid: The dnsresource_id i.e.
 
156
                    /api/2.0/dnsresources/{dnsresource_id}/
 
157
        :param fqdn: The fqdn address to update
 
158
        :param ip_address: The ip address to update the A record to point to
 
159
        :returns: True if the DNS object was updated, False otherwise.
 
160
        """
 
161
        return self._put('/dnsresources/{}/'.format(rid), fqdn=fqdn,
 
162
                         ip_addresses=ip_address)
 
163
 
 
164
    def create_dnsresource(self, fqdn, ip_address, address_ttl=None):
 
165
        """
 
166
        Creates a new DNS resource
 
167
 
 
168
        :param fqdn: The fqdn address to update
 
169
        :param ip_address: The ip address to update the A record to point to
 
170
        :param adress_ttl: DNS time to live
 
171
        :returns: True if the DNS object was updated, False otherwise.
 
172
        """
 
173
        fqdn = bytes(fqdn, encoding='utf-8')
 
174
        ip_address = bytes(ip_address, encoding='utf-8')
 
175
        if address_ttl:
 
176
            return self._post('/dnsresources/',
 
177
                              fqdn=fqdn,
 
178
                              ip_addresses=ip_address,
 
179
                              address_ttl=address_ttl)
 
180
        else:
 
181
            return self._post('/dnsresources/',
 
182
                              fqdn=fqdn,
 
183
                              ip_addresses=ip_address)
 
184
 
 
185
    ###########################################################################
 
186
    #  IP API - http://maas.ubuntu.com/docs2.0/api.html#ip-addresses
 
187
    ###########################################################################
 
188
    def get_ipaddresses(self):
 
189
        """
 
190
        Get a dictionary of a given ip_address
 
191
 
 
192
        :param ip_address: The ip address to get information for
 
193
        :returns: a dictionary for a given ip
 
194
        """
 
195
        return self._get('/ipaddresses/')
 
196
 
 
197
    def create_ipaddress(self, ip_address, hostname=None):
 
198
        """
 
199
        Creates a new IP resource
 
200
 
 
201
        :param ip_address: The ip address to register
 
202
        :param hostname: the hostname to register at the same time
 
203
        :returns: True if the DNS object was updated, False otherwise.
 
204
        """
 
205
        if hostname:
 
206
            return self._post('/ipaddresses/', op='reserve',
 
207
                              ip_addresses=ip_address,
 
208
                              hostname=hostname)
 
209
        else:
 
210
            return self._post('/ipaddresses/', op='reserve',
 
211
                              ip_addresses=ip_address)