Пример #1
0
    def details(s):
        '''
        A collection of detailed information about all of the nodes
        in a particular nodegroup.
        '''
        center(s.__class__.__name__)

        #from client                             import MCA

        # Will probably produce a Nodes object but for now just return what comes
        # back from the rest interface.
        #
        response = s.__maas.post(u'/nodegroups/%s/' % s['uuid'], op='details')
        if not response.ok:
            if type(response.data) == str:
                cleave(s.__class__.__name__)
                raise MapiError(response.data)

        data = bson.BSON.decode(response.data)
        cdebug(json.dumps(data, sort_keys=True, indent=4))

        retval = response.data

        cleave(s.__class__.__name__)
        return retval
Пример #2
0
    def call(cls, uri, op, method, creds, data=[]):
        center('RestClient.call')
        # TODO: this is el-cheapo URI Template
        # <http://tools.ietf.org/html/rfc6570> support; use uritemplate-py
        # <https://github.com/uri-templates/uritemplate-py> here?
        #uri = self.uri.format(**vars(options))

        # Bundle things up ready to throw over the wire.
        uri, body, headers = cls.prepare_payload(op, method, uri, data)

        # Headers are returned as a list, but they must be a dict for
        # the signing machinery.
        headers = dict(headers)

        # Sign request if credentials have been provided.
        credentials = creds.split(':')
        if credentials is not None:
            cls.sign(uri, headers, credentials)

        # Use httplib2 instead of urllib2 (or MAASDispatcher, which is based
        # on urllib2) so that we get full control over HTTP method. TODO:
        # create custom MAASDispatcher to use httplib2 so that MAASClient can
        # be used.
        response, content = http_request(uri, method, body=body, headers=headers, insecure=False)

        # Compare API hashes to see if our version of the API is old.
        #self.compare_api_hashes(self.profile, response)

        # Output.
        #cdebug('response.status: %d' % response.status)
        #cls.print_debug(response)
        #cls.print_response(response, content)

        # 2xx status codes are all okay.
        if response.status // 100 != 2:
            cleave('MaiClient.call')
            if response.status == 500:
                raise MaasApiHttpInternalServerError(response.status, content)
            elif response.status == 503:
                raise MaasApiHttpServiceUnavailable(response.status, content)
            elif response.status == 400:
                raise MaasApiHttpBadRequest(response.status, content)
            elif response.status == 409:
                raise MaasApiHttpConflict(response.status, content)
            else:
                raise MaasApiUnknownError(response.status, content)

        if is_response_textual(response):
            try:
                retval = Response(True, json.loads(content))
                if Clog.dbg:
                    cdebug('content: %s' % content)
            except ValueError:
                # The content is not a json string. Just assume it's a plain string.
                #
                retval = Response(True, content)
        else:
            retval = Response(True, content)
        cleave('RestClient.call')
        return retval
Пример #3
0
    def details(s):
        '''
        A collection of detailed information about all of the nodes
        in a particular nodegroup.
        '''
        center(s.__class__.__name__)

        #from client                             import MCA

        # Will probably produce a Nodes object but for now just return what comes
        # back from the rest interface.
        #
        response = s.__maas.post(u'/nodegroups/%s/' % s['uuid'], op='details')
        if not response.ok:
            if type(response.data) == str:
                cleave(s.__class__.__name__)
                raise MapiError(response.data)

        data = bson.BSON.decode(response.data)
        cdebug(json.dumps(data, sort_keys=True, indent=4))

        retval = response.data

        cleave(s.__class__.__name__)
        return retval
Пример #4
0
 def __init__(s, url, creds):
     center(s.__class__.__name__)
     cdebug('      url: %s' % url)
     cdebug('    creds: %s' % creds)
     s.root  = url
     s.creds = creds
     cleave(s.__class__.__name__)
Пример #5
0
 def __init__(s, url, creds):
     center(s.__class__.__name__)
     cdebug('      url: %s' % url)
     cdebug('    creds: %s' % creds)
     s.root = url
     s.creds = creds
     cleave(s.__class__.__name__)
Пример #6
0
    def __init__(s, maas, group):
        center('Nodegroup.__init__')
        s.__maas   = maas
        cdebug('group: %s' % group)

        dict.__init__(s, group)

        cleave('Nodegroup.__init__')
Пример #7
0
def is_response_textual(response):
    """Is the response body text?"""
    center('api.is_response_textual')
    content_type = get_response_content_type(response)
    cdebug('content_type: %s' % content_type)
    retval = (content_type.endswith("/json") or content_type.startswith("text/"))
    cleave('api.is_response_textual (%s)' % retval)
    return retval
Пример #8
0
    def __init__(s, maas, group):
        center('Nodegroup.__init__')
        s.__maas = maas
        cdebug('group: %s' % group)

        dict.__init__(s, group)

        cleave('Nodegroup.__init__')
Пример #9
0
def is_response_textual(response):
    """Is the response body text?"""
    center('api.is_response_textual')
    content_type = get_response_content_type(response)
    cdebug('content_type: %s' % content_type)
    retval = (content_type.endswith("/json")
              or content_type.startswith("text/"))
    cleave('api.is_response_textual (%s)' % retval)
    return retval
Пример #10
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__boot_images is None:
            response = s.__maas.get(u'/nodegroups/%s/boot-images/' % s.__uuid)
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__boot_images = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #11
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__zones is None:
            response = s.__maas.get(u'/zones/')
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__zones = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #12
0
    def __fetch_if_needed(s):
        center('Interfaces.__fetch_if_needed')
        if s.__interfaces is None:
            response = s.__maas.get(u'/nodegroups/%s/interfaces/' % s.__uuid, op='list')
            if not response.ok:
                if type(response.data) == str:
                    cleave('Interfaces.__fetch_if_needed')
                    raise MapiError(response.data)

            s.__interfaces = response.data
            cdebug('    fetched')
        cleave('Interfaces.__fetch_if_needed')
Пример #13
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__groups is None:
            response = s.__maas.get(u'/nodes/%s/volume-groups/' % s.__system_id)
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__groups = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #14
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__resources is None:
            response = s.__maas.get(u'/boot-sources/')
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__resources = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #15
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__nodegroups is None:
            response = s.__maas.get(u'/nodegroups/', op='list')
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__nodegroups = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #16
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__keys is None:
            response = s.__maas.get(u'/account/prefs/sslkeys/', op='list')
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__keys = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #17
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__power_types is None:
            response = s.__maas.get(u'/nodegroups/', op='describe_power_types')
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__power_types = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #18
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__groups is None:
            response = s.__maas.get(u'/nodes/%s/volume-groups/' %
                                    s.__system_id)
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__groups = response.data
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #19
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__events is None:
            response = s.__maas.get(u'/events/', op='query')
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__prev_uri = response.data['prev_uri']
            s.__next_uri = response.data['next_uri']
            s.__count  = response.data['count']
            s.__events = response.data['events']
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #20
0
    def __fetch_if_needed(s):
        center(s.__class__.__name__)
        if s.__events is None:
            response = s.__maas.get(u'/events/', op='query')
            if not response.ok:
                if type(response.data) == str:
                    cleave(s.__class__.__name__)
                    raise MapiError(response.data)

            s.__prev_uri = response.data['prev_uri']
            s.__next_uri = response.data['next_uri']
            s.__count = response.data['count']
            s.__events = response.data['events']
            cdebug('    fetched')
        cleave(s.__class__.__name__)
Пример #21
0
def http_request(url, method, body=None, headers=None, insecure=False):
    """Issue an http request."""
    center('api.http_request')
    cdebug('         url: %s' % url)
    cdebug('      method: %s' % method)
    cdebug('        body: %s' % body)
    cdebug('     headers: %s' % headers)
    cdebug('    insecure: %s' % insecure)
    http = httplib2.Http(disable_ssl_certificate_validation=insecure)
    try:
        cleave('api.http_request')
        return http.request(url, method, body=body, headers=headers)
    except httplib2.SSLHandshakeError:
        cleave('api.http_request')
        raise MaasApiCertificateVerificationError(
            0, "Certificate verification failed, use --insecure/-k to "
            "disable the certificate check.")
Пример #22
0
def http_request(url, method, body=None, headers=None,
                 insecure=False):
    """Issue an http request."""
    center('api.http_request')
    cdebug('         url: %s' % url)
    cdebug('      method: %s' % method)
    cdebug('        body: %s' % body)
    cdebug('     headers: %s' % headers)
    cdebug('    insecure: %s' % insecure)
    http = httplib2.Http(disable_ssl_certificate_validation=insecure)
    try:
        cleave('api.http_request')
        return http.request(url, method, body=body, headers=headers)
    except httplib2.SSLHandshakeError:
        cleave('api.http_request')
        raise MaasApiCertificateVerificationError(0,
            "Certificate verification failed, use --insecure/-k to "
            "disable the certificate check.")
Пример #23
0
 def __init__(s, url, creds):
     center(s.__class__.__name__)
     cdebug('      url: %s' % url)
     cdebug('    creds: %s' % creds)
     super(MapiClient, s).__init__(url, creds)
     cleave(s.__class__.__name__)
Пример #24
0
    def prepare_payload(cls, op, method, uri, data):
        """Return the URI (modified perhaps) and body and headers.

        - For GET requests, encode parameters in the query string.

        - Otherwise always encode parameters in the request body.

        - Except op; this can always go in the query string.

        :param method: The HTTP method.
        :param uri: The URI of the action.
        :param data: An iterable of ``name, value`` or ``name, opener``
            tuples (see `name_value_pair`) to pack into the body or
            query, depending on the type of request.
        """
        center('RestClient.prepare_payload')
        cdebug('    op : %s' % op)
        cdebug('method : %s' % method)
        cdebug('   uri : %s' % uri)
        cdebug('  data : %s' % data)
        query = [] if op is None else [("op", op)]

        def slurp(opener):
            with opener() as fd:
                return fd.read()

        if method == "GET":
            query.extend((name, slurp(value) if callable(value) else value)
                         for name, value in data)
            body, headers = None, []
        else:
            if data is None or len(data) == 0:
                body, headers = None, []
            else:
                cdebug('encode multipart')
                message = build_multipart_message(data)
                headers, body = encode_multipart_message(message)

        uri = urlparse(uri)._replace(query=urlencode(query)).geturl()
        cleave('RestClient.prepare_payload')
        cdebug('    uri : %s' % uri)
        cdebug('   body : %s' % body)
        cdebug('headers : %s' % headers)
        return uri, body, headers
Пример #25
0
    def call(cls, uri, op, method, creds, data=[]):
        center('RestClient.call')
        # TODO: this is el-cheapo URI Template
        # <http://tools.ietf.org/html/rfc6570> support; use uritemplate-py
        # <https://github.com/uri-templates/uritemplate-py> here?
        #uri = self.uri.format(**vars(options))

        # Bundle things up ready to throw over the wire.
        uri, body, headers = cls.prepare_payload(op, method, uri, data)

        # Headers are returned as a list, but they must be a dict for
        # the signing machinery.
        headers = dict(headers)

        # Sign request if credentials have been provided.
        credentials = creds.split(':')
        if credentials is not None:
            cls.sign(uri, headers, credentials)

        # Use httplib2 instead of urllib2 (or MAASDispatcher, which is based
        # on urllib2) so that we get full control over HTTP method. TODO:
        # create custom MAASDispatcher to use httplib2 so that MAASClient can
        # be used.
        response, content = http_request(uri,
                                         method,
                                         body=body,
                                         headers=headers,
                                         insecure=False)

        # Compare API hashes to see if our version of the API is old.
        #self.compare_api_hashes(self.profile, response)

        # Output.
        #cdebug('response.status: %d' % response.status)
        #cls.print_debug(response)
        #cls.print_response(response, content)

        # 2xx status codes are all okay.
        if response.status // 100 != 2:
            cleave('MaiClient.call')
            if response.status == 500:
                raise MaasApiHttpInternalServerError(response.status, content)
            elif response.status == 503:
                raise MaasApiHttpServiceUnavailable(response.status, content)
            elif response.status == 400:
                raise MaasApiHttpBadRequest(response.status, content)
            elif response.status == 409:
                raise MaasApiHttpConflict(response.status, content)
            else:
                raise MaasApiUnknownError(response.status, content)

        if is_response_textual(response):
            try:
                retval = Response(True, json.loads(content))
                if Clog.dbg:
                    cdebug('content: %s' % content)
            except ValueError:
                # The content is not a json string. Just assume it's a plain string.
                #
                retval = Response(True, content)
        else:
            retval = Response(True, content)
        cleave('RestClient.call')
        return retval
Пример #26
0
    def prepare_payload(cls, op, method, uri, data):
        """Return the URI (modified perhaps) and body and headers.

        - For GET requests, encode parameters in the query string.

        - Otherwise always encode parameters in the request body.

        - Except op; this can always go in the query string.

        :param method: The HTTP method.
        :param uri: The URI of the action.
        :param data: An iterable of ``name, value`` or ``name, opener``
            tuples (see `name_value_pair`) to pack into the body or
            query, depending on the type of request.
        """
        center('RestClient.prepare_payload')
        cdebug('    op : %s' % op)
        cdebug('method : %s' % method)
        cdebug('   uri : %s' % uri)
        cdebug('  data : %s' % data)
        query = [] if op is None else [("op", op)]

        def slurp(opener):
            with opener() as fd:
                return fd.read()

        if method == "GET":
            query.extend(
                (name, slurp(value) if callable(value) else value)
                for name, value in data)
            body, headers = None, []
        else:
            if data is None or len(data) == 0:
                body, headers = None, []
            else:
                cdebug('encode multipart')
                message = build_multipart_message(data)
                headers, body = encode_multipart_message(message)

        uri = urlparse(uri)._replace(query=urlencode(query)).geturl()
        cleave('RestClient.prepare_payload')
        cdebug('    uri : %s' % uri)
        cdebug('   body : %s' % body)
        cdebug('headers : %s' % headers)
        return uri, body, headers
Пример #27
0
    def dump(s, d=None, title=None, key=None, more=False):
        if d is None:
            d = dict(s)

        if title:
            cdebug(title)
            cdebug('-------------------------------------------------------------------------------------------')
        if type(d) == dict:
            if key is not None:
                cdebug('%s : {' % key)
            else:
                cdebug('{')
            for k in d:
                if type(d[k]) == dict or type(d[k]) == list:
                    Clog.indent += 4
                    s.dump(d[k], key=k, more=True)
                    Clog.indent -= 4
                else:
                    cdebug('    %s : %s,' % (k, d[k]))
            if more:
                cdebug('},')
            else:
                cdebug('}')
        elif type(d) == list:
            if key is not None:
                cdebug('%s : [' % key)
            else:
                cdebug('[')
            for k in d:

                if type(k) == dict :
                    Clog.indent += 4
                    s.dump(k, more=True)
                    Clog.indent -= 4
                elif type(k) == list:
                    Clog.indent += 4
                    s.dump(k, key=k, more=True)
                    Clog.indent -= 4
                else:
                    cdebug('    %s,' % (k))

            if more:
                cdebug('],')
            else:
                cdebug(']')
        else:
            cdebug('    %s,' % (d))
Пример #28
0
 def __init__(s, url, creds):
     center(s.__class__.__name__)
     cdebug('      url: %s' % url)
     cdebug('    creds: %s' % creds)
     super(MapiClient, s).__init__(url, creds)
     cleave(s.__class__.__name__)
Пример #29
0
    def dump(s, d=None, title=None, key=None, more=False):
        if d is None:
            d = dict(s)

        if title:
            cdebug(title)
            cdebug(
                '-------------------------------------------------------------------------------------------'
            )
        if type(d) == dict:
            if key is not None:
                cdebug('%s : {' % key)
            else:
                cdebug('{')
            for k in d:
                if type(d[k]) == dict or type(d[k]) == list:
                    Clog.indent += 4
                    s.dump(d[k], key=k, more=True)
                    Clog.indent -= 4
                else:
                    cdebug('    %s : %s,' % (k, d[k]))
            if more:
                cdebug('},')
            else:
                cdebug('}')
        elif type(d) == list:
            if key is not None:
                cdebug('%s : [' % key)
            else:
                cdebug('[')
            for k in d:

                if type(k) == dict:
                    Clog.indent += 4
                    s.dump(k, more=True)
                    Clog.indent -= 4
                elif type(k) == list:
                    Clog.indent += 4
                    s.dump(k, key=k, more=True)
                    Clog.indent -= 4
                else:
                    cdebug('    %s,' % (k))

            if more:
                cdebug('],')
            else:
                cdebug(']')
        else:
            cdebug('    %s,' % (d))